原理很简单:
1、利用mysql的information_schema库,获取对用表的信息;

2、使用DataSource,建立数据库连接,并执行sql脚本;

3、Map的keySet和values集合是顺序一致的;

4、" on duplicate key update "这里摸了个鱼,将新增和修改整合在一起了;

直接上代码:

package com.modern.client.core;

import cn.hutool.core.map.MapBuilder;
import cn.hutool.core.map.MapUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Lists;
import lombok.SneakyThrows;
import org.springframework.util.Assert; import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.*;
import java.util.stream.Collectors; /**
* 数据库脱离实体操作助手
*/
public class MybatisHelper { /**
* 获取所有列
*
* @param ds
* @param tableName
* @return
*/
@SneakyThrows
private static List<String> tableColumns(DataSource ds, String tableName) {
Connection connection = ds.getConnection();
try {
ResultSet set = connection.prepareCall("select column_name from information_schema.`COLUMNS` where table_name = '" + tableName + "'").executeQuery();
ArrayList<String> list = Lists.newArrayList();
while (set.next()) {
list.add(set.getString(1));
}
return list;
} finally {
connection.close();
}
} /**
* 获取主键
*
* @param ds
* @param tableName
* @return
*/
@SneakyThrows
private static String tablePrimarykey(DataSource ds, String tableName) {
Connection connection = ds.getConnection();
try {
ResultSet set = connection.prepareCall("select column_name from information_schema.`COLUMNS` where table_name = '" + tableName + "' and COLUMN_key = 'PRI'").executeQuery();
Assert.isTrue(set.next(),"表"+tableName+"未找到主键!");
return set.getString(1);
} finally {
connection.close();
}
} @SneakyThrows
private static void callSql(DataSource ds, String sql) {
Connection connection = ds.getConnection();
try {
connection.prepareCall(sql).execute();
} finally {
connection.close();
}
} /**
* 删除
*
* @param ds
* @param tableName
* @param jsonStr
* @throws SQLException
*/
public static void delete(DataSource ds, String tableName, String jsonStr) throws SQLException {
String primarykey = tablePrimarykey(ds, tableName);
Assert.notNull(primarykey, "表" + tableName + "无主键,执行删除失败!");
String value = null;
JSONObject object = JSON.parseObject(jsonStr);
for (Map.Entry<String, Object> entry : object.entrySet()) {
if (entry.getKey().equalsIgnoreCase(primarykey.replaceAll("_", ""))) {
value = entry.getValue().toString();
break;
}
}
Assert.notNull(value, "表" + tableName + "无主键 值,执行删除失败!");
StringBuilder builder = new StringBuilder();
builder.append(" delete from ");
builder.append(tableName);
builder.append(" where ");
builder.append(primarykey);
builder.append(" = ");
builder.append("'");
builder.append(value);
builder.append("'");
callSql(ds, builder.toString());
} /**
* 新增或修改
*
* @param ds
* @param tableName
* @param jsonStr
*/
public static void insertOrUpdate(DataSource ds, String tableName, String jsonStr) {
List<String> columns = tableColumns(ds, tableName);
JSONObject object = JSON.parseObject(jsonStr);
MapBuilder<Object, Object> mapBuilder = MapUtil.builder();
for (Map.Entry<String, Object> entry : object.entrySet()) {
List<String> res = columns.stream().filter(p -> entry.getKey().equalsIgnoreCase(p.replaceAll("_", ""))).collect(Collectors.toList());
if (res.size() <= 0) continue;
mapBuilder.put(res.get(0), entry.getValue());
}
Map<Object, Object> map = mapBuilder.build();
StringBuilder builder = new StringBuilder();
//insert
builder.append(" insert into ");
builder.append(tableName);
builder.append(keyBunch(map.keySet()));
builder.append(" values ");
builder.append(valueBunch(map.values()));
//update
builder.append(updateBunch(map.keySet()));
callSql(ds, builder.toString());
} /**
* insertOrUpdate 分支
* @param c
* @return
*/
private static String keyBunch(Collection<?> c) {
StringBuilder builder = new StringBuilder("(");
Iterator<?> iterator = c.iterator();
while (iterator.hasNext()) {
builder.append(iterator.next());
if(iterator.hasNext()) builder.append(",");
}
builder.append(")");
return builder.toString();
} /**
* insertOrUpdate 分支
* @param c
* @return
*/
private static String valueBunch(Collection<?> c) {
StringBuilder builder = new StringBuilder("(");
Iterator<?> iterator = c.iterator();
while (iterator.hasNext()) {
builder.append("'");
builder.append(iterator.next().toString());
builder.append("'");
if(iterator.hasNext()) builder.append(",");
}
builder.append(")");
return builder.toString();
} /**
* insertOrUpdate 分支
* @param c
* @return
*/
private static String updateBunch(Collection<?> c) {
StringBuilder builder = new StringBuilder(" on duplicate key update ");
Iterator<?> iterator = c.iterator();
while (iterator.hasNext()) {
Object next = iterator.next();
builder.append(next);
builder.append(" =values( ");
builder.append(next);
builder.append(")");
if(iterator.hasNext()) builder.append(",");
}
return builder.toString();
}
public static void main(String[] args) {
Map<String, String> map = MapUtil.builder(new HashMap<String,String>())
.put("id", "1")
.put("organization_id", "9")
.put("c", "9")
.put("d", "9")
.put("x", "2024-01-01").build();
StringBuilder builder = new StringBuilder();
//insert
builder.append(" insert into ");
builder.append("aaaa");
builder.append(keyBunch(map.keySet()));
builder.append(" values ");
builder.append(valueBunch(map.values()));
//update
builder.append(updateBunch(map.keySet()));
System.out.println("args = " + builder.toString());
}
}

最后拼接效果:

INSERT INTO aaaa ( c, d, organization_id, x, id )
VALUES
( '9', '9', '9', '2024-01-01', '1' )
ON DUPLICATE KEY UPDATE c =
VALUES
( c ),
d =
VALUES
( d ),
organization_id =
VALUES
( organization_id ),
x =
VALUES
( x ),
id =
VALUES
(
id
)

脱离实体类操作数据库(mysql版本)的更多相关文章

  1. PDF.NET数据开发框架实体类操作实例

    PDF.NET数据开发框架实体类操作实例(MySQL)的姊妹篇,两者使用了同一个测试程序,不同的只是使用的类库和数据库不同,下面说说具体的使用过程. 1,首先在App.config文件中配置数据库连接 ...

  2. 解决mybatis实体类和数据库列名不匹配的两种办法

    我们在实际开发中,会遇到实体类与数据库类不匹配的情况,在开发中就会产生各种各样的错误,那么我们应该怎么去解决这一类的错误呢?很简单,下面我们介绍两种解决方法: 首先我们看一下数据库和实体类不匹配的情况 ...

  3. ASP.NET Core EFCore 之DBFirst 自动创建实体类和数据库上下文

    通过引用Nuget包添加实体类 运行 Install-Package Microsoft.EntityFrameworkCore.SqlServer 运行 Install-Package Micros ...

  4. 在Code First中使用Migrations对实体类和数据库做出变更

    在Code First中使用Migrations对实体类和数据库做出变更,Mirgration包含一系列命令. 工具--库程序包管理器--程序包管理器控制台 运行命令:Enable-Migration ...

  5. ef-codefirst方式配置实体类,生成数据库

    做项目的时候,如果我们如果用orm方式来做数据库持久化操作的话.微软官方首先会向我们推荐ef,而我们用ado.net的话,似乎也需要建立实体类来接传值,那么我们用codefirst就有一举两得的效果了 ...

  6. php 通过mysqli 操作数据库mysql

    目录 php mysqli 操作数据库 连接数据库 通过mysqli 创建数据库 通过mysqi 创建数据表 通过mysqli向数据表中插入信息 通过mysqli 读取数据 where语句的应用 通过 ...

  7. YbSoftwareFactory 代码生成插件【十九】:实体类配合数据库表字段进行属性扩展的小技巧

    实体类通常需要和数据库表进行了ORM映射,当你需要添加新的属性时,往往同时也需要在数据库中添加相应的字段并配置好映射关系,同时可能还需对数据访问组件进行重新编译和部署才能有效.而当你开始设计一个通用数 ...

  8. 就这么 来ADO.net类操作数据库

    使用ADO.net操作数据库其实也是很简单,而且使用频率蛮高的一种方式.话不多说,上代码才更容易理解. 首先,先要引入数据库操作相关的命名空间,这样才能使用下面的代码 //数据库连接引用的命名空间 u ...

  9. MyBatis入门实例-包括实体类与数据库字段对应&CLOB字段处理

    1.我的开发环境是 jdk1.7+ecplise+oracle 11g 用到的jar包:mybatis-3.1.1.jar ojdbc6.jar 2.项目整体结构     3.首先配置conf.xml ...

  10. 6-2 python 操作数据库mysql

    1.python操作MySQL的 查询(select操作) 步骤 import pymysql # 1.建立数据库连接 conn = pymysql.connect(host='118.24.3.40 ...

随机推荐

  1. 定制jekins-slave-jnlp镜像封装docker和kebectl命令实现pipline

    基于官方:jenkins/inbound-agent:latest DockerHub成品: docker pull svipghy/jenkins-jnlp-slave:v1 Dockerfile ...

  2. JAVA 两个时间 相差的 小时,天数,分钟

    long nd = 1000 * 24 * 60 * 60; //每天毫秒数 long nh = 1000 * 60 * 60; //每小时毫秒数 long nm = 1000 * 60; //每分钟 ...

  3. Air780E如何发送SMS?一文详解!

    ​ 今天一起来学习使用合宙低功耗4G模组Air780E发送SMS短消息: 一.SMS简介 SMS(短消息服务,ShortMessageService)功能主要用于在蜂窝网络中传输短消息. 在4G网络中 ...

  4. OSG开发笔记(三十二):深入理解相机视口、制作支持与主视图同步变换旋转的相机HUD

    前言   深入理解相机视口,摸索相机视口旋转功能,背景透明或者不透明.  本篇,实现了一个左下角旋转HUD且背景透明的相机视口.   Demo                  HUD相机的坐标    ...

  5. uni app下开发AI运动小程序解决方案

    一.引言 近年来,随着AI视频识别技术的飞速发展,市场上涌现出了众多基于视觉识别的AI运动APP.这些APP凭借AI视觉识别技术的强大能力,让用户只需面对摄像头进行运动锻炼,就能享受到智能计时.精准计 ...

  6. 70 个群都来问我的 AI 日报,是这么做的。

    最近我给 FastGPT 用户交流群里接入了 AI 日报,每天早上 10 点会自动向群里推送 AI 日报,让群里的小伙伴们第一时间了解到昨天 AI 领域都发生了哪些大事. 效果大概是这个样子的: 如果 ...

  7. Element UI 表格排序所有页

    Element UI 表格排序只排了当前页,解决方案如下: 定义方法: /** 比较 * @param {string} propertyName 属性值 * @param {string} sort ...

  8. Spring源码学习 ------ IoC——AOP

    一直想抽空把Spring源码拿来读读,但真正去做这件事的时候发现不简单,Spring发展这么多年,它的规模已不是一个一般的开源框架所能比的,它的主要架构和流程不是非常清晰,很难抓到要害,但有一点可以肯 ...

  9. Web实时消息推送的解决方案

    什么是消息推送(push) 推送的场景比较多,比如有人关注我的公众号,这时我就会收到一条推送消息,以此来吸引我点击打开应用. 消息推送(push)通常是指网站的运营工作等人员,通过某种工具对用户当前网 ...

  10. Yii2 中配置方法汇总

    1.默认框架接收的是x-www-format-unencode格式的数据,如果想要接收text/json格式的数据,会为空,这个时候需要在配置文件中添加对应的配置项 config > main. ...