mybatis框架(持續更新...)

mybatis框架

概述

mybatis是基於java的持久層框架,內部封裝了jdbc,使開發者只關注sql語句本身。
mybatis通過xml和註解的方式將各種statement配置起來,並通過Java對象和statement中的動態參數進行映射最終生成sql語句,並對結果映射爲java對象並返回
mybatis採用ORM的思想方便操作等
ORM:
Object Relational Mapping 對應關係映射
簡單的來說就是:
將數據庫中的表和實體類及實體類的屬性對應起來
讓我們看可以操作實體類就可以實現操作數據庫表

			表			實體類
			user				User
			id				user_id
			name				user_name
			.				.	
			.				.
			.				.

mybatis 入門(xml實現)

創建一個maven項目,直接創建
在pom.xml加入依賴

<dependencies>
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.5.2</version>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.6</version>
        </dependency>
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.12</version>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>3.8.2</version>
            <scope>test</scope>
        </dependency>
    </dependencies>

在resource文件夾中創建mybatis的 --主配置-- 文件命名爲mysqlMapConfig.xml,
在主配置文件中配置我們的所有javabean對象的一些CRUD操作。
主配置文件主要功能:
1.配置連接的數據庫
2.配置文件映射,如:對UserDao的一些操作的文件映射,需要使用Mapper標籤

<?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">
<!-- mybatis 的 主配置文件-->

<configuration>
    <!-- 配置環境-->
    <environments default="mysql">
        <!--配置mysql-->
        <environment id="mysql">
            <!--配置事務類型-->
            <transactionManager type="JDBC"/>
            <!--配置數據源/連接池-->
            <dataSource type="POOLED">
                <!--配置連接數據庫的基本信息-->
                <property name="driver" value="com.mysql.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://xx.xxx.xxx.xxx:3306/xxx"/>
                <property name="username" value="xxxx"/>
                <property name="password" value="xxx"/>
            </dataSource>
        </environment>
    </environments>

    <!--指定映射配置文件的位置,映射配置文件指的是每個dao獨立的配置文件-->
    <mappers>
       <mapper resource="club/twzw/dao/UserDao.xml"/>
    </mappers>
	
</configuration>

在resources 文件夾下 創建UserDao.xml(與類名相一致,路徑也要一致,映射的配置文件相一致)
主要包括一些CRUD的操作,延遲加載等等。

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org.//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="club.twzw.dao.UserDao"> 		<<<<<------這裏的namespace 必須和 接口進行綁定,也就是接口的全類名路徑,且各個標籤使用的id爲接口中定義的名稱,接口名爲findAll,標籤使用的id也爲findAll,完成綁定。

    <select id="findAll" resultType="club.twzw.domain.User">
        select * from user
    </select>
</mapper>

在resources 文件夾下 創建log4j.properties文件,用於輸入日誌文件

# Global logging configuration
log4j.rootLogger=DEBUG, stdout
# 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

創建dao處理層接口,用於一些CRUD操作的方法,

package club.twzw.dao;

import club.twzw.domain.User;

import java.util.List;

/**
 * 用戶持久層接口
 */
public interface UserDao {

    /**
     * 查詢所有操作
     */
    List<User> findAll();
}

創建bean對象,用於存儲數據

package club.twzw.domain;

import java.io.Serializable;

public class User implements Serializable {
    private Integer id;
    private String name;
    private String born;
    private Integer sex;
    private String address;
	
    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", born='" + born + '\'' +
                ", sex=" + sex +
                ", address='" + address + '\'' +
                '}';
    }

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getBorn() {
        return born;
    }

    public void setBorn(String born) {
        this.born = born;
    }

    public Integer getSex() {
        return sex;
    }

    public void setSex(Integer sex) {
        this.sex = sex;
    }

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }
}

創建測試函數,factory.openSession();爲空需要手動提交,factory.openSession(true);爲自動提交

package club.twzw.test;

import club.twzw.dao.UserDao;
import club.twzw.domain.User;
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 javax.annotation.Resource;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;

public class mybatisTest {
    public static void main(String[] args) throws IOException {
        // 讀取配置文件,爲主配置文件
        InputStream in = Resources.getResourceAsStream("mysqlMapConfig.xml");
        // 創建SqlSessionFactory 工廠
        SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
        SqlSessionFactory factory = builder.build(in);
    	//使用工廠生產session
        SqlSession sqlSession = factory.openSession();
        //  使用sqlsession創建dao接口的代理對象,傳入接口
        UserDao userDao = sqlSession.getMapper(UserDao.class);
        // 使用代理對象執行方法
        List<User> users = userDao.findAll();
        for (User user:users){
            System.out.println(user);
        }
        //釋放資源				
        in.close();
        sqlSession.close();
    }
}

最終實現效果控制檯輸出

User{id=1, name='comi', born='1998', sex=0, address='xxxx'}
User{id=2, name='siki', born='2002', sex=1, address=' xxxx'}

mybatis 注意事項

一、創建UserDao.xml和UserDao.java時名稱是爲了和我們之前的知識保持一致
在mybatis中它把持久層的操作接口名稱和映射文件也叫做  Mapper
所以 UserDao 和 UserMapper 是一樣的
二、mybatis的映射配置文件位置必須與dao接口的包結構相同
三、映射配置文件的mapper標籤namespace屬性的取值必須是dao接口的全限定類名
四、映射配置文件的操作配置(select),id屬性的取值必須是dao接口的方法名

當我們遵循二、三、四點後,在開發中便~~~無須實現dao實現類~~~

Sqlsession和connection都是非線程安全的,不能放在成員變量中,每一次使用都應該去獲取新的對象

mybatis 引用外部文件配置數據庫連接

新建一個dbconfig.properties文件,在主配置文件下 添加以下語句,並且修改配置文件的properties

    <properties resource="dbconfig.properties"/>
	
	<environments default="mysql">
        <!--配置mysql-->
        <environment id="mysql">
            <!--配置事務類型-->
            <transactionManager type="JDBC"/>
            <!--配置數據源/連接池-->
            <dataSource type="POOLED">
                <!--配置連接數據庫的基本信息-->
                <property name="driver" value="${jdbc.driver}"/>
                <property name="url" value="${jdbc.url}"/>
                <property name="username" value="${jdbc.username}"/>
                <property name="password" value="${jdbc.password}"/>
            </dataSource>
        </environment>
    </environments>

dbconfig.properties文件內容

jdbc.driver = com.mysql.jdbc.Driver
jdbc.url = jdbc:mysql://xx.xx.xx.xx:3306/blog
jdbc.username = blog
jdbc.password =  146325

主配置文件的常用標籤

setting

在這裏,可以配置相關的全局設置,比如懶加載,駝峯命名等等設置。

typeAliases 別名處理器

可以爲我們常用的Java類起別名,讓很長的名字變得短,別名不區分大小寫。在主配置文件下就爲全局配置,在單獨的UserDao中就爲局部別名。
package可以批量起別名,自動爲package下的類自動起別名

    <settings>
        <!--懶加載-->
        <setting name="lazyLoadingEnabled" value="true"/>
        <setting name="aggressiceLazyLoading" value="false"/>
        <!--開啓駝峯命名自動轉換-->
        <setting name="mapUnderscoreToCamelCase" value="true"/>
    </settings>
	
	<!--如果不配置alias就會默認爲類名的小寫-->
	<typeAliases>
        <typeAlias type="club.twzw.dao.UserDao" alias="user"/>
    </typeAliases>
	
	<!-包下所有類自動起別名-->
	<package name="club.twzw.dao"/>

mappers 將sql映射註冊到全局配置中 mapper 註冊一個sql映射

resource:引用類路徑下的sql映射文件
url:引入網絡路徑或者磁盤路徑下的sql映射文件
class:引入(註冊)接口
1.有sql文件,sql文件必須和接口同名且在同一目錄
2.註解實現
推薦比較重要的Dao接口可以用xml實現,不太重要的可以使用註解實現,提高開發速度

批量註冊

使用package標籤,註冊該包下所有的映射,如果是xml文件,同樣,sql文件必須和接口同名且在同一目錄,才能實現註冊

<package name="club.twxw.dao.UserDao"/>

databaseIdProvider 使用不同的數據庫

且每一個標籤都有各自的使用順序,否者會報錯。

    <databaseIdProvider type="DB_VEBDOR">
        <property name="MySQL" value="mysql"/>
        <property name="Oracle" value="oracle"/>
    </databaseIdProvider>

mybatis(註解實現映射)

1.無需在配置UserDao.xml文件
2.將mysqlMapConfig.xml的mapper屬性的resource改爲class,並配置全路徑類名
	 <mappers>  
  			<mapper class="club.twzw.dao.UserDao"/>  
	 </mappers>
3.將UserDao的findAll方法上加入註解@Select()
	@Select("select * from user")  
	List<User> findAll();

增加代碼的複用性

由於每一次使用dao都會有一些重複的過程,我們可以把這些重複的額過程提取出來,不但方便使用,而且代碼簡潔。
比如說:我們可以在代碼運行之前,銷燬之前運行一些代碼

    @Before
    public void init() throws IOException {
        // 讀取配置文件
        in = Resources.getResourceAsStream("mysqlMapConfig.xml");
        // 創建SqlSessionFactory 工廠
        builder = new SqlSessionFactoryBuilder();
        factory = builder.build(in);
        //使用工廠生產session
        sqlSession = factory.openSession();
        //  使用sqlsession創建dao接口的代理對象
        userDao = sqlSession.getMapper(UserDao.class);
    }

    @After
    public void destory() throws Exception{
		sqlSession.commit();
        //釋放資源
        in.close();
        sqlSession.close();
    }

這樣我們就可以簡化代碼,徹底專注於核心業務dao層

  @Test
    public void testSave() throws IOException {
        User user = new User();
        user.setAddress("japan");
        user.setBorn("1998");
        user.setName("gimi");
        user.setSex(1);
        user.setId(3);
        // 使用代理對象執行方法
        userDao.addUser(user); 		<<<-----
		
		//sqlSession.commit();     <<<-----必須要提交事務,否則無法實現CRUD操作,同樣,也可以把這一句放在銷燬之前,但是這一句便不能再出現
    }

當然,還需要再UserDao.xml 中 加入相應的id addUser

    <insert id="addUser" parameterType="club.twzw.domain.User">
        insert into user (id,name,born,sex,address)values(#{id},#{name},#{born},#{sex},#{address})
    </insert>

完善CRUD相關代碼及模糊查詢

	//findById
    @Test
    public void testDelete(){
		User user = userDao.findById(1);
		System.out.println(user);
    }
	
	//add
    @Test
    public void testSave() throws IOException {
        User user = new User();
        user.setAddress("japan");
        user.setBorn("1998");
        user.setName("gimi");
        user.setSex(1);
        user.setId(3);
        // 使用代理對象執行方法
        userDao.addUser(user);
    }
	//update
    @Test
    public void testUpdate(){
        User user = new User();
        user.setId(3);
        user.setSex(1);
        user.setName("???");
        user.setAddress("djkajdjwa");
        user.setBorn("20000000000");
        userDao.UpdateUser(user);
    }
	//delete
    @Test
    public void testDelete(){
        userDao.delete(3);
    }
	//	模糊查詢
	@Test
    public void findByName() {
        List<User> users = userDao.findByName("%comii%");
        for (User user : users) {
            System.out.println(user);
        }
    }
	

配置相關xml,namespace 需和類路徑相同,與接口進行綁定,且#{xxx}中的名稱爲JavaBean中的屬性名稱相同,User中有name,sex,address,那麼xml文件中的#{xxx} 也爲#{name},#{sex},#{address}

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org.//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<mapper namespace="club.twzw.dao.UserDao">
    <!--    // 有時數據庫和java bean 中的命名不一致,爲了方便起見,我們可以配置resultMap(結果集)-->
    <!--    // 配置查詢結果的列名和實體類的屬性名對應的關係(如果命名不一致,一致無需創建)-->
	
    <resultMap id="userMap" type="club.twzw.domain.User">
        <!--        主鍵對應字段-->
        <id property="id" column="id"></id>
        <!--        非主鍵對應字段-->
        <result property="name" column="name"></result>
        <result property="born" column="born"></result>
        <result property="sex" column="sex"></result>
    </resultMap>
	
    <!--使用resultMap-->
    <!--查詢所有-->
    <select id="findAll" resultMap="userMap">
        select * from user
    </select>
	
    <!--不使用resultMap-->
    <!--查詢所有-->
    <select id="findAll" resultType="club.twzw.domain.User">
        select * from user
    </select>
	
    <!--查詢單個-->
    <select id="findById" parameterType="int" resultType="club.twzw.domain.User">
        select * from user where id = #{id}
    </select>
	
    <!--添加用戶-->
    <insert id="addUser" parameterType="club.twzw.domain.User">
        insert into user (id,name,born,sex,address)values(#{id},#{name},#{born},#{sex},#{address})
    </insert>
	
    <!--更新用戶數據-->
    <update id="UpdateUser" parameterType="club.twzw.domain.User">
        update user set name=#{name},address=#{address},sex=#{sex},born=#{born} where id=#{id}
    </update>
	
    <!--刪除用戶數據-->
    <delete id="delete" parameterType="Integer">
        delete from user where id=#{id}
    </delete>
	
    <!--根據name模糊查詢用戶-->
    <select id="findByName" parameterType="string" resultType="club.twzw.domain.User">
        select * from user where name like #{name}
    </select>
</mapper>

在插入完成之後獲取ID的值

1.通過selectKey標籤 設置resultType,keyProperty,keyColumn,order 相關設置,自動返回數據。(不支持自增的數據庫使用的方法,Oracle),order=“BEFORE” 在執行插入之前
2.使用useGeneratedKeys=“true” keyProperty=“id”,這裏的id 爲JavaBean的id(支持自增的數據庫,mysql)

	    <!--方法一-->
    <insert id="addUser" parameterType="club.twzw.domain.User">
        <selectKey resultType="int" keyProperty="int" keyColumn="id" order="BEFORE">
            <!--查詢主鍵id,得到後便可以使id有值-->
			select last_intsert_id();
        </selectKey>
        insert into user (id,name,born,sex,address)values(#{id},#{name},#{born},#{sex},#{address})
    </insert>

	<!--方法二-->
	<insert id="addUser" parameterType="user" useGeneratedKeys="true" keyProperty="id">
         insert into user (name,born,sex,address)values(#{name},#{born},#{sex},#{address})
    </insert>

OGNL表達式(object graphic navigation language)

通過對象的取值方法 來獲取數據,在寫法上省略了get(省略相關配置)
eg:
	類:	User.GetName();
	ONNL:	User.name

使用alias 配置別名

    <!--    使用alias配置別名-->
	<!--    <typeAliases>-->
	<!--        <typeAlias type="club.twzw.domain.User" alias="user"></typeAlias>-->
	<!--    </typeAliases>-->
    <!--    那麼所有的club.twzw.domain.User 便可以用 user 替代-->
    <!--    <select id="findById" parameterType="int" resultType="user">-->
    <!--        select * from user where id = #{id}-->
    <!--    </select>-->

mtbatics 中的動態sql語句查詢 -if

UserDao.xml 中添加

    <!--    根據條件查詢-->
    <select id="findByCondition" resultType="club.twzw.domain.User" parameterType="club.twzw.domain.User">
        select * from user where 1 = 1		<<<<<----------
        <if test="name != null">
            and name = #{name}
        </if>
    </select>

UserDao.java 中添加

    boolean findByCondition(User user);

測試代碼

    @Test
    public void findByCondition() {
        User u = new User();
        u.setName("comi");
        User u = userDao.findByCondition(u);
        System.out.println(u);
    }

mtbatics 中的動態sql語句查詢 -where

    <!--使用where 標籤-->
    <select id="findByCondition" resultType="club.twzw.domain.User" parameterType="club.twzw.domain.User">
        select * from user			<<<<<----------
        <where>						<<<<<----------
            <if test="name != null">
                and name = #{name}
            </if>
            <if test="sex != null">
                and sex = #{sex}
            </if>
        </where>
    </select>

將重複使用的 sql 語句,抽取出來,重複使用

<!--由於我們經常使用 select * from user 這條語句,所以我們可以把這條語句抽取出來-->
<sql id="selectUserAll">			<<<<<----------
    select * from user;
</sql>

<!-- 使用 sql-->
<select id="findAll" resultType="club.twzw.damain.User">
   <include refid="selectUserAll"></include> 			<<<<<----------
</select>

mtbatics 中的動態sql語句–批量查詢,-foreach

sql 語句 select * from user where id in (41,42,43);
mybatis 實現

    <!--    查詢多個指定id的數據-->
    <select id="findByUsersIds" resultType="club.twzw.damain.User" parameterType="club.twzw.damain.User">
        select * from user
        <where>
            <if test="ids != null and ids.size()>0">
                <foreach collection="ids" open=" and ids in (" close=")" item="id" separator=",">
                    #{id}
                </foreach>
            </if>
        </where>
    </select>

mtbatics 中的動態sql語句–批量保存,-foreach

接口定義

void addUsers(@Param("users")List<User> users);

xml語句

    <insert id="saveUsers" parameterType="domain.User">
        insert INTO user(name,gender,email)values
        <foreach collection="users" item="user" separator=",">
            (#{user.name},#{user.gender},#{user.email})
        </foreach>
    </insert>

mtbatics 中字符截取,-trim

如果gender爲空,那麼會在結尾多出來一個and,而suffixOverrides就是用來截取and的功能

    <select id="findByCondition" resultType="domain.User" parameterType="string">
        select * from user
        <trim suffixOverrides="and">
            <where>
                <if test="name !=''">
                    and name like #{name} and
                </if>
                <if test="gender !=''">
                    gender = #{gender}
                </if>
            </where>
        </trim>    
    </select>

mtbatics 中字符截取,-choose,類似於switch case選擇分支語句

     <select id="findByCondition" parameterType="string" resultType="domain.User">
        select *
        from user
        <where>
            <choose>
                <when test="id != ''">
                    id=#{id}
                </when>
                <when test="gender != ''">
                    gender=#{gender}
                </when>
                <otherwise>
                    email=#{email}
                </otherwise>
            </choose>
        </where>
    </select>

mtbatics 中數據更新,-set

    <update id="updateByCondition" parameterType="string">
        update user
        <set>
            <if test="name !=''">
                name=#{name},
            </if>
            <if test="gender !=''">
                gender=#{gender}
            </if>
        </set>
        where id=#{id}
    </update>

單個參數和多個參數

如果是單個參數或者javaBe對象,mybatis會自動識別,無需特別處理,但是如果是多個參數,則需要特殊處理

使用@Param註解,在接口中使用

    boolean addUser(@Param("id")Interger id,@Param("name")String name);

在xml中直接使用key即可

    <select id="findByCondition" resultMap="userMap">
        select * from user where id = #{id} and name =#{name}
    </select>

將不相關的數據進行封裝成一個參數

java代碼中

        Map<String,Object> map = new HashMap<>();
        map.put("id",1);
        map.put("name","comi");
        User u = userDao.findByCondition(mao);

xml就可以直接使用#{id},#{name}

    <select id="findByCondition" resultMap="userMap">
        select * from user where id = #{id} and name =#{name}
    </select>

select 標籤

1.使用select 封裝 List,如果返回數據爲多個,mybatis會自動封裝返回的數據爲list
2.使用select 封裝 Map,resultMap 設置爲Map(單個數據)
3.使用select 封裝 Map,在方法上添加 @MapKey(“id”) 指定 key,就可以自動封裝

@MapKey("id")
public Map<Interger,User> map getUserByCondition(String name);

resultMap 自定義結果集(如果數據庫和JavaBean數據名稱對應不一致)

    <resultMap id="userMap" type="club.twzw.domain.User">
        <!--        主鍵對應字段-->
        <id property="id" column="Id"></id>
        <!--        非主鍵對應字段-->
        <result property="name" column="Name"></result>
        <result property="born" column="Born"></result>
        <result property="sex" column="Sex"></result>
    </resultMap>

resultMap中返回的結果中一個類包含另一個類的情況(聯合查詢)

有兩個JavaBean對象,一個是User,一個是account,在查詢user時需要查詢account。
user
 id
 name
 gender
 acc
account
 id
 money
進行設置結果集

	    <!--方法一-->
    <resultMap id="userMap" type="club.twzw.domain.User">
        <!--        主鍵對應字段-->
        <id property="id" column="Id"></id>
        <!--        非主鍵對應字段-->
        <result property="name" column="Name"></result>
        <result property="born" column="Born"></result>
        <result property="gender" column="Gender"></result>
		<result property="aid" column="account.id"></result>  		 <<<<---------
		<result property="amonty" column="account.money"></result>   <<<<---------
    </resultMap>
	
	<!--方法二-->
	<!--property 指的是 要封裝的JavaBean中的屬性是哪一個-->
	<!--javaType 這個屬性對象的類型,即account-->
	<association property="acc" column="id" javaType="club.twzw.domain.account">
		<result property="aid" column="id"></result>  		 <<<<---------
		<result property="amonty" column="money"></result>   <<<<---------
    </association>

mybatis 延遲加載和立即加載

什麼是延遲加載?

在真正使用數據時,才發起查詢,不用的時候不查詢,按需加載(懶加載)

什麼是立即加載?

不管用不用,只要一調用方法,馬上發起查詢。
在對應的四種表關係中:一對一,多對一(mytatis 沒有這個概念),一對多,多對多。不同情況使用不同的加載策略。
一對多,多對多:採用延遲加載
一對一,多對一:採用立即加載

配置延遲加載

全局配置文件中加入(如果不加入這兩句,就會變爲分步查詢)

    <!--在這裏配置相關懶加載參數-->
	<!--這樣 懶加載的配置就配置好了-->
    <settings>
        <setting name="lazyLoadingEnabled" value="true"/>
        <setting name="aggressiceLazyLoading" value="false"/>
    </settings>

mybatis 返回數據中子屬性爲單個JavaBean

在UserDao.xml 中配置 resultMap的association標籤屬性,重點是select 屬性,必須是namespace加方法名,唯一標識用戶,通過此方法去查出信息

    <!--配置延遲加載-->
    <resultMap id="userMap" type="club.twzw.domain.User">
        <!--主鍵對應字段-->
        <id property="id" column="id"></id>
        <!--非主鍵對應字段-->
        <result property="name" column="name"></result>
        <result property="born" column="born"></result>
        <result property="sex" column="sex"></result>
		
        <!--使用association 標籤-->
		<!--select 屬性指定的內容是查詢用戶的唯一標識-->
        <!--同樣 column 也是必須的,否則無法運行,會報錯-->
        <!--這樣我們就可以配置相關連的對象了,比如說用戶的賬戶信息等!-->
        <association property="user" column="id" javaType="user" select="club.twzw.dao.UserDao.findById"> 		<<<<<---------
        </association>
    </resultMap>

mybatis 返回數據中子屬性爲集合

使用標籤collection
  collection定義關聯集合的屬性的封裝規則
  ofType指定集合中的元素類型

    <resultMap id="userMap" type="club.twzw.domain.User">
        <!--主鍵對應字段-->
        <id property="id" column="id"></id>
        <!--非主鍵對應字段-->
        <result property="name" column="name"></result>
        <result property="born" column="born"/>
        <result property="sex" column="sex"></result>
		
        <collection property="account" ofType="club.twzw.domain.account">
            <!--主鍵對應字段-->
            <id property="aid" column="id"></id>
            <!--非主鍵對應字段-->
            <result property="amoney" column="money"></result>
        </collection>
    </resultMap>

同樣,按需加載也是需要設定select屬性並書寫相應的xml查詢語句

resultMap 鑑別器 discriminator (類似於switch)

加入我們需要根據不同的部門來查詢封裝信息,則需要使用discriminator標籤
javaType:傳入值類型
column:哪一列需要作爲判斷

    <resultMap id="userMap" type="club.twzw.domain.User">
        <!--主鍵對應字段-->
        <id property="id" column="id"></id>
        <!--非主鍵對應字段-->
        <result property="name" column="name"></result>
        <result property="born" column="born"/>
        <result property="sex" column="sex"></result>

        <discriminator javaType="String" column="department">
            <case value="研發部">
                <!--相關操作-->
            </case>
            <case value="設計部">
                <!--相關操作-->
            </case>
        </discriminator>
    </resultMap>

mybatis 緩存機制

二級緩存(全局緩存)

一級緩存(本地緩存)

 與數據庫同一次會話期間查詢到的數據會放在本地緩存中,以後有相同數據,直接從緩存中拿,沒必要查詢數據庫,
 在同一次會話中,相同的sql語句只會查詢一次,查詢結果被緩存在sqlsseesion中,一級緩存是一直開啓的。

一級緩存失效情況

1.sqlsession不同
2.sqlsession相同,查詢條件不同(當一級緩存還沒有這條數據)
3.sqlsession相同,兩次查詢之間執行了增刪改操作(這次修改可能對之前數據有影響)
4.手動清除cache緩存

 @Test
    void testFirstLevel() throws IOException {
        InputStream in = Resources.getResourceAsStream("mysqlConfig.xml");
        SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
        SqlSessionFactory factory = builder.build(in);
        SqlSession session = factory.openSession(true);
        try {
            UserDao dao = session.getMapper(UserDao.class);
            Map<Integer, User> users = dao.getUser("comi");
            System.out.println(users);
        } finally {
            session.close();
        }
    }

二級緩存

基於namespace級別的緩存,一個namespace對應一個二級緩存

工作機制:

1.一個會話,查詢一條數據,這個數據就會放在當前會話的一級緩存中。
2.如果會話關閉,一級緩存中的數據會保存到二級緩存中,新的會話查詢信息,就可以參照二級緩存
3.SQL session
  userMapper==>user
  accountMapper==>account

使用步驟

  在全局配置文件中開啓全局二級緩存(默認開啓)

    <settings>
        <setting name="cacheEnabled" value="true"/>
    </settings>

  在單獨的xml文件中配置二級緩存

    <!--    開啓緩存,設置刷新緩存間隔 60 秒 刷新規則:先進先出 且只讀-->
    <cache readOnly="true" flushInterval="60000" eviction="FIFO"></cache>

  JavaBean實現序列化接口
測試代碼:不同的sqlsession請求同一個數據,開啓二級緩存之後,還是隻會請求一次

    @Test
    void testSecondCache() throws IOException {
        InputStream in = Resources.getResourceAsStream("mysqlConfig.xml");
        SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
        SqlSessionFactory factory = builder.build(in);
        SqlSession session = factory.openSession(true);
        SqlSession session1 = factory.openSession(true);
        try {
            UserDao dao = session.getMapper(UserDao.class);
            UserDao mapper = session1.getMapper(UserDao.class);
            Map<Integer, User> comi = dao.getUser("comi");
            System.out.println(comi);
            session.close();
            Map<Integer, User> user = mapper.getUser("comi");
            System.out.println(user);
        } finally {
            session1.close();
        }
    }
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章