脱离实体类操作数据库(mysql版本)
原理很简单:
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版本)的更多相关文章
- PDF.NET数据开发框架实体类操作实例
PDF.NET数据开发框架实体类操作实例(MySQL)的姊妹篇,两者使用了同一个测试程序,不同的只是使用的类库和数据库不同,下面说说具体的使用过程. 1,首先在App.config文件中配置数据库连接 ...
- 解决mybatis实体类和数据库列名不匹配的两种办法
我们在实际开发中,会遇到实体类与数据库类不匹配的情况,在开发中就会产生各种各样的错误,那么我们应该怎么去解决这一类的错误呢?很简单,下面我们介绍两种解决方法: 首先我们看一下数据库和实体类不匹配的情况 ...
- ASP.NET Core EFCore 之DBFirst 自动创建实体类和数据库上下文
通过引用Nuget包添加实体类 运行 Install-Package Microsoft.EntityFrameworkCore.SqlServer 运行 Install-Package Micros ...
- 在Code First中使用Migrations对实体类和数据库做出变更
在Code First中使用Migrations对实体类和数据库做出变更,Mirgration包含一系列命令. 工具--库程序包管理器--程序包管理器控制台 运行命令:Enable-Migration ...
- ef-codefirst方式配置实体类,生成数据库
做项目的时候,如果我们如果用orm方式来做数据库持久化操作的话.微软官方首先会向我们推荐ef,而我们用ado.net的话,似乎也需要建立实体类来接传值,那么我们用codefirst就有一举两得的效果了 ...
- php 通过mysqli 操作数据库mysql
目录 php mysqli 操作数据库 连接数据库 通过mysqli 创建数据库 通过mysqi 创建数据表 通过mysqli向数据表中插入信息 通过mysqli 读取数据 where语句的应用 通过 ...
- YbSoftwareFactory 代码生成插件【十九】:实体类配合数据库表字段进行属性扩展的小技巧
实体类通常需要和数据库表进行了ORM映射,当你需要添加新的属性时,往往同时也需要在数据库中添加相应的字段并配置好映射关系,同时可能还需对数据访问组件进行重新编译和部署才能有效.而当你开始设计一个通用数 ...
- 就这么 来ADO.net类操作数据库
使用ADO.net操作数据库其实也是很简单,而且使用频率蛮高的一种方式.话不多说,上代码才更容易理解. 首先,先要引入数据库操作相关的命名空间,这样才能使用下面的代码 //数据库连接引用的命名空间 u ...
- MyBatis入门实例-包括实体类与数据库字段对应&CLOB字段处理
1.我的开发环境是 jdk1.7+ecplise+oracle 11g 用到的jar包:mybatis-3.1.1.jar ojdbc6.jar 2.项目整体结构 3.首先配置conf.xml ...
- 6-2 python 操作数据库mysql
1.python操作MySQL的 查询(select操作) 步骤 import pymysql # 1.建立数据库连接 conn = pymysql.connect(host='118.24.3.40 ...
随机推荐
- rce临时文件上传[RCE1]P8
rce临时文件上传[RCE1]P8 /[A-Za-z0-9!~^|&]+/i 匹配了我能想到的所有绕过方法,想到临时文件上传,是否可以执行/tmp/?????????这个文件呢 /tmp/?? ...
- 5.Kubeadm和二进制方式对比
Kubeadm方式搭建K8S集群 安装虚拟机,在虚拟机安装Linux操作系统[3台虚拟机] 对操作系统初始化操作 所有节点安装Docker.kubeadm.kubelet.kubectl[包含mast ...
- vue-amap接入高德地图示例
通过 CDN 的方式我们可以很容易地使用 vue-amap 写出一个 Hello world 页面. 什么是CDN? 定义是这样的:CDN是构建在网络之上的内容分发网络,依靠部署在各地的边缘服务器,通 ...
- P4119 Ynoi2018 未来日记
P4119 Ynoi2018 未来日记 lxl 出的题好 duliu 啊. 感谢来自 fr200110217102 的博客 题解 P4119 [Ynoi2018未来日记]. 下标分块+值域分块+并查集 ...
- .NET周刊【11月第3期 2024-11-17】
国内文章 .NET 9使用Scalar替代Swagger https://www.cnblogs.com/netry/p/18543378/scalar-an-alternative-to-swagg ...
- Spring3.0核心组件的源码简单分析
前言 本文结合Spring3.0的源码进行简单的介绍,这里的核心组件不是我们常见所谓的IOC和AOP,而是以Spring3.0发布的开发包为切入点,当然Spring3.0以后的各个版本基本上差不多,思 ...
- 压缩工具之upx
在golang项目中, 最终运行的是打包好的二进制文件,如何才能让这个文件尽可能的小呢? 1.编译阶段的参数处理 go build使用的是静态编译,会将程序的依赖一起打包,这样一来编译得到的可执行文件 ...
- 基于python的文件监控watchdog
实时监控第三方库watchdog,其原理通过操作系统的时间触发的,不需要循环和等待 使用场景: 1.监控文件系统中文件或目录的增删改情况 2.当特定的文件被创建,删除,修改,移动时执行相应的任务 1. ...
- Go Vue3 CMS管理后台(前后端分离模式)
本后台使用前后端分离模式开发,前端UI为Vue3+Ant Design Vue,后端Api为Go+Gin,解耦前后端逻辑,使开发更专注 技术栈 前端:Vue3,Ant Design Vue,Axios ...
- The 2023 ICPC Asia Hong Kong Regional Programming Contest
The 2023 ICPC Asia Hong Kong Regional Programming Contest A. TreeScript 给你一个根,让你构造一棵树,每个节点被创造的时候必须知道 ...