MyBatis 常用工具类
SQL 类
MyBatis 提供了一个 SQL 工具类,使用这个工具类,我们可以很方便在 Java 代码动态构建 SQL 语句
String newSql = new SQL() ({
SELECT("P.ID, P.USERNAME, P.PASSWORD, P.FULL NAME");
SELECT("P.LAST NAME, P.CREATED ON, P.UPDATED ON");
FROM("PERSON P");
FROM("ACCOUNT A");
INNER JOIN("DEPARTMENT D ON DID=P.DEPARTMENT ID");
INNER JOIN("COMPANY C On D.COMPANY ID=C.ID");
WHERE("P.ID = A.ID");
WHERE("P.FIRST NAME like ?");
OR();
WHERE("P.LAST NAME like ?");
GROUP BY("P.ID");
HAVING("P.LAST_NAME like ?");
OR();
HAVING("P.FIRST NAME like ?");
ORDER BY("P.ID");
ORDER BY("P.FULL NAME");
}}.tostring();
如上面的代码所示,创建了一个匿名的 SQL 类的子类,在匿名子类的初始化代码块中,调用 SELECT()、FROM() 等方法构建 SQL 语句,这种方式能够很好地避免字符串拼接过程中缺少空格或者偶然间重复出现的 AND 关键字导致的 SOL 语句不正确
除了 SELECT 语句外,SQL 工具类也可以用作构建 UPDATE、INSERT 等语句
@Test
public void testInsertSql() {
String insertSql = new SQL().
INSERT INTO("PERSON").
VALUES("ID, FIRST NAME","#{id}, #{firstName}").
VALUES("LAST NAME","#(lastName}").toString();
System.out.println(insertSal);
}
@Test
public void testDeleteSql() {
String deleteSql= new SQL() {{
DELETE FROM("PERSON");
WHERE("ID = #{id)");
}}.toString();
System.out.println(deleteql);
}
@Test
public void testUpdateSql() {
String updateSql= new SQL() {{
UPDATE("PERSON");
SET("FIRST NAME = #{firstName}");
WHERE("ID = #{id}");
}}.toString();
System.out.println(updateSql);
}
使用 SQL 工具类的另一个好处是可以很方便地在 Java 代码中根据条件动态地拼接 SQL 语句
public String selectPerson(final String id, final String firstName, final String lastName) {
return new SQL() {{
SELECT("P.ID, P.USERNAME, P.PASSWORD");
SELECT("P.FIRST_NAME, P.LAST NAME");
FROM("PERSON P");
if (id != null) {
WHERE("P.ID=#{id}");
}
if (firstName != null) {
WHERE("P.FIRST_NAME=#{firstName}");
}
if (lastName != null) {
WHERE("P.LAST_NAME=#{lastName}");
}
}}.toString();
}
ScriptRunner
该工具类用于读取脚本文件中的 SQL 语句并执行
public void testscriptRunner() {
try {
Connection connection=DriverManager.getConnection("jdbc:hsqldb:mem:mybatis","sa","");
Scriptrunner scriptRunnermnew ScriptRunner(connection):
scriptrunner.runScript(Resources.getResourceAsReader("create-table.sql"))
} catch (Exception e) {
e.printstackTrace();
}
}
如上面的代码所示,ScriptRunner 工具类的构造方法需要一个 java.sql.Connection 对象作为参数。创建 ScriptRunner 对象后,调用该对象的 runScript 方法即可,该方法接收一个读取 SQL 脚本文件的 Reader 对象作为参数
ScriptRunner 工具类中提供了一些属性,用于控制执行 SQL 脚本的一些行为,代码如下;
public class ScriptRunner{
// SQL异常是否中断程序执行
private boolean stopOnError;
// 是否抛出 SQLWarning 警告
private boolean throwWarning;
//是否自动提交
private boolean autoCommit;
// 属性为 true 时,批量执行文件中的 SQL 语句
//为false时逐条执行 sQL 语句,默认情况下,SQL语句以分号分割
private boolean sendfullScript;
//是否去除Windows系统换行符中的\r
private boolean removecrs;
//设置statement属性是否支持转义处理
private boolean escapeProcessing=true;
// 日志输出位置,默认标准输入输出,即控制台
private PrintWriter logWriter=new PrintWriter(System.out);
// 错误日志输出位置,默认控制台
private PrintWriter errorLoqWriter =new PrintWriter(System.err);
// 脚本文件中 SOL 语句的分隔符,默认为分号
private String delimiter= DEFAULT_DELIMITER;
// 是否支持 SOL 语句分割符,单独占一行
private boolean fullLineDelimiter;
...
}
我们可以直接调用这些属性对应的 Setter 方法来控制 ScriptRunner 工具类执行 SQL 脚本的行为
SqlRunner
MyBatis 提供了一个非常实用的、用于操作数据库的 SqlRunner 工具类,该类对 JDBC 做了很好的封装,结合 SQL 工具类,能够很方便地通过 Java 代码执行 SQL 语句并检索 SQL 执行结果
SglRunner 类提供了几个操作数据库的方法,分别说明如下:
- SqlRunner#closeConnection: 用于关闭 Connection 对象
- SqlRunner#selectOne(String sql, Object… args):执行 SELECT 语句,SQL 语句中可以使用占位符,如果 SOL 中包含占位符,则可变参数用于为参数占位符赋值,该方法只返回一条记录,若查询结果行数不等于一,则会抛出 SQLException 异常
- SqlRunner#selectAll(String sql,Object… args):该方法和 selectOne 方法的作用相同,只不过该方法可以返回多条记录,方法返回值是一个 List 对象,List 中包含多个 Map 对象,每个 Map 对象对应数据库中的一行记录
- SqlRunner#insert(String sql,Object… args):执行一条 INSERT 语句,插入一条记录
- SqlRunner#update(String sql,Object… args):更新若干条记录
- SqlRunner#delete(String sql,Object… args):删除若干条记录
- SqlRunner#run(String sql):执行任意一条 SQL 语句,最好为 DDL 语句
接下来我们来看一下 SqlRunner 工具类的使用案例,代码如下:
@Test
public void testselectOne() throws SQLException {
SqlRunner sqlRunner=new SqlRunner(connection)
String gryUserSql = new SQL() {{
SELECT("*");
FROM("user");
WHERE("id=?");
}}.toString();
Map<String, Object> resultMap = sqlRunner.selectOne(qryUserSql, Integer.valueOf(1));
System.out.println(JSON.toJSONString(resultMap));
}
@Test
public void testDelete() throws SQLException {
SqlRunner sqlRunner=new SqlRunner(connection);
String deleteUserSql = new SQL() {{
DELETE FROM("user");
WHERE("id = ?");
}}.toString();
sqlRunner.delete(deleteUserSql,Integer.valueOf(1));
}
@Test
public void testUpdate() throws SQLException {
SqlRunner sqlRunner=new SqlRunner(connection);
String updateUserSql = new SQL() {{
UPDATE("user");
SET("nick_name = ?");
WHERE("id = ?");
}}.toString();
sqlRunner.update(updateUserSql,"Jane",Integer.valueOf(1));
}
@Test
public void testInsert() throws SQLException {
SqlRunner sqlRunner=new SqlRunner(connection);
String insertUserSql = new SQL() {{
INSERT INTO("user");
INTO COLUMNS("create_time, name, password, phone, nick_name");
INTO VALUES("?,?,?,?,?");
}}.toString();
sqlRunner.insert(insertUserSql,createTime,"Jane","test","18700000000" "J");
}
MetaObject
MetaObject 是 MyBatis 中的反射工具类,该工具类在 MyBati s源码中出现的频率非常高。使用 MetaObject 工具类,我们可以很优雅地获取和设置对象的属性值
使用 MetaObject 工具类获取 User 对象的属性信息,案例代码如下:
@Test
public void testMetaObject() {
List<order> orders= new ArrayList()(
add(new Order("order20171024010246","《MyBatis源码深度解析》图书"));
add(new Order("order20171024010248","《AngularJs入门与进阶》图书"));
};
User user = new User(orders,"江荣波",3);
MetaObject metaObject = SystemMetaObject.forObject(user);
// 获取第一笔订单的商品名称
System.out.println(metaObject.getValue("orders[0].goodsName"));
// 获取第二笔订单的商品名称
System.out.println(metaObject.getvalue("orders[1].goodsName"));
// 为属性设置值
metaObject.setValue("orders[1].orderNo","order20181113010139");
// 判断 User 对象是否有 orderNo 属性
System.out.println("是否有orderNo属性且orderNo属性有对应的Getter方法:" + metaObject.hasGetter("orderNo"));
// 判断 User 对象是否有 name 属性
System.out.println("是否有name属性且name 属性有对应的Getter方法:" + metaObject.hasGetter("name"));
}
MetaClass
MetaClass 是 MyBatis 中的反射工具类,与 MetaOjbect 不同的是,MetaObject 用于获取和设置对象的属性值,而 MetaClass 则用于获取类相关的信息
@Test
public void testMetaClass() {
MetaClass metaClass =MetaClass.forClass(Orderclass,newDefaultReflectorFactory());
// 获取所有有 Getter 方法的属性名
String[] getterNames = metaClass.getGetterNames();
System.out.println(JSON.toJSONString(getterNames));
// 是否有默认构造方法
System.out.println("是否有默认构造方法:" + metaClass.hasDefaultConstructor());
// 某属性是否有对应的Getter/Setter方法
System.out.printIn("orderNo属性是否有对应的Getter 方法:" + metaClass.hasGetter("orderNo"));
System.out.println("orderNo属性是否有对应的Setter方法:" + metaClass.hasSetter("orderNo"));
System.out.println("orderNo属性类型:" + metaClass.getGetterType("orderNo"));
}
ObjectFactory
ObjectFactory 是 MyBatis 中的对象工厂,MyBatis 每次创建 Mapper 映射结果对象的新实例时,都会使用一个对象工厂实例来完成。ObjectFactory 接口只有一个默认的实现,即 DefaultObjectFactory,默认的对象工厂需要做的仅仅是实例化目标类,要么通过默认构造方法,要么在参数映射存在的时候通过参数构造方法来实例化
public class ObjectFactoryExample {
@Test
public void testObjectFactory() {
ObjectFactory objectFactory = new DefaultObjectFactory();
List<Integer> list = objectFactory.create(List.class);
Map<String, String> map = objectFactory.create(Map.class);
list.addAll(Arrays.asList(1. 23));
map.put("test","test");
System.out.printin(list);
System.out.println(map);
}
}
MyBatis 中使用 ObjectFactory 实例创建 Mapper 映射结果对象的目的是什么呢?实际上,这是 MyBatis 提供的一种扩展机制。有些情况下,在得到映射结果之前我们需要处理一些逻辑,或者在执行该类的有参构造方法时,在传入参数之前,要对参数进行一些处理,这时我们可以通过自定义 ObjectFactory 来实现。下面是一个自定义 ObjectFactory 的案例,代码如下:
public class CustomObjectfactory extends Defaultobjectfactory{
@Override
public object create(Class type){
if(type.equals(User.class)) {
//实例化User类
User user=(User)super.create(type);
user.setUuid(UUID.randomUUID().toString());
return user;
}
return super.create(type);
}
}
如上面的代码所示,自定义一个 ObjectFactory 非常简单,我们可以继承 DefaultObjectFactory,然后重写 create 方法即可。自定义 ObjectFactory 后,还需要在MyBatis 主配置文件中通过 标签配置自定义的 ObjectFactory,具体如下:
<objectfactory type="com.blog4java.mybatis.objectfactory.CustomobjectFactory">
<property name="someProperty" value="10"/>
</objectfactory>
ProxyFactory
ProxyFactory 是 MyBatis 的代理工厂,主要用于创建动态代理对象,ProxyFactory接口有两个不同的实现,分别为 CglibProxyFactory 和 JavassistProxyFactory。从实现类的名称可以看出,MyBatis 支持两种动态代理策略,分别为 Cglib 和 Javassist 动态代理。ProxyFactory主要用于实现 MyBatis 的懒加载功能。当开启懒加载后,MyBatis 创建 Mapper 映射结果对象后,会通过 ProxyFactory 创建映射结果对象的代理对象。当我们调用代理对象的 Getter 方法获取数据时,会执行 CglibProxyFactory 或 JavassistProxyFactory 中定义的拦截逻辑,然后执行一次额外的查询
下面是使用 JavassistProxyFactory 创建动态代理对象的案例,代码如下:
public class ProxyFactoryExample {
@Data
@AllArgsConstructor
private static class Order {
private String orderNo;
private String goodsName;
}
@Test
public void testProxyFactory() {
// 创建 ProxyFactory对象
ProxyFactory proxyFactory =new JavassistProxyFactory();
Order order = new Order("gn20170123","《MyBatis源码深度解析》图书");
ObjectFactory objectFactory=new DefaultObjectFactory();
//调用ProxyFactory对象的createProxy()方法创建代理对象
Object proxyOrder=proxyFactory.createProxy(order,
mock(ResultLoaderMap.class),
mock(Configuration.class),
objectfactory,
Arrays.asList(String.class,String.class),
Arrays.asList(order.getorderNo(),order.getGoodsName()));
System.out.println(proxyOrder.getClass());
System.out.println(((Order)proxyOrder).getGoodsName());
}
}
MyBatis 常用工具类的更多相关文章
- Maven基础&&Spring框架阶段常用工具类整理
常用工具类 1.密码加密工具类: package com.itheima.utils; import java.security.MessageDigest; import sun.misc.BASE ...
- js常用工具类.
一些js的工具类 复制代码 /** * Created by sevennight on 15-1-31. * js常用工具类 */ /** * 方法作用:[格式化时间] * 使用方法 * 示例: * ...
- IOS开发--常用工具类收集整理(Objective-C)(持续更新)
前言:整理和收集了IOS项目开发常用的工具类,最后也给出了源码下载链接. 这些可复用的工具,一定会给你实际项目开发工作锦上添花,会给你带来大大的工作效率. 重复造轮子的事情,除却自我多练习编码之外,就 ...
- Apache Commons 常用工具类整理
其实一直都在使用常用工具类,只是从没去整理过,今天空了把一些常用的整理一下吧 怎么使用的一看就明白,另外还有注释,最后的使用pom引入的jar包 public class ApacheCommonsT ...
- Android 常用工具类之SPUtil,可以修改默认sp文件的路径
参考: 1. 利用Java反射机制改变SharedPreferences存储路径 Singleton1900 2. Android快速开发系列 10个常用工具类 Hongyang import ...
- 封装一个简单好用的打印Log的工具类And快速开发系列 10个常用工具类
快速开发系列 10个常用工具类 http://blog.csdn.net/lmj623565791/article/details/38965311 ------------------------- ...
- javaweb常用工具类及配置文件备份
Javaweb常用工具类及配置文件备份 做一个代码备份,以后常用到的. hibernate工具类备份 package com.dly.service; /* * hibernate获取sessi ...
- [C#] 常用工具类——直接在浏览器输出数据
/// <summary> /// <para> </para> /// 常用工具类——直接在浏览器输出数据 /// <para> ---------- ...
- [C#] 常用工具类——加密解密类
using System; using System.Configuration; using System.Collections.Generic; using System.Text; using ...
- C#常用工具类——Excel操作类
/// 常用工具类——Excel操作类 /// <para> ------------------------------------------------</para> / ...
随机推荐
- jdk1.8 LocalTime、LocalDate、LocalDateTime 使用大全
目录 LocalTime.LocalDate.LocalDateTime 区别 LocalTime.LocalDate.LocalDateTime 使用 now 获取当前 时刻.日期.时间 of 获取 ...
- 3.1 JAVA方法:
JAVA方法: 何为方法 方法是语句的集合,这个集合执行一个功能 方法包含于类或对象中 方法在程序中被创建,在其他地方被引用 java全是值传递 方法的定义和调用 方法的定义: 修饰符 返回类型 方法 ...
- 海思码率控制相关参数调优(CBR/VBR)
1.CBR 海思相关参数调整(在Hisi板,cat /proc/umap/rc 可查看相关参数变化) 1.1 RC参数 1.2 VENC参数 VENC_PARAM_H264_CBR_S/VENC_PA ...
- C# 禁用窗口激活
如果界面点击时,不想让窗口激活,可以按如下操作: 1 public MainWindow() 2 { 3 InitializeComponent(); 4 SourceInitialized += O ...
- [Pytorch框架] 1.1、Pytorch简介
文章目录 1.1 Pytorch 简介 1.1.1 PyTorch的由来 1.1.2 Torch是什么? 1.1.3 重新介绍 PyTorch 1.1.4 对比PyTorch和Tensorflow 1 ...
- Hibernate 基本操作、懒加载以及缓存
前言 上一篇咱们介绍了 Hibernate 以及写了一个 Hibernate 的工具类,快速入门体验了一波 Hibernate 的使用,我们只需通过 Session 对象就能实现数据库的操作了. 现在 ...
- 2023-04-02:设计一个仓库管理器,提供如下的方法: 1) void supply(String item, int num, int price) 名字叫item的商品,个数num,价格pri
2023-04-02:设计一个仓库管理器,提供如下的方法: void supply(String item, int num, int price) 名字叫item的商品,个数num,价格price. ...
- 2022-10-06:以下go语言代码输出什么?A:[1 2 3] [1 2 3] ;B:[1 2 3] [3 4 5]; C:[1 2 3] [3 4 5 6 7 8 9];D:[1 2 3] [3
2022-10-06:以下go语言代码输出什么?A:[1 2 3] [1 2 3] :B:[1 2 3] [3 4 5]: C:[1 2 3] [3 4 5 6 7 8 9]:D:[1 2 3] [3 ...
- 2022-09-25:给定一个二维数组matrix,数组中的每个元素代表一棵树的高度。 你可以选定连续的若干行组成防风带,防风带每一列的防风高度为这一列的最大值 防风带整体的防风高度为,所有列防风高度
2022-09-25:给定一个二维数组matrix,数组中的每个元素代表一棵树的高度. 你可以选定连续的若干行组成防风带,防风带每一列的防风高度为这一列的最大值 防风带整体的防风高度为,所有列防风高度 ...
- 2021-01-18:java中,HashMap的创建流程是什么?
福哥答案2021-01-18: jdk1.7创建流程:三种构造器.1.初始容量不能为负数,默认16.2.初始容量大于最大容量时,初始容量等于最大容量.3.负载因子必须大于0,默认0.75.4.根据初始 ...