目录
Mybatis详解
Mybatis图解
打印执行SQL语句日志
<settings>
<!-- 打印查询语句 -->
<setting name="logImpl" value="STDOUT_LOGGING" />
</settings>
Mybatis入门程序
1.项目列表
2.Mybatis配置 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>
<environments default="development">
<environment id="development">
<!-- 使用JDBC事务管理,事务控制由mybatis管理 -->
<transactionManager type="JDBC" />
<!-- 数据库连接池,由mybatis管理 -->
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=UTF-8"/>
<property name="username" value="root"/>
<property name="password" value="123456"/>
</dataSource>
</environment>
</environments>
<!--加入映射文件-->
<mappers>
<mapper resource="config/mybatisMapper/user.xml" />
</mappers>
</configuration>
2.Mybatis日志配置 log4j.properties文件
# Global logging configuration
# developer-->DEBUG product-->INFO or ERROR
#开发环境DEBUG,生产环境info或error
#log4j.rootLogger=info, stdout
log4j.rootLogger=DEBUG, stdout
#log4j.logger.org.mybatis.example.BlogMapper=TRACE
# 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
3.编写UserInfo对象和user.xml
1)UserInfo.java
package com.xieli.liu.pojo;
import java.util.Date;
/**
* 用户表
* @filename UserInfo.java
* @author hm
* @date 2018年6月26日下午3:03:14
*/
public class UserInfo {
private Integer userId;//用户id
private String userName;//用户名
private String nickName;//昵称
private String userPwd;//用户密码
public Integer getUserId() {
return userId;
}
public void setUserId(Integer userId) {
this.userId = userId;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName == null ? null : userName.trim();
}
public String getNickName() {
return nickName;
}
public void setNickName(String nickName) {
this.nickName = nickName == null ? null : nickName.trim();
}
public String getUserPwd() {
return userPwd;
}
public void setUserPwd(String userPwd) {
this.userPwd = userPwd == null ? null : userPwd.trim();
}
}
2)user.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="test">
<!-- 查询数据库所有用户信息,用来测试数据库是否连接上 -->
<select id="selectAll" parameterType="int" resultType="com.xieli.liu.pojo.UserInfo">
select user_id userId, user_name userName,nick_name nickName,user_pwd userPwd from User_info where user_id=#{VALUE}
</select>
</mapper>
4.编写测试类test.java
package com.xieli.liu;
import com.xieli.liu.pojo.UserInfo;
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 java.io.IOException;
import java.io.InputStream;
/**
* Created by Administrator on 2019-11-20.
*/
public class test {
public static void main(String arg[]) {
SqlSessionFactory sessionFactory;
//使用MyBatis提供的Resources类加载mybatis的配置文件
try {
InputStream resourceAsStream = Resources.getResourceAsStream("config/sqlMapConfig.xml");
//构建sqlSession的工厂
sessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);
SqlSession sqlSession = sessionFactory.openSession();
UserInfo userInfo=sqlSession.selectOne("test.selectAll",1);
System.out.println(userInfo.getUserId()+":"+userInfo.getUserName()+"......."+userInfo.getUserPwd());
sqlSession.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
运行结果
5.注意事项
对数据库进行非查询操作时需要提交数据
Mybatis插入数据时对自增ID返回(MySQL中LAST_INSERT_ID()可以查询插入数据条数)
1)MySQL
2)oracle
非主键自增
SqlSession是线程不安全的,只能写在方法体类
Mybatis mapper代理方式
1.规范
1)mapper.xml中namespace等于mapper接口的地址
2)mapper.java接口的方法名和mapper.xml中statement的id一致
3)mapper.java接口的方法输入参数类型和mapper.xml中statement的parameterType指定的类型一致
4)mapper.java接口的方法返回值类型和mapper.xml中statement的resultType类型一致
2.注意事项
3.typeAliases别名
<?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>
<typeAliases>
<typeAlias type="com.xieli.liu.pojo.UserInfo" alias="userInfo"></typeAlias>
<!-- 通过package, 可以直接指定package的名字,
mybatis会自动扫描你指定包下面的javabean, 并且默认设置一个别名,
默认的名字为: javabean 的首字母小写的非限定类名来作为它的别名 -->
<!-- <package name="com.xieli.liu.pojo" />-->
</typeAliases>
</configuration>
4.mappers(映射器)
Mappers 标签是用来加载映射文件的,可通过下列四种方式加载映射文件
(1)通过resource加载单个mapper
<!-- 通过resource加载 -->
<mapper resource="config/sqlmap/User.xml" />
(2)通过使用完全限定路径
<!-- 通过url加载 -->
<mapper url="config/sqlmap/User.xml" />
(3)通过mapper接口加载单个mapper
<!-- 通过mapper接口加载,但需要将接口名和映射文件名保存一致,且在同一目录 -->
<mapper class="com.dao.UserDao"/>
(4)批量加载mapper(推荐使用)
<!-- 需要将接口名和映射文件名保存一致,且在同一目录 -->
<!-- 批量加载 -->
<package name="com.po"/>
动态SQL
<!-- 查询用户列表 分页 -->
<select id="selectUserInfo" parameterType="java.util.HashMap"
resultMap="userInfo">
select * from user_info
<where>
is_delete='0'
<if test="userInfo.userName!=null and userInfo.userName!=''">
and
user_name like "%"#{userInfo.userName}"%"
</if>
<if test="userInfo.userState!=null and userInfo.userState!=''">
and user_state like "%"#{userInfo.userState}"%"
</if>
<if test="userInfo.createTime!=null and userInfo.createTime!=''">
and (create_time > #{userInfo.createTime}
or
create_time like concat(#{userInfo.createTime},'%'))
</if>
<if test="createTime1!=null and createTime1!=''">
and (create_time < #{createTime1}
or create_time like
concat(#{createTime1},'%'))
</if>
</where>
order by update_time desc
<if test="imports==null or imports==''">
limit #{pageBean.pageIndex},#{pageBean.page}
</if>
</select>
对象关系映射ORM(一对一,一对多)
pojo层代码
用户信息
package com.xieli.liu.pojo;
import java.util.Date;
import java.util.List;
/**
* 用户表
* @filename UserInfo.java
* @author hm
* @date 2018年6月26日下午3:03:14
*/
public class UserInfo {
private Integer userId;//用户id
private String userName;//用户名
private String nickName;//昵称
private String userCode;//用户登录code
private String userPwd;//用户密码
private String userType;//用户类型
private String userState;//用户状态
private String isDelete;//删除状态
private Integer createBy;//创建人
private Date createTime;//创建时间
private Integer udateBy;//修改人
private Date updateTime;//修改时间
private Date createTime1;
private UserGroup userGroup;
private List<Role> roles;
public List<Role> getRoles() {
return roles;
}
public void setRoles(List<Role> roles) {
this.roles = roles;
}
public UserGroup getUserGroup() {
return userGroup;
}
public void setUserGroup(UserGroup userGroup) {
this.userGroup = userGroup;
}
public Date getCreateTime1() {
return createTime1;
}
public void setCreateTime1(Date createTime1) {
this.createTime1 = createTime1;
}
public Integer getUserId() {
return userId;
}
public void setUserId(Integer userId) {
this.userId = userId;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName == null ? null : userName.trim();
}
public String getNickName() {
return nickName;
}
public void setNickName(String nickName) {
this.nickName = nickName == null ? null : nickName.trim();
}
public String getUserCode() {
return userCode;
}
public void setUserCode(String userCode) {
this.userCode = userCode == null ? null : userCode.trim();
}
public String getUserPwd() {
return userPwd;
}
public void setUserPwd(String userPwd) {
this.userPwd = userPwd == null ? null : userPwd.trim();
}
public String getUserType() {
return userType;
}
public void setUserType(String userType) {
this.userType = userType == null ? null : userType.trim();
}
public String getUserState() {
return userState;
}
public void setUserState(String userState) {
this.userState = userState == null ? null : userState.trim();
}
public String getIsDelete() {
return isDelete;
}
public void setIsDelete(String isDelete) {
this.isDelete = isDelete == null ? null : isDelete.trim();
}
public Integer getCreateBy() {
return createBy;
}
public void setCreateBy(Integer createBy) {
this.createBy = createBy;
}
public Date getCreateTime() {
return createTime;
}
public void setCreateTime(Date createTime) {
this.createTime = createTime;
}
public Integer getUdateBy() {
return udateBy;
}
public void setUdateBy(Integer udateBy) {
this.udateBy = udateBy;
}
public Date getUpdateTime() {
return updateTime;
}
public void setUpdateTime(Date updateTime) {
this.updateTime = updateTime;
}
}
角色信息
package com.xieli.liu.pojo;
import java.util.Date;
/**
* 角色表
* @filename Role.java
* @author hm
* @date 2018年6月26日下午3:04:11
*/
public class Role {
private Integer roleId;//角色id
private String roleName;//角色名称
private String roleDesc;//角色描述
private String roleCode;//角色代码
private String roleState;//角色状态
private Integer createBy;//创建人
private Date createTime;//创建时间
private Integer udateBy;//修改人
private Date updateTime;//修改时间
private Date createTime2;//创建时间
public Date getCreateTime2() {
return createTime2;
}
public void setCreateTime2(Date createTime2) {
this.createTime2 = createTime2;
}
public Integer getRoleId() {
return roleId;
}
public void setRoleId(Integer roleId) {
this.roleId = roleId;
}
public String getRoleName() {
return roleName;
}
public void setRoleName(String roleName) {
this.roleName = roleName == null ? null : roleName.trim();
}
public String getRoleDesc() {
return roleDesc;
}
public void setRoleDesc(String roleDesc) {
this.roleDesc = roleDesc == null ? null : roleDesc.trim();
}
public String getRoleCode() {
return roleCode;
}
public void setRoleCode(String roleCode) {
this.roleCode = roleCode == null ? null : roleCode.trim();
}
public String getRoleState() {
return roleState;
}
public void setRoleState(String roleState) {
this.roleState = roleState == null ? null : roleState.trim();
}
public Integer getCreateBy() {
return createBy;
}
public void setCreateBy(Integer createBy) {
this.createBy = createBy;
}
public Date getCreateTime() {
return createTime;
}
public void setCreateTime(Date createTime) {
this.createTime = createTime;
}
public Integer getUdateBy() {
return udateBy;
}
public void setUdateBy(Integer udateBy) {
this.udateBy = udateBy;
}
public Date getUpdateTime() {
return updateTime;
}
public void setUpdateTime(Date updateTime) {
this.updateTime = updateTime;
}
@Override
public String toString() {
return "Role [roleId=" + roleId + ", roleName=" + roleName
+ ", roleDesc=" + roleDesc + ", roleCode=" + roleCode
+ ", roleState=" + roleState + ", createBy=" + createBy
+ ", createTime=" + createTime + ", udateBy=" + udateBy
+ ", updateTime=" + updateTime + ", createTime2=" + createTime2
+ "]";
}
}
用户组信息
package com.xieli.liu.pojo;
/**
* 用户组
* @filename UserGroup.java
* @author hm
* @date 2018年6月26日下午3:06:38
*/
public class UserGroup {
private Integer groupId;//用户组id
private String groupName;//用户组名称
private String groupCode;//用户组code
private String groupDesc;//用户组描述
private String groupState;//用户组状态
public Integer getGroupId() {
return groupId;
}
public void setGroupId(Integer groupId) {
this.groupId = groupId;
}
public String getGroupName() {
return groupName;
}
public void setGroupName(String groupName) {
this.groupName = groupName == null ? null : groupName.trim();
}
public String getGroupCode() {
return groupCode;
}
public void setGroupCode(String groupCode) {
this.groupCode = groupCode == null ? null : groupCode.trim();
}
public String getGroupDesc() {
return groupDesc;
}
public void setGroupDesc(String groupDesc) {
this.groupDesc = groupDesc == null ? null : groupDesc.trim();
}
public String getGroupState() {
return groupState;
}
public void setGroupState(String groupState) {
this.groupState = groupState == null ? null : groupState.trim();
}
@Override
public String toString() {
return "UserGroup [groupId=" + groupId + ", groupName=" + groupName
+ ", groupCode=" + groupCode + ", groupDesc=" + groupDesc
+ ", groupState=" + groupState + "]";
}
}
DAO层代码
package com.xieli.liu.dao;
import com.xieli.liu.pojo.UserInfo;
import java.util.List;
/**
*
* @filename UserInfoMapper.java
* @author hm
* @date 2018年7月3日下午3:22:20
*/
public interface UserInfoMapper {
/**
*
*@返回类型:UserInfo
*@方法功能:测试查询用户列表
*/
public UserInfo selectAll(int id) throws Exception;
/**
*
*@返回类型:int
*@方法功能: 新增用户
*/
public int addUserInfo(UserInfo userInfo)throws Exception;
public List<UserInfo> selectUSERAndGroup() throws Exception;
public List<UserInfo> selectUserInfoAndRole() throws Exception;
}
<?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="com.xieli.liu.dao.UserInfoMapper">
<resultMap id="userInfoResultMap" type="UserInfo">
<id column="user_id" property="userId" />
<result column="user_name" property="userName" />
<result column="nick_name" property="nickName" />
<result column="user_code" property="userCode" />
<result column="user_pwd" property="userPwd" />
<result column="user_type" property="userType" />
<result column="user_state" property="userState" />
<result column="is_delete" property="isDelete" />
<result column="create_by" property="createBy" />
<result column="create_time" property="createTime" />
<result column="udate_by" property="udateBy" />
<result column="update_time" property="updateTime" />
<association property="userGroup" javaType="UserGroup" >
<id column="group_id " property="groupId"/>
<result column="group_name" property="groupName" />
<result column="group_code" property="groupCode" />
<result column="group_desc" property="groupDesc" />
<result column="group_state" property="groupState" />
</association>
</resultMap>
<resultMap id="userInfoAndRoleResultMap" type="UserInfo" extends="userInfoResultMap">
<collection property="roles" ofType="Role">
<id column="role_id" property="roleId" />
<result column="role_name" property="roleName" />
<result column="role_desc" property="roleDesc" />
<result column="role_code" property="roleCode" />
<result column="role_state" property="roleState" />
<result column="create_by" property="createBy" />
<result column="create_time" property="createTime" />
<result column="udate_by" property="udateBy" />
<result column="update_time" property="updateTime" />
</collection>
</resultMap>
<!-- 查询数据库所有用户信息,用来测试数据库是否连接上 -->
<select id="selectAll" parameterType="int" resultType="userInfo">
select user_id userId, user_name userName,nick_name nickName,user_pwd userPwd from User_info where user_id=#{VALUE}
</select>
<insert id="addUserInfo" parameterType="UserInfo">
INSERT INTO user_info(user_name,user_pwd) values(#{userName},MD5(#{userPwd}))
<selectKey keyProperty="user_id" order="AFTER" resultType="java.lang.Integer">
SELECT LAST_INSERT_ID()
</selectKey>
</insert>
<!--查询用户和其用户组信息-->
<select id="selectUSERAndGroup" resultMap="userInfoResultMap">
SELECT user_info.`user_name`,user_info.`user_pwd`,user_group.`group_name`,user_group.`group_state` FROM `user_info` ,`user_group` WHERE user_info.`group_id`=user_group.`group_id`
</select>
<!--查询用户和其用户组以及用户拥有的角色信息-->
<select id="selectUserInfoAndRole" resultMap="userInfoAndRoleResultMap">
SELECT user_info.user_id, user_info.`user_name`,user_group.`group_name`,user_group.`group_code`,role.`role_id`,role.`role_name`,role.`role_code`
FROM `user_info`
LEFT JOIN `user_group` ON user_info.`group_id`=user_group.`group_id`
LEFT JOIN `user_role` ON user_role.`user_id`=user_info.`user_id`
LEFT JOIN `role` ON role.`role_id`=user_role.`role_id`
</select>
</mapper>
测试代码
public static void main(String arg[]) {
SqlSessionFactory sessionFactory;
//使用MyBatis提供的Resources类加载mybatis的配置文件
try {
InputStream resourceAsStream = Resources.getResourceAsStream("config/sqlMapConfig.xml");
//构建sqlSession的工厂
sessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);
SqlSession sqlSession = sessionFactory.openSession();
UserInfoMapper mapper = sqlSession.getMapper(UserInfoMapper.class);
List<UserInfo> userInfos = mapper.selectUserInfoAndRole();
sqlSession.close();
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
测试结果
注意事项
唯一识别<id column="user_id" property="userId" />
在SQL必须出现否则<collection property="roles" ofType="Role">
将会失效 private List roles;只会存在一条数据
延迟加载
1.开启延迟加载
在Mybatis配置文件中加入如下代码
<settings>
<setting name="lazyLoadingEnabled" value="true"/>
<setting name="aggressiveLazyLoading" value="false"/>
<setting name="lazyLoadTriggerMethods" value="true"/>
</settings>
注意<settings>
必须放在<configuration>
中的首位
<?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>
<settings>
<setting name="lazyLoadingEnabled" value="true"/>
<setting name="aggressiveLazyLoading" value="false"/>
<setting name="lazyLoadTriggerMethods" value="true"/>
</settings>
<typeAliases>
<!-- <typeAlias type="com.xieli.liu.pojo.UserInfo" alias="userInfo"></typeAlias>-->
<!-- 通过package, 可以直接指定package的名字,
mybatis会自动扫描你指定包下面的javabean, 并且默认设置一个别名,
默认的名字为: javabean 的首字母小写的非限定类名来作为它的别名 -->
<package name="com.xieli.liu.pojo" />
</typeAliases>
<environments default="development">
<environment id="development">
<!-- 使用JDBC事务管理,事务控制由mybatis管理 -->
<transactionManager type="JDBC" />
<!-- 数据库连接池,由mybatis管理 -->
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=UTF-8"/>
<property name="username" value="root"/>
<property name="password" value="123456"/>
</dataSource>
</environment>
</environments>
<!--加入映射文件-->
<mappers>
<!-- <mapper resource="config/mybatisMapper/user.xml" />-->
<package name="com.xieli.liu.dao"/>
</mappers>
</configuration>
2.编码部分
Javabeen
package com.xieli.liu.pojo;
import java.util.Date;
import java.util.List;
/**
* 用户表
* @filename UserInfo.java
* @author hm
* @date 2018年6月26日下午3:03:14
*/
public class UserInfo {
private Integer userId;//用户id
private Integer groupId;//用户组id
private String userName;//用户名
private String nickName;//昵称
private String userCode;//用户登录code
private String userPwd;//用户密码
private String userType;//用户类型
private String userState;//用户状态
private String isDelete;//删除状态
private Integer createBy;//创建人
private Date createTime;//创建时间
private Integer udateBy;//修改人
private Date updateTime;//修改时间
private Date createTime1;
private UserGroup userGroup;
public UserGroup getUserGroup() {
return userGroup;
}
public void setUserGroup(UserGroup userGroup) {
this.userGroup = userGroup;
}
public Date getCreateTime1() {
return createTime1;
}
public Integer getGroupId() {
return groupId;
}
public void setGroupId(Integer groupId) {
this.groupId = groupId;
}
public void setCreateTime1(Date createTime1) {
this.createTime1 = createTime1;
}
public Integer getUserId() {
return userId;
}
public void setUserId(Integer userId) {
this.userId = userId;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName == null ? null : userName.trim();
}
public String getNickName() {
return nickName;
}
public void setNickName(String nickName) {
this.nickName = nickName == null ? null : nickName.trim();
}
public String getUserCode() {
return userCode;
}
public void setUserCode(String userCode) {
this.userCode = userCode == null ? null : userCode.trim();
}
public String getUserPwd() {
return userPwd;
}
public void setUserPwd(String userPwd) {
this.userPwd = userPwd == null ? null : userPwd.trim();
}
public String getUserType() {
return userType;
}
public void setUserType(String userType) {
this.userType = userType == null ? null : userType.trim();
}
public String getUserState() {
return userState;
}
public void setUserState(String userState) {
this.userState = userState == null ? null : userState.trim();
}
public String getIsDelete() {
return isDelete;
}
public void setIsDelete(String isDelete) {
this.isDelete = isDelete == null ? null : isDelete.trim();
}
public Integer getCreateBy() {
return createBy;
}
public void setCreateBy(Integer createBy) {
this.createBy = createBy;
}
public Date getCreateTime() {
return createTime;
}
public void setCreateTime(Date createTime) {
this.createTime = createTime;
}
public Integer getUdateBy() {
return udateBy;
}
public void setUdateBy(Integer udateBy) {
this.udateBy = udateBy;
}
public Date getUpdateTime() {
return updateTime;
}
public void setUpdateTime(Date updateTime) {
this.updateTime = updateTime;
}
}
package com.xieli.liu.pojo;
/**
* 用户组
* @filename UserGroup.java
* @author hm
* @date 2018年6月26日下午3:06:38
*/
public class UserGroup {
private Integer groupId;//用户组id
private String groupName;//用户组名称
private String groupCode;//用户组code
private String groupDesc;//用户组描述
private String groupState;//用户组状态
public Integer getGroupId() {
return groupId;
}
public void setGroupId(Integer groupId) {
this.groupId = groupId;
}
public String getGroupName() {
return groupName;
}
public void setGroupName(String groupName) {
this.groupName = groupName == null ? null : groupName.trim();
}
public String getGroupCode() {
return groupCode;
}
public void setGroupCode(String groupCode) {
this.groupCode = groupCode == null ? null : groupCode.trim();
}
public String getGroupDesc() {
return groupDesc;
}
public void setGroupDesc(String groupDesc) {
this.groupDesc = groupDesc == null ? null : groupDesc.trim();
}
public String getGroupState() {
return groupState;
}
public void setGroupState(String groupState) {
this.groupState = groupState == null ? null : groupState.trim();
}
}
mapper.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="com.xieli.liu.dao.UserInfoMapper">
<resultMap id="userInfoResultMap" type="UserInfo">
<id column="user_id" property="userId" />
<result column="group_id" property="groupId" />
<result column="user_name" property="userName" />
<result column="nick_name" property="nickName" />
<result column="user_code" property="userCode" />
<result column="user_pwd" property="userPwd" />
<result column="user_type" property="userType" />
<result column="user_state" property="userState" />
<result column="is_delete" property="isDelete" />
<result column="create_by" property="createBy" />
<result column="create_time" property="createTime" />
<result column="udate_by" property="udateBy" />
<result column="update_time" property="updateTime" />
<association property="userGroup" javaType="UserGroup" select="com.xieli.liu.dao.UserGroupMapper.selectUserGroupById" column="group_id">
</association>
</resultMap>
<!-- 查询数据库所有用户信息,用来测试数据库是否连接上 -->
<select id="selectAll" resultMap="userInfoResultMap">
select * from User_info
</select>
</mapper>
<?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="com.xieli.liu.dao.UserGroupMapper" >
<resultMap id="BaseResultMap" type="UserGroup" >
<id column="group_id" property="groupId" />
<result column="group_name" property="groupName" />
<result column="group_code" property="groupCode" />
<result column="group_desc" property="groupDesc" />
<result column="group_state" property="groupState" />
</resultMap>
<!-- 查询所有用户组信息 -->
<select id="selectUserGroupById" parameterType="int" resultMap="BaseResultMap">
SELECT * FROM user_group where user_group.group_id=#{VALUE}
</select>
</mapper>
测试代码
package com.xieli.liu;
import com.xieli.liu.dao.UserInfoMapper;
import com.xieli.liu.pojo.Role;
import com.xieli.liu.pojo.UserInfo;
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 java.io.IOException;
import java.io.InputStream;
import java.util.List;
/**
* Created by Administrator on 2019-11-20.
*/
public class test {
public static void main(String arg[]) {
SqlSessionFactory sessionFactory;
//使用MyBatis提供的Resources类加载mybatis的配置文件
try {
InputStream resourceAsStream = Resources.getResourceAsStream("config/sqlMapConfig.xml");
//构建sqlSession的工厂
sessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);
SqlSession sqlSession = sessionFactory.openSession();
UserInfoMapper mapper = sqlSession.getMapper(UserInfoMapper.class);
List<UserInfo> userInfos = mapper.selectAll();
for (UserInfo userInfo: userInfos) {
if (userInfo.getUserGroup() == null) {
System.out.println(userInfo.getUserName());
}else {
System.out.println(userInfo.getUserName()+"......"+userInfo.getUserGroup().getGroupName());
}
}
sqlSession.close();
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
}
3.效果展示
SQL执行完后userInfo中tUserGroup属性并没有值
当准备调用userInfo.getUserGroup()时才会去执行延迟加载的SQL,此时userInfo中UserGroup属性已经有值
缓存(一级缓存,二级缓存)
缓存图解
一级缓存(SqlSession,Mybatis默认开启)
一级缓存图解
测试代码
1)查询过程中没有对数据库进行操作
package com.xieli.liu;
import com.xieli.liu.dao.UserInfoMapper;
import com.xieli.liu.pojo.Role;
import com.xieli.liu.pojo.UserInfo;
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 org.junit.Test;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
/**
* Created by Administrator on 2019-11-20.
*/
public class test {
@Test
public void test() {
SqlSessionFactory sessionFactory;
//使用MyBatis提供的Resources类加载mybatis的配置文件
try {
InputStream resourceAsStream = Resources.getResourceAsStream("config/sqlMapConfig.xml");
//构建sqlSession的工厂
sessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);
SqlSession sqlSession = sessionFactory.openSession();
SqlSession sqlSession2 = sessionFactory.openSession();
SqlSession sqlSession3 = sessionFactory.openSession();
//发起第一次查询
UserInfoMapper mapper = sqlSession.getMapper(UserInfoMapper.class);
List<UserInfo> userInfos = mapper.selectAll();
for (UserInfo userInfo: userInfos) {
System.out.println(userInfo.getUserName());
}
System.out.println("第一次查询结果打印结束-------------------------------------------------------------");
List<UserInfo> userInfos2 = mapper.selectAll();
for (UserInfo userInfo: userInfos2) {
System.out.println(userInfo.getUserName());
}
//写入二级缓存
sqlSession.close();
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
}
2)查询过程中对数据库进行操作
package com.xieli.liu;
import com.xieli.liu.dao.UserInfoMapper;
import com.xieli.liu.pojo.Role;
import com.xieli.liu.pojo.UserInfo;
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 org.junit.Test;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
/**
* Created by Administrator on 2019-11-20.
*/
public class test {
@Test
public void test() {
SqlSessionFactory sessionFactory;
//使用MyBatis提供的Resources类加载mybatis的配置文件
try {
InputStream resourceAsStream = Resources.getResourceAsStream("config/sqlMapConfig.xml");
//构建sqlSession的工厂
sessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);
SqlSession sqlSession = sessionFactory.openSession();
SqlSession sqlSession2 = sessionFactory.openSession();
SqlSession sqlSession3 = sessionFactory.openSession();
//发起第一次查询
UserInfoMapper mapper = sqlSession.getMapper(UserInfoMapper.class);
List<UserInfo> userInfos = mapper.selectAll();
for (UserInfo userInfo: userInfos) {
System.out.println(userInfo.getUserName());
}
System.out.println("对数据进行操作。。。。。。。。。。。。。。。。。。。。");
UserInfo userInfo2=new UserInfo();
userInfo2.setUserState("1");
mapper.updateStatics(userInfo2);
System.out.println("第二次查询结果打印开始-------------------------------------------------------------");
List<UserInfo> userInfos2 = mapper.selectAll();
for (UserInfo userInfo: userInfos2) {
System.out.println(userInfo.getUserName());
}
//写入二级缓存
sqlSession.close();
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
}
总结:
1)Mybatis自动开启
2)同一SqlSession下查询相同的SQL时,第一次查询执行SQL并放入SqlSession缓存,第二次以后直接从缓存取,不再执行SQL
3)如果存在对数据库commit操作,SqlSession会清空,下次读取时重新执行SQL
4)在spring中执行两次service调用相同的SQL,不走一级缓存(弊端)
二级缓存(mapper,namespace来区分)
二级缓存图解
开启二级缓存
1)设置Mybatis配置文件
<?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>
<settings>
<!--开启二级缓存-->
<setting name="cacheEnabled" value="true"/>
</settings>
<typeAliases>
<package name="com.xieli.liu.pojo" />
</typeAliases>
<environments default="development">
<environment id="development">
<!-- 使用JDBC事务管理,事务控制由mybatis管理 -->
<transactionManager type="JDBC" />
<!-- 数据库连接池,由mybatis管理 -->
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=UTF-8"/>
<property name="username" value="root"/>
<property name="password" value="123456"/>
</dataSource>
</environment>
</environments>
<!--加入映射文件-->
<mappers>
<package name="com.xieli.liu.dao"/>
</mappers>
</configuration>
2)设置mapper.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="com.xieli.liu.dao.UserInfoMapper">
<!--开启二级缓存-->
<cache/>
<resultMap id="userInfoResultMap" type="UserInfo">
<id column="user_id" property="userId" />
<result column="group_id" property="groupId" />
<result column="user_name" property="userName" />
<result column="nick_name" property="nickName" />
<result column="user_code" property="userCode" />
<result column="user_pwd" property="userPwd" />
<result column="user_type" property="userType" />
<result column="user_state" property="userState" />
<result column="is_delete" property="isDelete" />
<result column="create_by" property="createBy" />
<result column="create_time" property="createTime" />
<result column="udate_by" property="udateBy" />
<result column="update_time" property="updateTime" />
</resultMap>
<!-- 查询数据库所有用户信息,用来测试数据库是否连接上 -->
<select id="selectAll" resultMap="userInfoResultMap">
select * from User_info
</select>
</mapper>
3)实体类UserInfo实现序列化
测试代码
1)不同的sqlSession执行同一SQL
package com.xieli.liu;
import com.xieli.liu.dao.UserInfoMapper;
import com.xieli.liu.pojo.Role;
import com.xieli.liu.pojo.UserInfo;
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 java.io.IOException;
import java.io.InputStream;
import java.util.List;
/**
* Created by Administrator on 2019-11-20.
*/
public class test {
public static void main(String arg[]) {
SqlSessionFactory sessionFactory;
//使用MyBatis提供的Resources类加载mybatis的配置文件
try {
InputStream resourceAsStream = Resources.getResourceAsStream("config/sqlMapConfig.xml");
//构建sqlSession的工厂
sessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);
SqlSession sqlSession = sessionFactory.openSession();
SqlSession sqlSession2 = sessionFactory.openSession();
SqlSession sqlSession3 = sessionFactory.openSession();
UserInfoMapper mapper = sqlSession.getMapper(UserInfoMapper.class);
List<UserInfo> userInfos = mapper.selectAll();
for (UserInfo userInfo: userInfos) {
System.out.println(userInfo.getUserName());
}
//写入二级缓存
sqlSession.close();
UserInfoMapper mapper2 = sqlSession2.getMapper(UserInfoMapper.class);
//发起第二次查询
List<UserInfo> userInfos2 =mapper2.selectAll();
for (UserInfo userInfo: userInfos2) {
System.out.println(userInfo.getUserName());
}
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
}
结果总结:
第二次查询没有执行SQL,直接从二级缓存中获取
2)不同的sqlSession执行同一SQL,中间夹杂对数据库的操作
package com.xieli.liu;
import com.xieli.liu.dao.UserInfoMapper;
import com.xieli.liu.pojo.Role;
import com.xieli.liu.pojo.UserInfo;
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 java.io.IOException;
import java.io.InputStream;
import java.util.List;
/**
* Created by Administrator on 2019-11-20.
*/
public class test {
public static void main(String arg[]) {
SqlSessionFactory sessionFactory;
//使用MyBatis提供的Resources类加载mybatis的配置文件
try {
InputStream resourceAsStream = Resources.getResourceAsStream("config/sqlMapConfig.xml");
//构建sqlSession的工厂
sessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);
SqlSession sqlSession = sessionFactory.openSession();
SqlSession sqlSession2 = sessionFactory.openSession();
SqlSession sqlSession3 = sessionFactory.openSession();
//发起第一次查询
UserInfoMapper mapper = sqlSession.getMapper(UserInfoMapper.class);
List<UserInfo> userInfos = mapper.selectAll();
for (UserInfo userInfo: userInfos) {
System.out.println(userInfo.getUserName());
}
//写入二级缓存
sqlSession.close();
//对数据库进行操作
UserInfoMapper mapper3 = sqlSession3.getMapper(UserInfoMapper.class);
UserInfo u=new UserInfo();
u.setUserState("1");
mapper3.updateStatics(u);
sqlSession3.commit();
sqlSession3.close();
//发起第二次查询
UserInfoMapper mapper2 = sqlSession2.getMapper(UserInfoMapper.class);
List<UserInfo> userInfos2 =mapper2.selectAll();
for (UserInfo userInfo: userInfos2) {
System.out.println(userInfo.getUserName());
}
sqlSession2.close();
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
}
结果总结:
对数据库操作会清空二级缓存。
第二次查询执行SQL,没有从二级缓存中获取。
禁用二级缓存
<select id="selectAll" resultMap="userInfoResultMap" useCache="false">
select * from User_info
</select>
清空缓存
<select id="selectAll" resultMap="userInfoResultMap" flushCache="true">
select * from User_info
</select>
清空缓存,不是重新从数据库复制数据
Mybatis整合ehcache
加入jar包
二级缓存必须开启
创建ehcahce.xml
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="../config/ehcache.xsd">
<!--<diskStore path="java.io.tmpdir" />-->
<defaultCache
maxElementsInMemory="10000"
maxElementsOnDisk="10000000"
eternal="false"
timeToIdleSeconds="120"
timeToLiveSeconds="120"
overflowToDisk="true"
diskPersistent="false"
diskExpiryThreadIntervalSeconds="120"
memoryStoreEvictionPolicy="LRU" />
<!--
name:Cache的唯一标识
maxElementsInMemory:内存中最大缓存对象数
maxElementsOnDisk:磁盘中最大缓存对象数,若是0表示无穷大
eternal:Element是否永久有效,一但设置了,timeout将不起作用
overflowToDisk:配置此属性,当内存中Element数量达到maxElementsInMemory时,Ehcache将会Element写到磁盘中
timeToIdleSeconds:设置Element在失效前的允许闲置时间。仅当element不是永久有效时使用,可选属性,默认值是0,也就是可闲置时间无穷大
timeToLiveSeconds:设置Element在失效前允许存活时间。最大时间介于创建时间
和失效时间之间。仅当element不是永久有效时使用,默认是0.,也就是element存活时间无穷大
diskPersistent:是否缓存虚拟机重启期数据
diskExpiryThreadIntervalSeconds:磁盘失效线程运行时间间隔,默认是120秒
diskSpoolBufferSizeMB:这个参数设置DiskStore(磁盘缓存)的缓存区大小。默认是30MB。每个Cache都应该有自己的一个缓冲区
memoryStoreEvictionPolicy:当达到maxElementsInMemory限制时,Ehcache将会根据指定的策略去清理内存。默认策略是LRU(最近最少使用)。你可以设置为FIFO(先进先出)或是LFU(较少使用)
-->
</ehcache>
我使用的是IDEA2017存在报错
处理报错
添加如图上图所示的内容http://ehcache.org/ehcache.xsd
修改ehcahce.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="com.xieli.liu.dao.UserInfoMapper">
<!--开启二级缓存-->
<cache type="org.mybatis.caches.ehcache.EhcacheCache"/>
<resultMap id="userInfoResultMap" type="UserInfo">
<id column="user_id" property="userId" />
<result column="group_id" property="groupId" />
<result column="user_name" property="userName" />
<result column="nick_name" property="nickName" />
<result column="user_code" property="userCode" />
<result column="user_pwd" property="userPwd" />
<result column="user_type" property="userType" />
<result column="user_state" property="userState" />
<result column="is_delete" property="isDelete" />
<result column="create_by" property="createBy" />
<result column="create_time" property="createTime" />
<result column="udate_by" property="udateBy" />
<result column="update_time" property="updateTime" />
</resultMap>
<!-- 查询数据库所有用户信息,用来测试数据库是否连接上 -->
<select id="selectAll" resultMap="userInfoResultMap">
select * from User_info
</select>
<!-- 根据前台传来的用户ID修改用户状态 -->
<update id="updateStatics" parameterType="UserInfo">
UPDATE user_info SET
user_state=0
WHERE user_id = #{userId}
</update>
</mapper>
编写测试类
1.查询过程中没有操作数据库
package com.xieli.liu;
import com.xieli.liu.dao.UserInfoMapper;
import com.xieli.liu.pojo.Role;
import com.xieli.liu.pojo.UserInfo;
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 org.junit.Test;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
/**
* Created by Administrator on 2019-11-20.
*/
public class test {
@Test
public void test() {
SqlSessionFactory sessionFactory;
//使用MyBatis提供的Resources类加载mybatis的配置文件
try {
InputStream resourceAsStream = Resources.getResourceAsStream("config/sqlMapConfig.xml");
//构建sqlSession的工厂
sessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);
SqlSession sqlSession = sessionFactory.openSession();
SqlSession sqlSession2 = sessionFactory.openSession();
SqlSession sqlSession3 = sessionFactory.openSession();
//发起第一次查询
UserInfoMapper mapper = sqlSession.getMapper(UserInfoMapper.class);
List<UserInfo> userInfos = mapper.selectAll();
for (UserInfo userInfo: userInfos) {
System.out.println(userInfo.getUserName());
}
//写入二级缓存
sqlSession.close();
//对数据库进行操作
/* UserInfoMapper mapper3 = sqlSession3.getMapper(UserInfoMapper.class);
UserInfo u=new UserInfo();
u.setUserState("1");
mapper3.updateStatics(u);
sqlSession3.commit();
sqlSession3.close();*/
//发起第二次查询
UserInfoMapper mapper2 = sqlSession2.getMapper(UserInfoMapper.class);
List<UserInfo> userInfos2 =mapper2.selectAll();
for (UserInfo userInfo: userInfos2) {
System.out.println(userInfo.getUserName());
}
sqlSession2.close();
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
}
2.查询过程中操作数据库
package com.xieli.liu;
import com.xieli.liu.dao.UserInfoMapper;
import com.xieli.liu.pojo.Role;
import com.xieli.liu.pojo.UserInfo;
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 org.junit.Test;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
/**
* Created by Administrator on 2019-11-20.
*/
public class test {
@Test
public void test() {
SqlSessionFactory sessionFactory;
//使用MyBatis提供的Resources类加载mybatis的配置文件
try {
InputStream resourceAsStream = Resources.getResourceAsStream("config/sqlMapConfig.xml");
//构建sqlSession的工厂
sessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);
SqlSession sqlSession = sessionFactory.openSession();
SqlSession sqlSession2 = sessionFactory.openSession();
SqlSession sqlSession3 = sessionFactory.openSession();
//发起第一次查询
UserInfoMapper mapper = sqlSession.getMapper(UserInfoMapper.class);
List<UserInfo> userInfos = mapper.selectAll();
for (UserInfo userInfo: userInfos) {
System.out.println(userInfo.getUserName());
}
//写入二级缓存
sqlSession.close();
//对数据库进行操作
UserInfoMapper mapper3 = sqlSession3.getMapper(UserInfoMapper.class);
UserInfo u=new UserInfo();
u.setUserState("1");
mapper3.updateStatics(u);
sqlSession3.commit();
sqlSession3.close();
//发起第二次查询
UserInfoMapper mapper2 = sqlSession2.getMapper(UserInfoMapper.class);
List<UserInfo> userInfos2 =mapper2.selectAll();
for (UserInfo userInfo: userInfos2) {
System.out.println(userInfo.getUserName());
}
sqlSession2.close();
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
}
下图为第二次查询的日志