1. 程式人生 > >第 3 章 認識 MyBatis 核心元件

第 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();
            }
        }

    }


}