动态sql除了支持xml方式以外,还是支持使用纯注解的方式
主要一下四个注解+对应动态sql语句的类文件
@InsertProvider 动态查询SQL语句对应注解
@InsertProvider 动态插入SQL语句对应注解
@UpdateProvider 动态修改SQL语句对应注解
@DeleteProvider 动态删除SQL语句对应注解
允许构建动态 SQL。这些备选的 SQL 注解允许你指定返回 SQL 语句的类和方法,以供运行时执行。(从 MyBatis 3.4.6 开始,可以使用 CharSequence
代替 String
来作为返回类型)。当执行映射语句时,MyBatis 会实例化注解指定的类,并调用注解指定的方法。你可以通过 ProviderContext
传递映射方法接收到的参数、“Mapper interface type” 和 “Mapper method”(仅在 MyBatis 3.4.5 以上支持)作为参数。(MyBatis 3.4 以上支持传入多个参数)属性:type
、method
。type
属性用于指定类名。method
用于指定该类的方法名(从版本 3.5.1 开始,可以省略 method
属性,MyBatis 将会使用 ProviderMethodResolver
接口解析方法的具体实现。如果解析失败,MyBatis 将会使用名为 provideSql
的降级实现)。提示 接下来的“SQL 语句构建器”一章将会讨论该话题,以帮助你以更清晰、更便于阅读的方式构建动态 SQL。
Java 程序员面对的最痛苦的事情之一就是在 Java 代码中嵌入 SQL 语句。这通常是因为需要动态生成 SQL 语句,不然我们可以将它们放到外部文件或者存储过程中。如你所见,MyBatis 在 XML 映射中具备强大的 SQL 动态生成能力。但有时,我们还是需要在 Java 代码里构建 SQL 语句。此时,MyBatis 有另外一个特性可以帮到你,让你从处理典型问题中解放出来,比如加号、引号、换行、格式化问题、嵌入条件的逗号管理及 AND 连接。确实,在 Java 代码中动态生成 SQL 代码真的就是一场噩梦
MyBatis 3 提供了方便的工具类来帮助解决此问题。借助 SQL 类,我们只需要简单地创建一个实例,并调用它的方法即可生成 SQL 语句。
看面案例:
查询姓名带黄的或者 age = 25
Mapper接口:
/*
* @SelectProvider(type=UserSqlBuilder.class,method="selectByCondition")
* @SelectProvider 查询动态sql语句的 注解
* type : 编写动态sql语句的类对应的字节码
* method : 编写动态sql语句类对应的方法名称
* 此方法返回的是一个String字符串,字符串就是拼接sql语句
*/
@SelectProvider(type = UserSqlBuilder.class,method = "selectByCondition")
List selectByCondition(User user);
UserSqlBuilder sql构建类:
public class UserSqlBuilder {
public String selectByCondition(User user){
// 创建 sql 对象 构建 sql字符串
SQL sql = new SQL();
// select *
sql.SELECT("*");
// select * from t_user
sql.FROM("t_user");
// select * from t_user where name like #{name}
if (user.getName() != null) {
sql.WHERE("name like #{name}");
}
//默认多条件是AND ,可以自己制定成 OR
if (user.getAge() != null) {
sql.OR();
sql.WHERE("age = #{age}");
}
return sql.toString();
}
}
测试代码sql的构建:
@Test
public void testSelectConditionSQLBuilder(){
UserSqlBuilder userSqlBuilder = new UserSqlBuilder();
User u = new User();
u.setName("%黄%");
u.setAge(25);
String s = userSqlBuilder.selectByCondition(u);
System.out.println(s);
}
查看日志:
SELECT *
FROM t_user
WHERE (name like #{name})
OR (age = #{age})
测试代码:
@Test
public void testSelectCondition(){
SqlSession sqlSession = SqlSessionUtils.getSqlSession();
UserMapperAnnotation mapper = sqlSession.getMapper(UserMapperAnnotation.class);
User u = new User();
u.setName("%黄%");
u.setAge(25);
List users = mapper.selectByCondition(u);
System.out.println(users);
SqlSessionUtils.close(sqlSession);
}
日志:
DEBUG [main] - ==> Preparing: SELECT * FROM t_user WHERE (name like ?) OR (age = ?)
DEBUG [main] - ==> Parameters: %黄%(String), 25(Integer)
TRACE [main] - <== Columns: id, name, pwd, age
TRACE [main] - <== Row: 4, 洪七公, aaa, 25
TRACE [main] - <== Row: 5, 黄蓉, 阿里巴巴, 38
TRACE [main] - <== Row: 6, 王语嫣, abc, 25
TRACE [main] - <== Row: 7, 周芷若, 1234, 25
TRACE [main] - <== Row: 8, 黄药师, 1234, 66
DEBUG [main] - <== Total: 5
Mapper接口:
Long selectTotalByCondition(User user);
UserSqlBuilder sql构建类:
public String selectTotalByCondition(User user){
SQL sql = new SQL();
// select *
sql.SELECT("count(*) ");
// select * from t_user
sql.FROM("t_user");
// select * from t_user where name like name = #{name}
if (user.getName() != null) {
sql.WHERE(" name like name = #{name}");
}
if (user.getAge() != null) {
// select * from t_user where name like name = #{name} or age = #{age}
sql.OR();
sql.WHERE("age = #{age}");
}
return sql.toString();
}
测试sql构建:
@Test
public void testselectTotalByConditionSqlBuilder() {
UserSqlBuilder sqlBuilder = new UserSqlBuilder();
User u = new User();
u.setName("%黄%");
u.setAge(25);
String s = sqlBuilder.selectTotalByCondition(u);
System.out.println(s);
}
日志:
SELECT count(*)
FROM t_user
WHERE ( name like name = #{name})
OR (age = #{age})
测试代码:
@Test
public void testSelectTotalByCondition(){
SqlSession sqlSession = SqlSessionUtils.getSqlSession();
UserMapperAnnotation mapper = sqlSession.getMapper(UserMapperAnnotation.class);
User u = new User();
u.setName("%黄%");
u.setAge(25);
Long aLong = mapper.selectTotalByCondition(u);
System.out.println(aLong);
SqlSessionUtils.close(sqlSession);
}
日志:
DEBUG [main] - ==> Preparing: SELECT count(*) FROM t_user WHERE ( name like name = ?) OR (age = ?)
DEBUG [main] - ==> Parameters: %黄%(String), 25(Integer)
TRACE [main] - <== Columns: count(*)
TRACE [main] - <== Row: 3
DEBUG [main] - <== Total: 1
3
mapper接口:
@UpdateProvider(type = UserSqlBuilder.class, method = "updateUserByNotNull")
int updateUserByNotNull(User user);
UserSqlBuilder sql构建类:
public String updateUserByNotNull(User user){
SQL sql = new SQL();
// update t_user
sql.UPDATE("t_user");
// update t_user set name = #{name}
if (user.getName() != null) { // 不要自己在后面加 ,
sql.SET("name = #{name}");
}
// update t_user set name = #{name},age = #{age}
if (user.getAge() != null) {
sql.SET("age = #{age}");
}
// update t_user set name = #{name},age = #{age},pwd = #{pwd}
if (user.getPwd() != null) {
sql.SET("pwd = #{pwd}");
}
// update t_user set name = #{name},age = #{age},pwd = #{pwd} where id = #{id}
sql.WHERE("id = #{id}");
return sql.toString();
}
sql构建的测试:
@Test
public void testUpdateSqlBuilder() {
UserSqlBuilder sqlBuilder = new UserSqlBuilder();
User u = new User();
u.setName("紫衫龙王");
u.setAge(25);
u.setId(4);
String s = sqlBuilder.updateUserByNotNull(u);
System.out.println(s);
}
日志:
UPDATE t_user
SET name = #{name}, age = #{age}
WHERE (id = #{id})
测试代码:
@Test
public void testUpdate(){
SqlSession sqlSession = SqlSessionUtils.getSqlSession();
UserMapperAnnotation mapper = sqlSession.getMapper(UserMapperAnnotation.class);
User u = new User();
u.setName("紫衫龙王");
u.setAge(25);
u.setId(8);
int i= mapper.updateUserByNotNull(u);
sqlSession.commit();
System.out.println(i);
SqlSessionUtils.close(sqlSession);
}
日志:
DEBUG [main] - ==> Preparing: UPDATE t_user SET name = ?, age = ? WHERE (id = ?)
DEBUG [main] - ==> Parameters: 紫衫龙王(String), 25(Integer), 8(Integer)
DEBUG [main] - <== Updates: 1
1
mapper的代码:
@DeleteProvider(type = UserSqlBuilder.class,method = "deleteUsers")
int deleteUsers(@Param("list") List list);
UserSqlBuilder sql构建类:
public String deleteUsers(@Param("list") List list){
SQL sql = new SQL();
// delete from t_user
sql.DELETE_FROM("t_user");
// 没有拼接的方法 只能自己写字符串拼接
// 拼接条件 (#{list[0]},#{list[1]},#{list[2]})
StringBuilder sb = new StringBuilder();
sb.append("(");
for (int i = 0; i < list.size(); i++) {
sb.append("#{list["+i+"]},");
}
// 删除 字符串拼接最后一个 ,
sb.deleteCharAt(sb.length() - 1);
sb.append(")");
// delete from t_user where id in (1,2,3);
sql.WHERE("id in " +sb.toString());
return sql.toString();
}
sql测试代码:
@Test
public void testDeleteSqlBuilder() {
UserSqlBuilder sqlBuilder = new UserSqlBuilder();
List list =new ArrayList<>();
list.add(1);
list.add(4);
list.add(5);
sqlBuilder.deleteUsers(list);
String s = sqlBuilder.deleteUsers(list);
System.out.println(s);
}
日志:
DELETE FROM t_user
WHERE (id in (#{list[0]},#{list[1]},#{list[2]}))
测试代码:
@Test
public void testSelectList(){
SqlSession sqlSession = SqlSessionUtils.getSqlSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
List list =new ArrayList<>();
list.add(1);
list.add(4);
list.add(5);
List users = mapper.selectList(list);
System.out.println(users);
SqlSessionUtils.close(sqlSession);
}
日志:
DEBUG [main] - ==> Preparing: DELETE FROM t_user WHERE (id in (?,?,?))
DEBUG [main] - ==> Parameters: 1(Integer), 4(Integer), 5(Integer)
DEBUG [main] - <== Updates: 3
3
mapper接口:
@InsertProvider(type = UserSqlBuilder.class,method = "insertUsers")
int insertUsers(@Param("users")List list);
UserSqlBuilder sql构建类:
public String insertUsers(@Param("users")List list){
SQL sql = new SQL();
// insert into t_user(name,pwd,age) values (?,?,?)
StringBuilder sb = new StringBuilder();
sb.append("insert into t_user(name,pwd,age) values ");
for (int i = 0; i < list.size(); i++) {
sb.append("(");
sb.append("#{users["+i+"].name},");
sb.append("#{users["+i+"].pwd},");
sb.append("#{users["+i+"].age}");
sb.append("),");
}
sb.deleteCharAt(sb.length() - 1);
return sb.toString();
}
sql构建测试代码:
@Test
public void testInsertSqlBuilder() {
UserSqlBuilder sqlBuilder = new UserSqlBuilder();
List list =new ArrayList<>();
list.add(new User(null,"梅超风","123",30));
list.add(new User(null,"曲正风","123",40));
list.add(new User(null,"空见","123",35));
String s = sqlBuilder.insertUsers(list);
System.out.println(s);
}
测试代码:
@Test
public void testInsertUsers(){
SqlSession sqlSession = SqlSessionUtils.getSqlSession();
UserMapperAnnotation mapper = sqlSession.getMapper(UserMapperAnnotation.class);
List list =new ArrayList<>();
list.add(new User(null,"梅超风","123",30));
list.add(new User(null,"曲正风","123",40));
list.add(new User(null,"空见","123",35));
mapper.insertUsers(list);
sqlSession.commit();
SqlSessionUtils.close(sqlSession);
}
日志:
DEBUG [main] - ==> Preparing: insert into t_user(name,pwd,age) values (?,?,?),(?,?,?),(?,?,?)
DEBUG [main] - ==> Parameters: 梅超风(String), 123(String), 30(Integer), 曲正风(String), 123(String), 40(Integer), 空见(String), 123(String), 35(Integer)
DEBUG [main] - <== Updates: 3