原理很简单:
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. Lattice、Xilinx FPGA reg初始化赋值问题

    一.起因 最近在开发Lattice的一款低功耗FPGA时,遇到了reg初始化复位问题,经过在网上搜寻相关资料整理如下: 二.FPGA中reg的初始化方式 在定义时初始化,例如: reg r_test ...

  2. 基于Java+SpringBoot+Mysql实现的古诗词平台功能设计与实现四

    一.前言介绍: 1.1 项目摘要 随着信息技术的迅猛发展和数字化时代的到来,传统文化与现代科技的融合已成为一种趋势.古诗词作为中华民族的文化瑰宝,具有深厚的历史底蕴和独特的艺术魅力.然而,在现代社会中 ...

  3. 一个专注推荐.Net开源项目的榜单

    大家好,我是编程乐趣,从7月份开始推荐开源项目,已经推荐了接近100个开源项目了,其中绝大部分是有关.Net的开源项目,也受到大家非常多人的喜欢. 由于公众号不方便查询,很多人又想了解更多的开源项目, ...

  4. python之gevent

    gevent 是一个基于协程的 Python 网络库,它使用 Greenlet 库提供了一种高效的协程实现. 协程是一种轻量级的线程,允许并发执行,但没有真正的并行性.协程可 以在遇到 I/O 操作时 ...

  5. java/spring项目打成jar包供第三方引用方案

    分类 单独工具类 比如StringUtils 注入类工具类 实现 单独工具类 将项目打jar包 项目结构 开始打包: 在目标项目中pom引用直接使用 注入类工具类 当我们想要利用SpringBoot封 ...

  6. 一文聊清楚Redis主从复制原理

    本地缓存带来的挑战 分布式缓存相比于本地缓存,在实现层面需要关注的点有哪些不同.梳理如下: 维度 本地缓存 集中式缓存 缓存量 受限于单机内存大小,存储数据有限 需要提供给分布式系统里面所有节点共同使 ...

  7. 使用IDEA一键发布应用

    1.编辑Dockerfile from java:8 WORKDIR /usr/local ADD ./target/jpaas-bpm.jar . CMD ["java",&qu ...

  8. Visual Studio 使用IISprofile进行远程部署

      ​

  9. 记ios的input框获取焦点之后界面放大问题

    在移动端开发项目中,发现页面在使用 iPhone 访问的时候,点击 input 和 textarea 等文本输入框聚焦 focus() 时,页面会整体放大,而且失去焦点之后页面不能返回原来的样子.检查 ...

  10. 前端跨平台调试代理神器Whistle

    概述 抓包一直是平时开发中经常要做的,有一款好用的抓包工具可以让开发体验更棒,以前一直用fiddler,fiddler虽然强悍,但是入手有一定难度,而且较笨重,今天介绍另一款抓包工具:Whistle. ...