第 3 章 認識 MyBatis 核心元件
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();
}
}
}
列印結果:
[email protected]a1bc
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();
}
}
}
}