1. if
在MyBatis中,元素是最常用的判断语句,它类似于Java中的if语句,主要用于实现某些简单的条件选择。
代码演示 (实现一个多条模糊 根据姓名和职业组合条件查询用户信息列表的动态SQL)
实体类
package beans.Pojo;
public class User {
private Integer id;
private String name;
private String job;
public User() {
}
public User(Integer id, String name, String job) {
this.id = id;
this.name = name;
this.job = job;
}
public User(Integer id, String name) {
this.id = id;
this.name = name;
}
public String getJob() {
return job;
}
public void setJob(String job) {
this.job = job;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", name='" + name + '\'' +
", job='" + job + '\'' +
'}';
}
}
首先配置 SqlMapConfig.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<!-- 核心配置文件-->
<properties resource="jdbc.properties"></properties>
<!--配置类型别名-->
<typeAliases>
<!-- <typeAlias type="beans.Pojo.User" alias="user"></typeAlias>-->
<package name="beans.Pojo"/>
</typeAliases>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"></transactionManager>
<dataSource type="POOLED">
<property name="driver" value="${jdbc.driver}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</dataSource>
</environment>
</environments>
<mappers>
<package name="beans.dao"></package>
</mappers>
</configuration>
其中的 jdbc.properties
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc\:mysql\://localhost\:3306/···
jdbc.username= ···
jdbc.password= ···
日志 log4j.properties
# Global logging configuration,建议开发环境中要用debug
log4j.rootLogger=DEBUG, stdout
# Console output...
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%5p [%t] -
%m%n
创建一个接口 UserMapper
public interface UserMapper {
//模糊
List<User> findMohu(String name);
//多个模糊
List<User> findMohuByNamAndJob(User user);
}
修改映射文件CustomerMapper.xml
在映射文件中使用if元素编写根据姓名和职业组合条件查询用户信息列表的动态SQL
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!-- parameterType 输入映射
resultType 和 resultMap 完成输出映射-->
<!-- 与接口相关联-->
<mapper namespace="beans.dao.UserMapper">
<!-- 动态sql if 实现多模糊的效果-->
<select id="findMohuByNamAndJob" parameterType="user" resultType="user">
<!-- where 1=1 永为真 防止sql注入-->
select * from t_user where 1=1
<if test="name!=null and name!='' ">
and name like concat ('%',#{name},'%')
</if>
<if test="job!=null and job!='' ">
and job = #{job}
</if>
</select>
<!-- 单个模糊-->
<select id="findMohu" parameterType="String" resultType="user">
select * from t_user where name like #{name}
</select>
</mapper>
题外话:
where 1=1的写法是为了检化程序中对条件的检测
上述例子的两个参数都可能为空, 这时你要构造语句的话,一个个检测再写语句就麻烦
加where 或直接用 and ?,你这里还要对参数是否为空进行检测
用上 where 1=1 之后,就不存在这样的问题, 条件是 and 就直接and ,是or就直接 or
如果不写1=1,那么在每一个不为空的查询条件面前,都必须判断有没有where字句。否则要在第一个出现的地方加where
测试类
InputStream inputStream;
SqlSessionFactory sessionFactory;
@Before
public void before() {
try {
inputStream = Resources.getResourceAsStream("SqlMapConfig.xml");
sessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
} catch (IOException e) {
e.printStackTrace();
}
}
//模糊
@Test
public void main9(){
SqlSession sqlSession = sessionFactory.openSession();
User user = new User();
user.setName("V");
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
List<User> mohu = mapper.findMohu("%"+user.getName()+"%");
for (User user1 : mohu) {
System.out.println(user1);
}
sqlSession.close();
}
//多个模糊
@Test
public void main10(){
SqlSession sqlSession = sessionFactory.openSession();
User user = new User();
user.setName("V");
user.setJob("A");
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
List<User> mohu = mapper.findMohuByNamAndJob(user);
for (User user1 : mohu) {
System.out.println(user1);
}
sqlSession.close();
}
2 <choose>、<when>、<otherwise>
元素
相当于Java中的switch和case语句(多条件分支判断 )
如果遇到下面的场景:
当用户名称不为空,则只根据用户名称进行筛选
当用户名称为空,而用户职业不为空,则只根据用户职业进行用户筛选
当用户名称和用户职业都为空,则要求查询出所有当前在线用户的用户信息
此种情况下,使用if元素进行处理是非常不合适的。如果使用的java语言,这种情况显然更适合使用switch…case…default语句来处理。针对上面情况,MyBatis中可以用choose、when、otherwise元素进行处理。
代码演示
实体类:
package beans.Pojo;
public class User {
private Integer id;
private String name;
private String job;
private Integer online;
public User() {
}
public User(Integer id, String name, String job,Integer online) {
this.id = id;
this.name = name;
this.job = job;
this.online=online;
}
public User(Integer id, String name) {
this.id = id;
this.name = name;
}
public String getJob() {
return job;
}
public void setJob(String job) {
this.job = job;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getOnline() {
return online;
}
public void setOnline(Integer online) {
this.online = online;
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", name='" + name + '\'' +
", job='" + job + '\'' +
", online=" + online +
'}';
}
}
首先配置 SqlMapConfig.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<!-- 核心配置文件-->
<properties resource="jdbc.properties"></properties>
<!--配置类型别名-->
<typeAliases>
<!-- <typeAlias type="beans.Pojo.User" alias="user"></typeAlias>-->
<package name="beans.Pojo"/>
</typeAliases>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"></transactionManager>
<dataSource type="POOLED">
<property name="driver" value="${jdbc.driver}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</dataSource>
</environment>
</environments>
<mappers>
<package name="beans.dao"></package>
</mappers>
</configuration>
其中的 jdbc.properties
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc\:mysql\://localhost\:3306/···
jdbc.username= ···
jdbc.password= ···
日志 log4j.properties
# Global logging configuration,建议开发环境中要用debug
log4j.rootLogger=DEBUG, stdout
# Console output...
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%5p [%t] -
%m%n
创建一个接口 UserMapper
public interface UserMapper {
//多条件分支判断
List<User> findMohuByNamAndJobByOnline(User user);
}
关联 UserMapper.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!-- parameterType 输入映射
resultType 和 resultMap 完成输出映射-->
<!-- 与接口相关联-->
<mapper namespace="beans.dao.UserMapper">
<!-- 多条件分支判断-->
<select id="findMohuByNamAndJobByOnline" parameterType="user" resultType="user">
select * from t_user where 1=1
<choose>
<when test="name!=null and name!='' ">
and name like concat ('%',#{name},'%')
</when>
<when test="job!=null and job!='' ">
and job= #{job}
</when>
<otherwise>
<!--不为空 就是在线-->
and online is not null
</otherwise>
</choose>
</select>
</mapper>
测试
InputStream inputStream;
SqlSessionFactory sessionFactory;
@Before
public void before() {
try {
inputStream = Resources.getResourceAsStream("SqlMapConfig.xml");
sessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
} catch (IOException e) {
e.printStackTrace();
}
}
@Test
public void main11(){
SqlSession sqlSession = sessionFactory.openSession();
User user = new User();
// name 和 job 在我的设置为空
user.setName("");
user.setJob("");
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
List<User> online = mapper.findMohuByNamAndJobByOnline(user);
for (User user1 : online) {
System.out.println(user1);
}
sqlSession.close();
}
3.<where>、<trim>
元素
上面的 “where 1=1”这种写法对于初学者来将不容易理解,并且也不够雅观。 针对上述情况中“where 1=1”,在MyBatis的SQL中就可以使用<where>或<trim>
元素进行动态处理。 将映射文件中的"where 1=1"条件删除 ,并使用where 元素替换后的代码
<!-- 动态sql if 实现多模糊的效果-->
<select id="findMohuByNamAndJob" parameterType="user" resultType="user">
<!-- where 1=1 永为真 防止sql注入-->
select * from t_user
<where>
<if test="name!=null and name!='' ">
and name like concat ('%',#{name},'%')
</if>
<if test="job!=null and job!='' ">
and job = #{job}
</if>
</where>
</select>
在上述代码中,使用where元素对“where 1=1"条件进行了替换,where元素会自动判断组合条件下拼装的SQL语句,只有where 元素内的条件成立时,才会在拼接SQL中加入where关键字,否则将不会添加
使用 trim 对 “where 1=1” 进行替换
<!-- 动态sql if 实现多模糊的效果-->
<select id="findMohuByNamAndJob" parameterType="user" resultType="user">
<!-- where 1=1 永为真 防止sql注入-->
select * from t_user
<trim prefix="where" prefixOverrides="and">
<if test="name!=null and name!='' ">
and name like concat ('%',#{name},'%')
</if>
<if test="job!=null and job!='' ">
and job = #{job}
</if>
</trim>
</select>
prefx代表的是语句的前缀(这里使用where来连接后面的SQL片段),而prefixOverrides属性代表的是需要去除的那些特殊字符串
4 set元素
一般用来实现单个字段的更新
set元素中,如果遇到了逗号,他会把对应的逗号去掉.注意 因为set元素删除了逗号,当set中的if条件如果有1个以上成立,就会导致sql语法错误
到这里 我就只写接口和接口相关联的xml 以及我们的配置文件了
接口
//更新
void update(User user);
UserMapper.xml
<!-- set 更新-->
<update id="update" parameterType="user">
update t_user
<set>
<if test="name!=null and name!='' ">
name=#{name},
</if>
<if test="job!=null and job!='' ">
job=#{job},
</if>
<if test="online!=null and online!=''">
online=#{online}
</if>
</set>
where id=#{id}
</update>
测试类
InputStream inputStream;
SqlSessionFactory sessionFactory;
@Before
public void before() {
try {
inputStream = Resources.getResourceAsStream("SqlMapConfig.xml");
sessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
} catch (IOException e) {
e.printStackTrace();
}
}
@Test
public void main12(){
SqlSession sqlSession = sessionFactory.openSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
//实体类创建一个有参构造
User user = new User(1,"dsm","A",1);
mapper.update(user);
//提交事务
sqlSession.commit();
//关闭资源
sqlSession.close();
}
5.<foreach>
元素
foreach元素就相当于java中的for循环语句
它主要的目的还是做批量的操作。比如查询1000条数据中的一百条数据时,就需要使用foreach来提高效率。
接口:(我使用的是把list包进map中)
//根据多个用户id 来查询用户信息
List<User> findByIdsFro(Map map);
UserMapper.xml
<!-- 根据多个用户id 来查询用户信息-->
<select id="findByIdsFro" parameterType="map" resultType="user">
select * from t_user where id in
<foreach collection="mylist" item="id" index="mylist" open="(" separator="," close=")">
#{id}
</foreach>
</select>
collection:
List对象默认用"list"代替作为key键名,数组对象用"array"代替作为key键名,Map对象则是自己声明的key键名,没有默认的。
item:
迭代中当前对象(value)的别名,该参数为必选。
index:
如果传来的值是list或数组,index是元素的序号,下标。如果是map,index是当前键值队中的key(键名),该参数可选。
open:
foreach代码的开始符号,一般是(和close=")"合用。常用在in(),values()时。该参数可选
separator:
元素之间的分隔符,例如在in()的时候,separator=","会自动在元素中间用“,“隔开,避免手动输入逗号导致sql错误,如in(1,2,)这样。该参数可选。
close:
foreach代码的关闭符号,一般是)和open="("合用。常用在 in(), values() 时。该参数可选。
测试:
InputStream inputStream;
SqlSessionFactory sessionFactory;
@Before
public void before() {
try {
inputStream = Resources.getResourceAsStream("SqlMapConfig.xml");
sessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
} catch (IOException e) {
e.printStackTrace();
}
}
@Test
public void test1(){
SqlSession sqlSession = sessionFactory.openSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
ArrayList<Integer> list = new ArrayList<>();
list.add(1);
list.add(2);
list.add(3);
Map<String, List<Integer>> map = new HashMap<String, List<Integer>>();
//注意 map的键 为mylist
map.put("mylist",list);
List<User> byIdsFro = mapper.findByIdsFro(map);
byIdsFro.stream().forEach(System.out::println);
sqlSession.close();
}
6<bind>
元素
从OGML表达式中创造一个变量,并将其绑定在上下文,常用与模糊查询中
优点是可以防止注入攻击,统一各种数据库系统的格式,比如说:
MySQL先前要使用concat进行模糊查询的拼接
Oracle使用的是"||"。
代码演示:
接口
List<User> findMohu(String name);
UserMapper.xml
<select id="findMohu" parameterType="String" resultType="user">
<!--name表示他的变量名 与like #{ } 对应-->
<!--value是值-->
<!--_parameter是Mybatis内置的参数,代表传入的值-->
<!--'%'是sql语句中模糊查询的方法,用+号与传入值拼接起来-->
<bind name="name" value="'%'+_parameter+'%'"/>
select * from t_user where name like #{name}
</select>
测试:
@Test
public void main9(){
SqlSession sqlSession = sessionFactory.openSession();
User user = new User();
user.setName("V");
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
List<User> mohu = mapper.findMohu(user.getName());
mohu.stream().forEach(System.out::println);
sqlSession.close();
}