3.1 持久层的概念和 MyBatis 的特点
3.2 准备 MyBatis 的环境
jar包及其源码下载地址:https://github.com/mybatis/mybatis-3/releases
官方文档地址:http://www.mybatis.org/mybatis-3/zh/getting-started.html
3.3 MyBatis 的核心组件
SqlSessionFactoryBuilder 构造器
SqlSessionFactory 工厂接口
SqlSession 会话
SQL Mapper 映射器
3.4 SqlSessionFactory (工厂接口)
3.4.1 使用XML构建 SqlSessionFactory
代码清单3-1:MyBatis 的基础配置文件
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>
<typeAliases><!-- 别名 -->
<typeAlias alias="role" type="com.sinosoft.learn.ssm.pojo.Role" />
</typeAliases>
<!-- 数据库环境 -->
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/ssm"/>
<property name="username" value="root"/>
<property name="password" value="12345"/>
</dataSource>
</environment>
</environments>
<!-- 映射文件 -->
<mappers>
<mapper resource="com/sinosoft/learn/mapper/RoleMapper.xml"/>
</mappers>
</configuration>
解释:
<ypeAliases>
元素定义了一个别名role 代表com.sinosoft.learn.ssm.pojo.Role这个类<environment>
数据库描述,<dataSource>
元素配置数据库 ,type=”POOLED” 代表采用MyBatis内部提供的连接池方式<mapper>
元素代表引入的一些映射器
代码清单3-2:通过 XML 构建 SqlSessionFactory
package com.sinosoft.learn.ssm;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import java.io.IOException;
import java.io.InputStream;
/**
* @author jue
* @date 2018/9/2 1:10
* @describe 通过 XML 构建 SqlSessionFactory
*/
public class XmlBuildSqlSessionFactory {
public static void main(String[] args){
SqlSessionFactory sqlSessionFactory = null;
String resource = "mybatis-config.xml";
InputStream inputStream;
try {
inputStream = Resources.getResourceAsStream(resource);
sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
System.out.println(sqlSessionFactory);
} catch (IOException e) {
e.printStackTrace();
}
}
}
打印结果:
org.apache.ibatis.session.defaults.DefaultSqlSessionFactory@3b81a1bc
3.4.2 使用代码构建 SqlSessionFactory
代码清单3-3:使用代码构建 SqlSessionFactory
package com.sinosoft.learn.ssm;
import com.sinosoft.learn.ssm.mapper.RoleMapper;
import com.sinosoft.learn.ssm.pojo.Role;
import org.apache.ibatis.datasource.pooled.PooledDataSource;
import org.apache.ibatis.mapping.Environment;
import org.apache.ibatis.session.Configuration;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.apache.ibatis.transaction.jdbc.JdbcTransactionFactory;
/**
* @author jue
* @date 2018/9/3 22:56
* @describe
*/
public class CodeBuildSqlSessionFactory {
public static void main(String[] args){
//数据库连接池信息
PooledDataSource dataSource = new PooledDataSource();
dataSource.setDriver("com.mysql.jdbc.Driver");
dataSource.setUsername("root");
dataSource.setPassword("12345");
dataSource.setUrl("jdbc:mysql://localhost:3306/ssm");
dataSource.setDefaultAutoCommit(false);
//采用MyBatis的JDBC事务方式
JdbcTransactionFactory transactionFactory = new JdbcTransactionFactory();
Environment environment = new Environment("development", transactionFactory, dataSource);
//创建Configuration对象
Configuration configuration = new Configuration(environment);
//注册一个MyBatis上下文
configuration.getTypeAliasRegistry().registerAlias("role", Role.class);
//加入一个映射器
configuration.addMapper(RoleMapper.class);
//使用SqlSessionFactoryBuilder构建SqlSessionFactory
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(configuration);
System.out.println(sqlSessionFactory);
}
}
3.5 SqlSession
代码清单3-4: 创建SqlSession
SqlSession sqlSession = SqlSessionFactory.openSession();
代码清单3-5:SqlSession 事务控制伪代码
//定义SqlSession
SqlSession sqlSession = null;
try {
//打开 SqlSession 会话
sqlSession = sqlSessionFactory.openSession();
//some code
//提交事务
sqlSession.commit();
} catch (Exception e) {
//回滚事务
sqlSession.rollback();
} finally {
//在 finally 语句中确保资源被顺利关闭
if (sqlSession != null) {
sqlSession.close();
}
}
3.6 映射器
代码清单3-6: 定义角色的POJO
package com.sinosoft.learn.ssm.pojo;
/**
* @author jue
* @date 2018/9/2 1:20
* @describe
*/
public class Role {
private Long id;
private String roleName;
private String note;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getRoleName() {
return roleName;
}
public void setRoleName(String roleName) {
this.roleName = roleName;
}
public String getNote() {
return note;
}
public void setNote(String note) {
this.note = note;
}
}
3.6.1 用XML实现映射器(推荐)
代码清单3-7:映射器接口
package com.sinosoft.learn.ssm.mapper;
import com.sinosoft.learn.ssm.pojo.Role;
/**
* @author jue
* @date 2018/9/4 0:12
* @describe
*/
public interface RoleMapper {
public Role getRole(Long id);
}
代码清单3-8:用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.sinosoft.learn.ssm.pojo.Role">
<select id="selectRole" parameterType="long" resultType="role">
select * from role where id = #{id}
</select>
</mapper>
解释:
- 属性namespace 所对应的是一个接口的全限定名,在MyBatis的上下文中就可以找到对应的接口
- select 表示这是一条查询语句 ,id=”selectRole” 唯一标识了这条语句,
parameterType=”long” 说明传递给sql的是一个long类型的参数, resultType=”role” 之前配置文件中指定的别名,指的是com.sinosoft.learn.ssm.pojo.Role
3.6.2 注解实现映射器(不推荐)
代码清单3-9:通过注解实现映射器
package com.sinosoft.learn.ssm.mapper;
import com.sinosoft.learn.ssm.pojo.Role;
import org.apache.ibatis.annotations.Select;
/**
* @author jue
* @date 2018/9/4 22:02
* @describe
*/
public interface RoleMapper2 {
@Select(" select id, role_name as roleName, note from t_role where id=#{id} ")
public Role getRole(Long id);
}
接着要把mybatis-config.xml配置文件中<mapper resource="com/sinosoft/learn/mapper/RoleMapper.xml"/>
改为
<mapper class="com.sinosoft.learn.ssm.mapper.RoleMapper2"/>
3.6.3 SqlSession 发送 SQL
Role role = (Role)sqlSession.selectOne("com.sinosoft.learn.ssm.mapper.RoleMapper.getRole", 1L);
这是MyBatis的前身iBatis留下的方式
3.6.4 用Mapper接口发送SQL
代码清单3-10:用SqlSession 获取Mapper接口,并发送SQL
RoleMapper mapper = sqlSession.getMapper(RoleMapper.class);
Role role = mapper.getRole(1L);
3.6.5 对比两种发送SQL的方式
推荐使用Mapper接口方式
3.7 生命周期
3.7.1 SqlSessionFactoryBuilder
SqlSessionFactoryBuilder的作用在于创建SqlSessionFactory,创建成功后就失去作用了,只存在于创建SqlSessionFactory的方法中,而不能长期存在
3.7.2 SqlSessionFactory
SqlSessionFactory可认为是一个数据库连接池,作用是创建SqlSession对象,SqlSessionFactory的生命周期等同于MyBatis的应用周期,一般以单例模式存在,可以被共享。
3.7.3 SqlSession
SqlSession相当于一个数据库连接(Connection 对象),可以在一个事务里面执行多条sql,只存在一个业务请求中,处理完整个请求后,应该关闭这条连接,把它归还给SqlSessionFactory。使用try..catch…finally..语句来保证正常关闭。
3.7.4 Mapper
它的最大生命周期至多和SqlSession保持一致,一般应小于SqlSession的生命周期,Mapper代表的是一个请求中的业务处理,一旦处理完可相关的业务,就应该废弃它。
3.8 实例
代码清单3-11:log4j.properties
log4j.rootLogger=DEBUG,stdout
log4j.logger.org.mybatis=DEBUG
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%5p %d %c: %m%n
代码清单3-12:Role.java
package com.learn.ssm.chapter3.pojo;
/**
* @author jue
* @date 2018/9/8 14:19
* @describe
*/
public class Role {
private Long id;
private String roleName;
private String noteInfo;
public Role() {
}
public Role(Long id, String roleName, String noteInfo) {
this.id = id;
this.roleName = roleName;
this.noteInfo = noteInfo;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getRoleName() {
return roleName;
}
public void setRoleName(String roleName) {
this.roleName = roleName;
}
public String getNoteInfo() {
return noteInfo;
}
public void setNoteInfo(String noteInfo) {
this.noteInfo = noteInfo;
}
@Override
public String toString() {
return "Role{" +
"id=" + id +
", roleName='" + roleName + '\'' +
", noteInfo='" + noteInfo + '\'' +
'}';
}
}
代码清单3-13:RoleMapper.java
package com.learn.ssm.chapter3.mapper;
import com.learn.ssm.chapter3.pojo.Role;
import java.util.List;
/**
* @author jue
* @date 2018/9/8 14:21
* @describe
*/
public interface RoleMapper {
public int insertRole(Role role);
public int deleteRole(Long id);
public int updateRole(Role role);
public Role getRole(Long id);
public List<Role> findRoles(String roleName);
}
代码清单3-14:RoleMapper.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.learn.ssm.chapter3.mapper.RoleMapper">
<insert id="insertRole" parameterType="role">
insert into t_role(role_name, note) values (#{roleName}, #{noteInfo})
</insert>
<delete id="deleteRole" parameterType="long">
delete from t_role where id = #{id}
</delete>
<update id="updateRole" parameterType="role">
update t_role set role_name = #{roleName} ,note = #{noteInfo} where id = #{id}
</update>
<select id="getRole" parameterType="long" resultType="role">
select id, role_name roleName, note as noteInfo from t_role where id=#{id}
</select>
<select id="findRoles" parameterType="string" resultType="role">
select id,role_name roleName, note noteInfo from t_role
where role_name like concat('%', #{roleName}, '%')
</select>
</mapper>
代码清单3-15: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>
<typeAliases>
<typeAlias alias="role" type="com.learn.ssm.chapter3.pojo.Role" />
</typeAliases>
<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/ssm"/>
<property name="username" value="root"/>
<property name="password" value="12345"/>
</dataSource>
</environment>
</environments>
<mappers>
<mapper resource="com/learn/ssm/chapter3/mapper/RoleMapper.xml"/>
</mappers>
</configuration>
代码清单3-16:构建SqlSessionFactory 工具类
package com.learn.ssm.chapter3.utils;
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;
/**
* @author jue
* @date 2018/9/8 14:47
* @describe
*/
public class SqlSessionFactoryUtils {
private final static Class<SqlSessionFactoryUtils> LOCK = SqlSessionFactoryUtils.class;
private static SqlSessionFactory sqlSessionFactory = null;
public SqlSessionFactoryUtils() {}
public static SqlSessionFactory getSqlSessionFactory() {
synchronized (LOCK) {
if (sqlSessionFactory != null) {
return sqlSessionFactory;
}
String resource = "mybatis-config.xml";
InputStream inputStream;
try {
inputStream = Resources.getResourceAsStream(resource);
sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
} catch (IOException e) {
e.printStackTrace();
return null;
}
return sqlSessionFactory;
}
}
public static SqlSession openSqlSession() {
if (sqlSessionFactory == null) {
getSqlSessionFactory();
}
return sqlSessionFactory.openSession();
}
}
代码清单3-17:Chapter3Main.java
package com.learn.ssm.chapter3.main;
import com.learn.ssm.chapter3.mapper.RoleMapper;
import com.learn.ssm.chapter3.pojo.Role;
import com.learn.ssm.chapter3.utils.SqlSessionFactoryUtils;
import org.apache.ibatis.session.SqlSession;
import org.apache.log4j.Logger;
import org.junit.Test;
import java.util.List;
/**
* @author jue
* @date 2018/9/8 14:59
* @describe
*/
public class Chapter3Main {
public static void main(String[] args){
Logger log = Logger.getLogger(Chapter3Main.class);
SqlSession sqlSession = null;
try {
sqlSession = SqlSessionFactoryUtils.openSqlSession();
RoleMapper roleMapper = sqlSession.getMapper(RoleMapper.class);
Role role = roleMapper.getRole(5L);
// log.info(role);
System.out.println(role);
// Role role1 = new Role();
// role1.setRoleName("分公司管理员");
// role1.setNote("fen发");
// int insertNum = roleMapper.insertRole(role1);
// System.out.println("新增个数:" + insertNum);
// Role role2 = new Role(5L,"录单员", "绿单元");
// int updateNum = roleMapper.updateRole(role2);
// System.out.println("更新个数:"+updateNum);
// roleMapper.deleteRole(1L);
sqlSession.commit();
} finally {
if (sqlSession != null) {
sqlSession.close();
}
}
}
@Test
public void test1() {
Logger log = Logger.getLogger(Chapter3Main.class);
SqlSession sqlSession = null;
try {
sqlSession = SqlSessionFactoryUtils.openSqlSession();
RoleMapper roleMapper = sqlSession.getMapper(RoleMapper.class);
// Role role = roleMapper.getRole(5L);
List<Role> roles = roleMapper.findRoles("经办人");
roles.stream().forEach(System.out::println);
sqlSession.commit();
} finally {
if (sqlSession != null) {
sqlSession.close();
}
}
}
}