mybatis
1、理解数据持久化概念和ORM原理
1.1、持久化
持久化是程序数据在瞬时状态和持久状态间来回转换的过程
瞬时状态存在在内存里
持久状态存放在磁盘里
1.2、ORM(Object Relational Mapping)
以前使用JDBC做持久化操作,现在可以用框架做持久化
编写程序的时候,以面向对象的方式处理数据
保存数据的时候,却以关系型数据库的方式存储
ORM解决方案包含下面四个部分
在持久化对象上执行基本的增、删、改、查操作
对持久化对象提供一种查询语言或者API
对象关系映射工具
提供与事务对象交互、执行检查、延迟加载以及其他优化功能
2、理解MyBatis的概念以及优点特性
MyBatis前身是iBatis,本是Apache的一个开源的项目
官方网站:http://mybatis.org
2.1、ORM框架
实体类和SQL语句之间建立映射关系
2.2、特点
基于SQL语法,简单易学
能了解底层封装过程
SQL语句封装在配置文件中(不建议用注解),便于统一管理与维护,降低程序的耦合度
方便程序代码调试
3、搭建MyBatis环境
3.1、搭建步骤
1、启动数据库,运行smbms_db.sql脚本
2、新建一个web项目smbms
3、jar包
导入连接数据库jar包
导入mybatis的jar包,mybatis只要这个jar包足够了
4、创建实体类-POJO,对照数据库建立
Role.java
package cn.cwj.smbms.pojo;
import java.io.Serializable;
import java.util.Date;
/**
* 角色类
*/
//最好实现可序列化接口,保证安全
public class Role implements Serializable{
private static final long serialVersionUID = 1L;
private Integer id;
private String roleCode;
private String roleName;
private Integer createBy;
private Date creationDate;
private Integer modifyBy;
private Date modifyDate;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getRoleCode() {
return roleCode;
}
public void setRoleCode(String roleCode) {
this.roleCode = roleCode;
}
public String getRoleName() {
return roleName;
}
public void setRoleName(String roleName) {
this.roleName = roleName;
}
public Integer getCreateBy() {
return createBy;
}
public void setCreateBy(Integer createBy) {
this.createBy = createBy;
}
public Date getCreationDate() {
return creationDate;
}
public void setCreationDate(Date creationDate) {
this.creationDate = creationDate;
}
public Integer getModifyBy() {
return modifyBy;
}
public void setModifyBy(Integer modifyBy) {
this.modifyBy = modifyBy;
}
public Date getModifyDate() {
return modifyDate;
}
public void setModifyDate(Date modifyDate) {
this.modifyDate = modifyDate;
}
}
User.java
/*
* 用户类
*/
private Integer id;
private String userCode;
private String userName;
private String userPassword;
private Integer gender;
private Date birthday;
private String phone;
private String address;
private Integer userRole;
private Integer createdBy;
private Date creationDate;
private Integer modifyId;
private Date modifyDate;
private String idPicPath;
Bill.java
/*
* 商品类
*/
private Integer id;
private String billCode;
private String productName;
private String productDesc;
private String productUnit;
private Double productCount;
private Double totalPrice;
private Integer isPayment;
private Integer createdBy;
private Date creationDate;
private Integer modifyBy;
private Date modifyDate;
private Integer providerId;
Provider.java
/**
* 供应商类
*/
private Integer id;
private String proCode;
private String proName;
private String proDesc;
private String proContact;
private String proPhone;
private String proAddress;
private String proFax;
private Integer createdBy;
private Date creationDate;
private Integer modifyBy;
private Date modifyDate;
private String picPath;
3.2、 配置mybatis的配置文件
创建一个资源文件夹,单独放在mybatis文件夹,否则打包项目时jar包会整合到一起
新建一个mybatis-config.xml文件
transactionManager事务管理器,用JDBC来管理
dataSource,用连接词POOLED或者不用连接词UNPOOLED,JNDI
<?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>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.cj.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/smbms?useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=Asia/Shanghai"/>
<!-- xml文件要用&转义 -->
<property name="username" value="root"/>
<property name="password" value="111111"/>
</dataSource>
</environment>
</environments>
</configuration>
3.3、SQL映射文件
创建一个文件夹,新建一个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">
<!-- 如果用接口,这里是接口<mapper namespace="cn.cwj.dao.user.UserDao"> -->
<!--namespace可随便起名。但是尽量规范 ,最好包名.类名-->
<mapper namespace="cn.cwj.smbms.dao.user.UserMapper">
<!-- 查询用户,每一个操作都要给个id,要根据id去查找方法-->
<!-- resultType查询结果的类型,最好是实体类的包名.实体类名 ,后面这里可以起别名 -->
<select id="select" resultType="cn.cwj.smbms.pojo.User">
SELECT * FROM smbms_user
</select>
</mapper>
3.4、添加测试类
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import cn.cwj.smbms.pojo.User;
public class test {
public static void main(String[] args) {
//1、创建会话工厂创建器
SqlSessionFactoryBuilder builder=new SqlSessionFactoryBuilder();
try {
//2、创建读取mybatis核心配置文件的输入了,由于配置文件放在资源文件夹下面,所以不用写路径
InputStream is=Resources.getResourceAsStream("mybatis-config.xml");
//3、生成会话工厂
SqlSessionFactory factory=builder.build(is);
//4、创建会话
SqlSession session=factory.openSession();
//5、使用会话对象执行操作namespace.id,先找到配置文件,再找到对象的查询语句
List<User> userList=session.selectList("cn.cwj.dao.user.UserMapper.select");
for (User user : userList) {
System.out.println(user.getUserName());
}
//6关闭会话
session.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
要去mybatis-config.xml文件下加上映射
**此时的.改为/ **
<mappers>
<mapper resource="cn/cwj/smbms/dao/user/UserMapper.xml"/>
</mappers>
3.5、mybatis框架的优缺点
3.5.1、优点
与JDBC相比,减少了50%以上的代码量
最简单的持久化框架,小巧并简单易学
SQL代码从程序代码中彻底分离,可重用
提供XML标签,支持编写动态SQL
提供映射标签,支持对象与数据库的ORM字段映射
3.5.2、 缺点
SQL语句编写工作量大,对开发人员有一定要求
数据库移植性差
4、了解MyBatis与JDBC的区别与联系
4.1、mybatis的核心要素(核心对象)
4.1.1、SqlSessionFactoryBuilder
用过即丢,其生命周期只存在于方法体内
可重用其来创建多个 SqlSessionFactory 实例
负责构建SqlSessionFactory,并提供多个build方法的重载
4.1.2、SqlSessionFactory
SqlSessionFactory是每个MyBatis应用的核心
作用:创建SqlSession实例
作用域:Application
生命周期与应用的生命周期相同
SqlSession session = sqlSessionFactory.openSession(boolean autoCommit);
autoCommittrue:
关闭事务控制(默认)
false:开启事务控制
4.1.3、SqlSession
包含了执行SQL所需的所有方法
对应一次数据库会话,会话结束必须关闭
线程级别,不能共享
SqlSession session = sqlSessionFactory.openSession();
try {
// do work
} finally {
session.close();
}
在SqlSession里可以执行多次SQL语句,但一旦关闭了SqlSession就需要重新创建
4.1.3.1、SqlSession的两种使用方式
4.1.3.2、通过SqlSession实例直接运行映射的SQL语句
因为放入的是字符串,不会报错,运行会直接错误
List<User> userList=session.selectList("cn.cwj.smbms.dao.user.UserMapper.select");
4.2、基于Mapper接口方式操作数据
1、创建一个接口UserDao.java
package cn.cwj.smbms.dao.user;
import java.util.List;
import cn.cwj.smbms.pojo.User;
//这个借口不需要实现类,只需要一个方法即可
public interface UserDao {
List<User> select();
}
2、修改UserMapper.xml配置文件
把namespace="包名.映射文件名"改为namespace=“包名.接口名”
select id="select"id要和接口的方法名一样
<?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">
<mapper namespace="cn.cwj.smbms.dao.user.UserDao">
<select id="select" resultType="cn.cwj.smbms.pojo.User">
SELECT * FROM smbms_user
</select>
</mapper>
3、测试类的第5步使用会话对象执行操作改为
List<User> userList=session.getMapper(UserDao.class).select();
4.3、mybatis-config.xml 系统核心配置文件
4.3.1、如何加载配置文件
database.properties文件放入resource资源文件夹
driver=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://localhost:3306/smbms?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai
username=root
password=111111
mybatis-config.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 -->
<properties resource="database.properties"/>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<!-- 对应properties的值 -->
<property name="driver" value="${driver}"/>
<property name="url" value="${url}"/>
<!-- xml文件要用&转义 -->
<property name="username" value="${username}"/>
<property name="password" value="${password}"/>
</dataSource>
</environment>
</environments>
<mappers>
<mapper resource="cn/cwj/smbms/dao/user/UserMapper.xml"/>
</mappers>
</configuration>
4.4、别名typeAliases
4.4.1、给实体类起别名
1、在mybatis-config.xml文件里增加对应的实体类的别名
alias=“别名” type="包名.实体类名
<typeAliases>
<typeAlias alias="User" type="cn.cwj.smbms.pojo.User"/>
</typeAliases>
2、在userMapper.xml文件里修改resultType=“别名”
<select id="select" resultType="User">
SELECT * FROM smbms_user
</select>
4.4.2、让所有的对应类的类名自动变为别名
不需要<typeAlias alias="User" type="cn.cwj.smbms.pojo.User"/>,直接写包名
<typeAliases>
<package name="cn.cwj.smbms.pojo"/>
</typeAliases>
4.5、mapper.xml SQL映射文件
SQL映射文件的几个顶级元素(按照定义的顺序)
4.5.1、mapper - namespace
namespace:命名空间
namespace和子元素的id联合保证唯一,区别不同的mapper
绑定DAO接口
namespace的命名必须跟某个接口同名
接口中的方法与映射文件中SQL语句id一一对应
4.5.2、insert – 映射插入语句
创建接口int insert(User user);
创建映射
<insert id="insert">
INSERT INTO smbms_user(userCode,userName,userPassword,gender,birthday,phone,address,userRole,createdBy,creationDate,idPicPath)
VALUES(#{userCode},#{userName},#{userPassword},#{gender},#{birthday},#{phone},#{address},#{userRole},#{createdBy},NOW(),#{idPicPath})
</insert>
测试类
注意增删改查要提交session.commit();
//用构造方法new对象
User user=new User("212","test","1234",1,new Date(),"133333333335","test",2,1,"图片");
int count=session.getMapper(UserDao.class).insert(user);
if(count>0) {
//注意增删改要提交数据
session.commit();
System.out.println("成功");
}else {
session.rollback();
System.out.println("失败");
}
然后到数据库看是否成功
4.5.3、delete – 映射删除语句
接口int delect(int id);
UserMapper.xml(注意大写不要写错DELETE)
<!-- 删除 -->
<delete id="delect">
DELETE FROM smbms_user WHERE id=#{id}
</delete>
测试类
//删除
int count=session.getMapper(userDao.class).delect(21);
if(count!=0) {
session.commit();
System.out.println("成功");
}else {
session.rollback();
System.out.println("失败");
}
4.5.4、update – 映射更新语句
接口int update(User user);
UserMapper.xml文件中SQL语句(注意条件语句WHERE)
<!-- 更新 -->
<update id="update">
UPDATE smbms_user SET userCode=#{userCode},userName=#{userName},userPassword=#{userPassword},gender=#{gender},birthday=#{birthday},phone=#{phone},address=#{address},userRole=#{userRole},createdBy=#{createdBy},creationDate=#{creationDate},idPicPath=#{idPicPath}
WHERE id=#{id}
</update>
测试类
//更新
User user=new User();
user.setId(21);
user.setUserCode("21");
user.setUserName("lalaalall");
int count=session.getMapper(userDao.class).update(user);
if(count!=0) {
session.commit();
System.out.println("成功");
}else {
session.rollback();
System.out.println("失败");
}
4.5.5、select – 映射查询语句
select语句有很多属性可以详细配置每一条语句
id命名空间中唯一的标识符
接口中的方法与映射文件中的SQL语句id一一对应
关键代码
在UserDao.java的接口中添加方法
int count();
在UserMapper.xml文件中添加
<select id="count" resultType="int">
SELECT count(*) FROM smbms_user
</select>
在test.java中
int count=session.getMapper(UserDao.class).count();
System.out.println("用户数量:"+count);
4.5.5、parameterType传入SQL语句的参数类型
基础数据类型int、String、Date等
只能传入一个,通过#{参数名}即可获取传入的值
复杂数据类型Java实体类、Map等
通过#{属性名}或者#{map的keyName}即可获取传入值
4.5.5.1、根据多参数进行查询
添加接口的方法
User selectById(int id);
映射文件:
此时的WHERE id=#{id}
前面的id是数据库里的字段名,不可改,可以用表的别名点出来如WHERE U.id=#{id}
<select id="selectById" resultType="User" parameterType="int">
SELECT * FROM smbms_user WHERE id=#{id}
</select>
测试类
User user=session.getMapper(UserDao.class).selectById(10);
System.out.println(user.getUserName());
4.5.5.2、根据多个参数进行模糊查询
传入多个参数进行入参?
封装成User对象进行入参?
<select id="selectByNameRole" resultType="User" parameterType="User">
<!-- like模糊查询 concat连接字符串‘%’表示参数 -->
SELECT * FROM smbms_user WHERE userName LIKE CONCAT('%',#{userName},'%') AND userRole=#{userRole}
</select>
List<User> selectByNameRole(User user);
User user=new User();
user.setUserName("张");
user.setUserRole(3);
List<User> userList=session.getMapper(UserDao.class).selectByNameRole(user);
for (User user2 : userList) {
System.out.println(user2.getUserName());
}
使用map
List<User> selectByNameRole(Map map);
Map map=new HashMap();
map.put("userName", "张");
map.put("userRole", 3);
List<User> userList=session.getMapper(UserDao.class).selectByNameRole(map);
for (User user2 : userList) {
System.out.println(user2.getUserName());
}
也可以直接写入参数
List<User> userList=session.getMapper(UserDao.class).selectByNameRole("张",3);
for (User user2 : userList) {
System.out.println(user2.getUserName());
}
List<User> selectByNameRole(@Param("userName") String userName,@Param("userRole") int userRole);
参数必须添加注解,不然会报错Parameter 'userName' not found.
4.6、resultMap –用来描述数据库结果集和对象的对应关系
返回自定义的resultMap类型,数据库表里的字段名和实体类的不一样,必须要resultMap
id:resultMap的唯一标识
type:Java实体类
操作步骤
1、在User.java类新建一个变量,加上封装
private String userRoleName;
2、在UserMapper.xml文件加上,映射实体类对应的变量
映射的是resultMap,不是resultType,否则会报错Could not resolve type alias 'userMap'.
<resultMap type="User" id="userMap">
<result property="id" column="id"/>
<result property="userRoleName" column="roleName"/>
</resultMap>
<select id="select" resultMap="userMap">
SELECT U.*,R.roleName FROM smbms_user U JOIN smbms_role R ON R.id=U.userRole
</select>
测试类
List<User> userList=session.getMapper(UserDao.class).select();
for (User user : userList) {
System.out.println(user.getUserName()+"\t"+user.getUserRoleName());
}
在全局配置文件加上setting
<settings>
<!--value="PARTIAL半自动映射/NONE不映射/FULL全自动映射" -->
<setting name="autoMappingBehavior" value="NONE"/>
</settings>
4.6.1、resultMap子元素
id一般对应数据库中该行的主键id,设置此项可提高MyBatis性能
result映射到JavaBean的某个“简单类型”属性
association映射到JavaBean的某个“复杂类型”属性,比如JavaBean类
property:映射数据库列的实体对象的属性
column:数据库列名或者别名
在user类里加上private Role role;
在main方法里,可以直接获得复杂对象
User user=new User(); user.getRole().getRoleName();
4.6.2、association映射到JavaBean的某个“复杂类型”属性(集合)
1、在user类里加上private Role role;
2、代码操作
<resultMap type="User" id="userMap">
<id property="id" column="id"/>
<result property="userName" column="userName"/>
<!--<result property="userRoleName" column="roleName"/> -->
<!--property对应的是User类里的role变量javaType是别名,对应的是实体类 -->
<association property="role" javaType="Role">
<!--要查两个数据表都有id,会冲突,所以column起别名 -->
<id property="id" column="r_id"/>
<result property="roleCode" column="roleCode"/>
<result property="roleName" column="roleName"/>
</association>
</resultMap>
<select id="select" resultMap="userMap">
SELECT U.*,R.id r_id,R.roleName,R.roleCode FROM smbms_user U JOIN smbms_role R ON R.id=U.userRole
</select>
测试类
package cn.cwj.smbms.test;
import java.util.List;
import org.apache.ibatis.session.SqlSession;
import cn.cwj.smbms.dao.mybatisUtil.MybatisUtil;
import cn.cwj.smbms.dao.user.UserDao;
import cn.cwj.smbms.pojo.User;
public class testDemo {
public static void main(String[] args) {
SqlSession session=MybatisUtil.createSession();
List<User> userList=session.getMapper(UserDao.class).select();
for (User user : userList) {
System.out.println(user.getUserName()+"\t"+user.getRole().getRoleName());
}
MybatisUtil.closeSession(session);
}
}
3、映射没有加的时候会显示为空
System.out.println(user.getUserName()+"\t"+user.getRole().getRoleName()+"\t"+user.getUserCode());
加上映射后,对应数据就会显示出来
<result property="userCode" column="userCode"/>
半自动映射问题(PARTIAL半自动映射/NONE不映射/FULL全自动映射)
因为写上association元素会自动变成半自动映射
可以去mybatis-config.xml里改成全自动映射
<settings>
<!--value="PARTIAL半自动映射/NONE不映射/FULL全自动映射" -->
<setting name="autoMappingBehavior" value="NONE"/>
</settings>
如果需要多次使用association某种映射,可以再定义一个resultMap子元素,写在外面可以多次复用(用id调用)
4.6.3、多对一collection
1、新建一个接口RoleDao.java和RoleMapper.xml文件
2、在role实体类新增private List<User> users;
并封装
3、注意collection的子元素是ofType
<?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">
<mapper namespace="cn.cwj.smbms.dao.role.RoleDao">
<resultMap type="Role" id="roleMap">
<id property="id" column="id"/>
<result property="roleName" column="roleName"/>
<result property="roleCode" column="roleCode"/>
<collection property="users" ofType="User">
<id property="id" column="u_id"/>
<result property="userCode" column="userCode"/>
<result property="userName" column="userName"/>
</collection>
</resultMap>
<select id="select" resultMap="roleMap">
SELECT R.*,U.id u_id,U.userName,U.userCode FROM smbms_user U JOIN smbms_role R ON R.id=U.userRole
</select>
</mapper>
注意在配置文件加上mpper映射
List<Role> roleList=session.getMapper(RoleDao.class).select();
for (Role role : roleList) {
System.out.println(role.getRoleName());
for (Role role2 : roleList) {
System.out.println("\t"+role2.getUsers().getUserName());
}
}
但是如果每次都查角色下面所有的用户,消耗查询时间和占用内存,所以不建议这样做!
4.7、MyBatis缓存
把数据放在缓存/内存,下次就可以直接在缓存里拿数据
一级缓存无法禁用,默认存在,增删改在会话里,关掉会话则不存在
二级缓存是结果,查询的结果,一般不用,或者用其他的缓存方法,实际中不用MyBatis缓存
然后在映射文件
加上
MyBatis-SQL映射文件总结
5、MyBatis的动态SQL
5.1、if标签-一方传递的参数可为空
UserDao.java接口中创建方法
List<User> selectByNameRole(@Param("userName") String userName,@Param("userRole") Integer userRole);
调用方法的时候传递的参数不一样,SQL语句不一样
<select id="selectByNameRole" resultType="User" >
SELECT * FROM smbms_user
WHERE userName LIKE CONCAT('%',#{userName},'%')
<if test="userRole!=null">AND userRole=#{userRole}</if>
</select>
测试类
List<User> userList=session.getMapper(UserDao.class).selectByNameRole("张",null);
for (User user : userList) {
System.out.println(user.getUserName());
}
5.2、where
如果两个条件都为空或者前面为空或者后面为空,if会报错,此时可以加上where标签
<select id="selectByNameRole" resultType="User" parameterType="User">
SELECT * FROM smbms_user
<where>
<if test="userName!=null and userName!=''">userName LIKE CONCAT('%',#{userName},'%') </if>
<if test="userRole!=null and userRole!=''">AND userRole=#{userRole}</if>
</where>
</select>
此时如果两个传入得参数为null,会把整个表都列出来
List<User> userList=session.getMapper(UserDao.class).selectByNameRole(null,null);
for (User user : userList) {
System.out.println(user.getUserName());
}
where会自动去掉AND和OR
如果传递的值都不为空,则自动去掉第一个AND
和update配合使用
如果不使用where,if标签,进行更新,会把其他不更新的值变为空值
如果加上
<update id="update">
UPDATE smbms_user
<set>
<if test="userCode!=null and userCode!=''">userCode=#{userCode},</if>
<if test="userName!=null and userName!=''">userName=#{userName},</if>
<if test="userPassword!=null and userPassword!=''">userPassword=#{userPassword},</if>
<if test="gender!=null">gender=#{gender},</if>
<if test="birthday!=null">birthday=#{birthday},</if>
<if test="phone!=null and phone!=''">phone=#{phone},</if>
<if test="address!=null and address!=''">address=#{address},</if>
<if test="userRole!=null">userRole=#{userRole},</if>
<if test="modifyBy!=null">modifyBy=#{modifyBy},</if>
<if test="true">modifyDate=NOW(),</if>
<if test="idPicPath!=null and idPicPath!=''">idPicPath=#{idPicPath},</if>
</set>
WHERE id=#{id}
</update>
则可以只修改想要修改的值
5.3、trim
或者可以用trim标签代替where标签,但是要加上前缀prefix
<select id="selectByNameRole" resultType="User" >
SELECT * FROM smbms_user
<trim prefix="WHERE"prefixOverrides="AND/OR">
<if test="userName!=null and userName!=''">AND userName LIKE CONCAT('%',#{userName},'%')</if>
<if test="userRole!=null and userRole!=''">AND userRole=#{userRole}</if>
</trim>
</select>
前面要删除的prefixOverrides="AND/OR"suffix后缀suffixOverride后面要删除的
5.4、set
<update id="update">
UPADTE smbms_user
<set>
<if test="userCode!=null and userCode!=''">userCode=#{userCode},</if>
<if test="userName!=null and userName!=''">userName=#{userName},</if>
<if test="userPassword!=null and userPassword!=''">userPassword=#{userPassword},</if>
<if test="gender!=null">gender=#{gender},</if>
<if test="birthday!=null">birthday=#{birthday},</if>
<if test="phone!=null and phone!=''">phone=#{phone},</if>
<if test="address!=null and address!=''">address=#{address},</if>
<if test="userRole!=null">userRole=#{userRole},</if>
<if test="modifyBy!=null">modifyBy=#{modifyBy},</if>
<if test="true">modifyDate=NOW(),</if>
<if test="idPicPath!=null and idPicPath!=''">idPicPath=#{idPicPath},</if>
</set>
WHERE id=#{id}
</update>
User user = session.getMapper(UserDao.class).selectById(15);
user.setUserName("李33");
int count = session.getMapper(UserDao.class).update(user);
5.5、foreach迭代一个集合,通常用于in条件
属性item、index、collection:必须指定(list、array、map-key)、open、separator、close
数组
在接口里创建一个方法接收数组的参数List<User> listByRoleIds(int[] roleIds);
在UserMapper.xml文件里添加SQL语句
<select id="listByRoleIds" resultType="User">
SELECT * FROM smbms_user
WHERE userRole IN
<foreach collection="array" item="roleId" open="(" close=")" separator=",">
#{roleId}
</foreach>
</select>
测试类
List<User> userList=session.getMapper(UserDao.class).listByRoleIds(new int[] {1, 2});
for (User user : userList) {
System.out.println(user.getUserName());
}
集合
List<User> listByRoleIds(List<Integer> roleIds);
collection="list"改为list
<select id="listByRoleIds" resultType="User">
SELECT * FROM smbms_user
WHERE userRole IN
<foreach collection="list" item="roleId" open="(" close=")" separator=",">
#{roleId}
</foreach>
</select>
List<Integer> list=new ArrayList<Integer>();
list.add(1);
list.add(2);
List<User> userList=session.getMapper(UserDao.class).listByRoleIds(list);
for (User user : userList) {
System.out.println(user.getUserName());
}
map
List<User> listByRoleIds(Map<String,Object> roleIds);
<select id="listByRoleIds" resultType="User">
SELECT * FROM smbms_user
WHERE userRole IN
<foreach collection="xxx" item="roleId" open="(" close=")" separator=",">
#{roleId}
</foreach>
</select>
List<Integer> list=new ArrayList<Integer>();
list.add(1);
list.add(2);
Map<String,Object> map=new HashMap<String,Object>();
map.put("xxx", list);
List<User> userList=session.getMapper(UserDao.class).listByRoleIds(map);
for (User user : userList) {
System.out.println(user.getUserName());
}
xxx是键值对的键,可以任意起名
5.6、choose相当于Java中switch语句(互斥)
当when有条件满足的时候,就跳出choose,这些条件是互斥的,只有一个符合
List<User> listByCondition(@Param("id")Integer id,@Param("userCode")String userCode,@Param("userName")String userName);
<select id="listByCondition" resultType="User">
SELECT * FROM smbms_user
WHERE
<choose>
<when test="id!=null">id=#{id}</when>
<when test="userCode!=null and userCode!=''">userCode=#{userCode}</when>
<when test="userName!=null and userName!=''">userName LIKE CONCAT('%',#{userName},'%')</when>
<!-- 如果上面情况都不符合,则查询全部,因为1=1为true -->
<otherwise>1=1</otherwise>
</choose>
</select>
List<User> userList=session.getMapper(UserDao.class).listByCondition(1, null, "张");
for (User user : userList) {
System.out.println(user.getUserName());
}
但是这里需要注意,只要一个条件符合就会匹配
比如此时的查询结果是
5.7、分页查询
<select id="listByPage" resultType="User">
SELECT * FROM smbms_user
<where>
<if test="user.id!=null">id=#{user.id}</if>
<if test="user.userCode!=null and user.userCode!=''">userCode=#{user.userCode}</if>
<if test="user.userName!=null and user.userName!=''">userName LIKE CONCAT('%',#{user.userName},'%')</if>
</where>
LIMIT #{from},#{pageSize}
</select>
5.8、sql标签-可能会重复使用的SQL语句
<select id="listByPage" resultType="User">
SELECT * FROM smbms_user
<include refid="condition1"></include>
LIMIT #{from},#{pageSize}
</select>
<sql id="condition1">
<where>
<if test="user.id!=null">id=#{user.id}</if>
<if test="user.userCode!=null and user.userCode!=''">userCode=#{user.userCode}</if>
<if test="user.userName!=null and user.userName!=''">userName LIKE CONCAT('%',#{user.userName},'%')</if>
</where>
</sql>