日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 运维知识 > 数据库 >内容正文

数据库

MyBatis动态SQL_多表查询_延迟加载_缓存

發(fā)布時(shí)間:2024/7/5 数据库 26 豆豆
生活随笔 收集整理的這篇文章主要介紹了 MyBatis动态SQL_多表查询_延迟加载_缓存 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

POJO包裝傳遞對(duì)象

//POJO實(shí)體 public class QueryConditionObject {private User user;//user get,set方法 }//Dao 接口 public interface UserMapper{List<User> findByCondition(QueryConditionObject qco); }//UserMapper.xml中的select標(biāo)簽 <select id="findByCondition" resultType="com.regotto.domain.User"parameterType="com.itheima.domain.QueryVo"><!--此處使用OGNL表達(dá)式, 傳遞select查詢的條件-->select * from user where username like #{user.username}; </select>

resultType or resultMap配置結(jié)果參數(shù)

MyBatis封裝resultSet結(jié)果集時(shí), 使用反射機(jī)制, 因此, 必須保證resultSet結(jié)果集中的屬性名稱與實(shí)體的名稱保持一致, 因此使用 resultType 遵循以下規(guī)則:

  • 數(shù)據(jù)庫(kù)的列名與實(shí)體屬性名保持一致(在Windows下MySQL不區(qū)分大小寫, 在Linux下MySQL區(qū)分大小寫, 一定要注意保持包括大小寫也一致)
  • 若數(shù)據(jù)庫(kù)列名與實(shí)體屬性名不一致, 使用select name as userName…, 來(lái)保持resultSet結(jié)果集屬性的值與實(shí)體中的屬性值一樣, 保證反射屬性封裝成功.
  • 使用resultMap定義表列名與實(shí)體屬性的對(duì)應(yīng)關(guān)系.
  • typeAliases(類型別名)

    使用類型別名后, 在parameterType, resultType中就不用寫很長(zhǎng)的類路徑, 直接簡(jiǎn)寫
    例如: 以前 => resultType=“com.regotto.domain.User” 后來(lái) => resultType=“user”

    <typeAliases><!--對(duì)單個(gè)實(shí)體進(jìn)行--><typeAlias alias="user" type="com.regotto.domain.User"><!--掃描當(dāng)前包下的類, 自動(dòng)別名設(shè)定為類名(首字母大小寫都行)--><package name="com.regotto.domain"> </typeAliases>

    mappers映射器(指定Mapper.xml或者注解修飾的類)

    使用Mapper.xml (最常用) <mapper resource="com/regotto/dao/UserMapper.xml"> 使用注解 <mapper class="com.regotto.dao.UserMapper"> mapper接口與Mapper.xml文件在同一個(gè)目錄中, 且文件名相同 <package name="com.regotto.dao">

    MyBatis數(shù)據(jù)源配置

    MyBatis數(shù)據(jù)源種類: UNPOOLED(不使用連接池), POOLED(使用連接池), JNDI(從JNDI上查找DataSource)
    使用連接池, 提高數(shù)據(jù)庫(kù)操作性能, 通常MyBatis使用的數(shù)據(jù)源為POOLED

    <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>

    MyBatis使用工廠模式創(chuàng)建DataSource, 源碼如下:

    public interface DataSourceFactory {void setProperties(Properties var1);DataSource getDataSource(); }import org.apache.ibatis.datasource.unpooled.UnpooledDataSourceFactory; //UnpooledDataSourceFactory implements DataSourceFactory public class PooledDataSourceFactory extends UnpooledDataSourceFactory {public PooledDataSourceFactory() {this.dataSource = new PooledDataSource();} }

    根據(jù)源碼PooledDataSource中popConnection(String username, String password)方法可得出, 當(dāng)執(zhí)行Sql語(yǔ)句的時(shí)候, 才會(huì)從連接池中獲得一個(gè)Connection, 使用完畢后, 再歸還連接池.

    MyBatis事務(wù)控制

    JDBC事務(wù)提交: connection.setAutoCommit(boolean b).
    MyBatis中事務(wù)提交源碼:

    //SqlSessionFactory.class代碼如下:public SqlSession openSession() {return this.openSessionFromDataSource(this.configuration.getDefaultExecutorType(), (TransactionIsolationLevel)null, false);}public SqlSession openSession(boolean autoCommit) {return this.openSessionFromDataSource(this.configuration.getDefaultExecutorType(),(TransactionIsolationLevel)null,autoCommit);}private SqlSession openSessionFromDataSource(ExecutorType execType, TransactionIsolationLevel level, boolean autoCommit)

    可使用SqlSessionFactory.openSession(true)設(shè)置自動(dòng)提交. 或者使用session.commit進(jìn)行手動(dòng)提交.

    動(dòng)態(tài)SQL

    對(duì)paramType中的參數(shù)進(jìn)行判斷, 條件成立, 則拼裝Sql, 不成立, 不拼裝Sql

    • if標(biāo)簽(條件判斷, where 1=1用于if條件不成立, 導(dǎo)致sql執(zhí)行錯(cuò)誤)
    <select id="findByUser" resultType="user" parameterType="user">select * from user where 1=1<if test="username!=null and username != '' ">and username like #{username}</if> <if test="address != null">and address like #{address}</if> </select>
    • where標(biāo)簽(簡(jiǎn)化where 1=1的寫法)
    <select id="findByUser" resultType="user" parameterType="user"> select * from user<where> <if test="username!=null and username != '' ">and username like #{username}</if> <if test="address != null">and address like #{address}</if> </where> </select>
    • foreach標(biāo)簽(等價(jià)于for循環(huán), 重復(fù)執(zhí)行Sql)
    class Query{private List<Integer> ids;//ids get set方法... } <!-- 查詢所有用戶在 id 的集合之中 --> <select id="findInIds" resultType="user" parameterType="com.regotto.Query"> <!-- select * from user where id in (1,2,3,4,5); -->select * from user<where> <if test="ids != null and ids.size() > 0"> <foreach collection="ids" open="id in ( " close=")" item="uid" separator=",">#{uid}</foreach></if></where> </select>SQL 語(yǔ)句:select 字段 from user where id in (?) <foreach>標(biāo)簽用于遍歷集合,它的屬性:collection:代表要遍歷的集合元素,注意編寫時(shí)不要寫#{}open:代表語(yǔ)句的開始部分close:代表結(jié)束部分item:代表遍歷集合的每個(gè)元素,生成的變量名sperator:代表分隔符

    MyBatis多表查詢

    • 一對(duì)一(多對(duì)一)
      User <=> Account
    1. 編寫sql語(yǔ)句: select * from user, account where user.id = account.id; 2. 定義實(shí)體(可以使用int, String等基本屬性定義, 定義的實(shí)體內(nèi)容決定了Mapper.xml中select標(biāo)簽的編寫方式)class AccountUser{private User user;private String id;private String name;//......//get, set方法} 3. 定義dao接口interface AccountUserMapper{AccountUser findAccountUser();} 4. 定義AccountUserMapper.xml文件resultMap建立查詢結(jié)果與AccountUser屬性的對(duì)應(yīng)關(guān)系<resultMap type="account" id="accountMap"> <id column="aid" property="id"/><result column="uid" property="uid"/><result column="money" property="money"/><!-- 它是用于指定從表方的引用實(shí)體屬性的 --> <association property="user" javaType="user"> <id column="id" property="id"/><result column="username" property="username"/><result column="sex" property="sex"/><result column="birthday" property="birthday"/><result column="address" property="address"/></association></resultMap> <select id="findAll" resultMap="accountMap">select u.*,a.id as aid,a.uid,a.money from account a,user u where a.uid =u.id;</select>
    • 一對(duì)多
      User <=> 多個(gè)Account
    1. 編寫sql: select u.*,a.id as aid ,a.uid,a.money from user u left outer join account a on u.id =a.uid 2. 定義實(shí)體class User{private String id;private String name;private List<Account> accounts;//get, set方法} 3. 定義dao接口方法: List<Account> findAll(); 4. UserMapper.xml <resultMap type="user" id="userMap"> <id column="id" property="id"></id> <result column="username" property="username"/><result column="address" property="address"/><result column="sex" property="sex"/><result column="birthday" property="birthday"/><!-- collection 是用于建立一對(duì)多中集合屬性的對(duì)應(yīng)關(guān)系ofType 用于指定集合元素的數(shù)據(jù)類型--> <collection property="accounts" ofType="account"> <id column="aid" property="id"/><result column="uid" property="uid"/><result column="money" property="money"/></collection> </resultMap> <!-- 配置查詢所有操作 --> <select id="findAll" resultMap="userMap">select u.*,a.id as aid ,a.uid,a.money from user u left outer join account a on u.id =a.uid </select>

    相比于一對(duì)一, 若實(shí)體屬性是集合等結(jié)構(gòu), 則使用collection標(biāo)簽

    • 多對(duì)多
      多個(gè)Role <=> 多個(gè)User, 中間表USER_ROLE
    1.編寫sql:SELECT r.*,u.id uid, u.username username FROM ROLE rINNER JOIN USER_ROLE ur ON ( r.id = ur.rid) INNER JOIN USER u ON (ur.uid = u.id); 2.編寫實(shí)體:class Role {private id;private name;List<User> users;//get set方法} 3.dao接口:List<Role> findAll(); 4.編寫Mapper.xml<!--定義 role 表的 ResultMap--><resultMap id="roleMap" type="role"><id property="roleId" column="rid"></id><result property="roleName" column="role_name"></result><result property="roleDesc" column="role_desc"></result><collection property="users" ofType="user"><id column="id" property="id"></id><result column="username" property="username"></result><result column="address" property="address"></result><result column="sex" property="sex"></result><result column="birthday" property="birthday"></result></collection></resultMap><!--查詢所有--><select id="findAll" resultMap="roleMap">select u.*,r.id as rid,r.role_name,r.role_desc from role r

    將多對(duì)多的關(guān)系拆分為兩個(gè)一對(duì)多的關(guān)系處理

    MyBatis延遲加載

    一定程度上提高查詢性能, 但是造成的問(wèn)題是: 當(dāng)存在大量查詢需要立即獲得數(shù)據(jù), 導(dǎo)致用戶體驗(yàn)下降.
    在SqlMapperConfig.xml配置文件中開啟延遲加載:

    <settings> <setting name="lazyLoadingEnabled" value="true"/><setting name="aggressiveLazyLoading" value="false"/> </settings>
    • association實(shí)現(xiàn)延遲加載
      account <=> 多個(gè)user
    AccountUserMapper.xml文件內(nèi)容 <!-- 建立對(duì)應(yīng)關(guān)系 --> <resultMap type="account" id="accountMap"> <id column="aid" property="id"/><result column="uid" property="uid"/><result column="money" property="money"/><!-- 對(duì)user進(jìn)行查詢的時(shí)候, 指定需要延遲加載的User方法, 對(duì)應(yīng)方法參數(shù)名稱--> <association property="user" javaType="user" select="com.itheima.dao.IUserDao.findById" column="uid"/></resultMap> <select id="findAll" resultMap="accountMap">select * from account</select> association屬性: select: 填寫我們要調(diào)用的 select 映射的 id column : 填寫我們要傳遞給 select 映射的參數(shù)
    • collection實(shí)現(xiàn)延遲加載
      user <=> 多個(gè)account
    AccountUserMapper.xml: <resultMap type="user" id="userMap"> <id column="id" property="id"></id> <result column="username" property="username"/><result column="address" property="address"/><result column="sex" property="sex"/><result column="birthday" property="birthday"/><!-- collection 是用于建立一對(duì)多中集合屬性的對(duì)應(yīng)關(guān)系ofType 用于指定集合元素的數(shù)據(jù)類型select 是用于指定查詢賬戶的唯一標(biāo)識(shí)(賬戶的 dao 全限定類名加上方法名稱)column 是用于指定使用哪個(gè)字段的值作為條件查詢--> <collection property="accounts" ofType="account" select="com.itheima.dao.IAccountDao.findByUid" column="id"> </collection> </resultMap> <!-- 配置查詢所有操作 --> <select id="findAll" resultMap="userMap">select * from user </select> <collection>標(biāo)簽:主要用于加載關(guān)聯(lián)的集合對(duì)象select 屬性:用于指定查詢 account 列表的 sql 語(yǔ)句,所以填寫的是該 sql 映射的 idcolumn 屬性:用于指定 select 屬性的 sql 語(yǔ)句的參數(shù)來(lái)源,上面的參數(shù)來(lái)自于 user 的 id 列,所以就寫成 id 這一個(gè)字段名

    **結(jié)論: **使用association或者collection進(jìn)行延遲加載, 需要指定select, column, association與collection的區(qū)別: association使用property, javaType; collection使用property, ofType; property都是指定實(shí)體中屬性的名稱, javaType, ofType是指定集合泛型.

    MyBatis緩存

    一級(jí)緩存(SqlSession級(jí)別, Session存在緩存就存在)

    在映射文件中設(shè)定查詢結(jié)果的緩存有效:

    <!-- 根據(jù) id 查詢 --> <select id="findById" resultType="UsEr" parameterType="int" useCache="true">select * from user where id = #{uid} </select>useCache: 設(shè)定緩存是否有效

    執(zhí)行查詢操作之后, 結(jié)果放入一級(jí)緩存中, 下次查詢, 數(shù)據(jù)還是存緩存中獲取.

    二級(jí)緩存(Mapper映射級(jí)別, 多個(gè)Session共用一個(gè)緩存)

    1.在SlqMapperConfig.xml中開啟二級(jí)緩存

    MyBatis默認(rèn)開啟二級(jí)緩存 <settings><!-- 開啟二級(jí)緩存的支持 --> <setting name="cacheEnabled" value="true"/> </settings>

    2.在select標(biāo)簽上配置useCache標(biāo)簽值
    注: 使用緩存存儲(chǔ)對(duì)象, 實(shí)體必須實(shí)現(xiàn) Serializable接口

    MyBatis注解開發(fā)不具有靈活性, 不使用

    總結(jié)

    以上是生活随笔為你收集整理的MyBatis动态SQL_多表查询_延迟加载_缓存的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

    如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。