脱离实体类操作数据库(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 ...
随机推荐
- 【转载】 TensorFlow中CNN的两种padding方式“SAME”和“VALID”
原文地址: http://blog.csdn.net/wuzqchom/article/details/74785643 --------------------------------------- ...
- Socket编程与IO多路复用
0.引言 本篇博客将从socket模型为起点,引入IO多路复用的学习. 1.Socket模型 1.1.Socket的诞生 Socket的诞生背景: Socket最早出现在20实际80年代的Unix操作 ...
- git 拉取或者推送代码报错问题解决
报错截图: 当推送远程时,提示无法访问github地址 原因:在拉取或者是提交项目时,会发生git的http和https代理,我们电脑本地已经存在SSL协议的协议,可以取消http和https代理 在 ...
- 一个基于 .NET 8.0 构建的简单、跨平台、模块化商城系统
前言 今天给大家分享一个基于 .NET 8.0 构建的开源免费(MIT License).简单.跨平台.模块化的商城系统:Module Shop. 主要功能 销售:订单.物流. 内容:首页配置.评论. ...
- 服务器cli模式下的定时器
有时候需要一部分后台业务异步的处理,比如处理redis队列啊,处理mysql统计啊,数据同步啊,这种长时间任务,但是又需要每段时间去看看的,发现linux cron最小只能支持每分钟的任务 分 时 天 ...
- Educational Codeforces Round 105 (Rated for Div
Educational Codeforces Round 105 (Rated for Div. 2) ABC String 给定一个字符串只有A.B和C构成.要求替换A.B.C为')'和'(',并且 ...
- VLC web(http)控制 (3) 播放控制
VLC web(http) 播放控制: 1.如果已经在打开视频 播放和暂停都是:http://127.0.0.1:8080/requests/status.xml?command=pl_pause ...
- 数据库开发规范v1.0
一.建表规约 [强制]表达是与否概念的字段,必须使用 is_xxx 的方式命名,数据类型是 unsigned tinyint( 1 表示是,0 表示否). 说明:任何字段如果为非负数,必须是 unsi ...
- simpleui
目录 一.simpleui 1.1 使用步骤 1.2 功能介绍 1.3 展示大屏 一.simpleui 之前公司里,做项目前后端结合,要使用权限,要快速搭建后台管理,使用djagno的admin直接搭 ...
- 关于 K8s 的一些基础概念整理-补充【k8s系列之五】
〇.前言 本文继续整理下 K8s 的一些基础概念,作为前一篇概念汇总的补充. 前一篇博文链接:https://www.cnblogs.com/hnzhengfy/p/k8s_concept.html. ...