SqlSessionFactoryBuilder ->SqlSessionFactory->SqlSession->SQL Mapper
SqlSessionFactoryBuilder :根據配置生成SqlSessionFactory , 構建完所有SqlSessionFactory
SqlSessionFactory:依靠工廠生成SqlSession ,單例,整個生命週期
SqlSession:可以發送SQL執行並返回結果,也可以獲取Mapper接口 及時關閉
SQL Mapper:java interface+XML 給出sql映射規則,發送SQL執行並返回結果 一個SqlSession事務方法中使用,然後廢棄
SqlMapConfig.xml 全局配置文件
properties(屬性)
settings(全局配置參數)
typeAliases(類型別名)
typeHandlers(類型處理器)
objectFactory(對象工廠)
plugins(插件)
environments(環境集合屬性對象)
–environment(環境子屬性對象)
----transactionManager(事務管理)
----dataSource(數據源)
----mappers(映射器)
db.properties
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/mybatis
jdbc.username=root
jdbc.password=root
/*
其中 properties 配置分爲 1.xml中 2.db.properties 3.程序參數 ,優先級由低到高。
*/
相應的SqlMapConfig.xml
typeAliases 不區分大小寫
<typeAliases>
<!-- 單個別名定義 -->
<typeAlias alias="user" type="com.pojo.User"/>
<!-- 批量別名定義,掃描整個包下的類,別名爲類名(首字母大小寫都可以) -->
<package name="com.pojo"/> //配合 @Alias("user") 爲空則 首字母變小寫 如:UserType -> userType
</typeAliases>
typeHandlers 負責javatype與數據庫類型轉換 ,可自定義,如枚舉類型轉化,性別 0 men 1 weman
environments 數據源配置
<environments default="1">
<environment id="1">
<transactionManager type="JDBC">
<property name="autoCommit" value="false"/>
</transactionManager>
<dataSource type="POLLED"> //POLLED UNPOLLED JNDI 也可自定義 type=" 替換即可 "
</property> // name pwd....
</dataSource>
</environment>
<environment id="2">
</environment>
</environments>
select詳解
<?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="對應DAO接口">
<select id="對應DAO接口方法名" parameterType=“Integer” resultType="org.chench.test.mybatis.model.Test">
select * from test where id = #{id}
</select>
</mapper>
/* 可以開啓駝峯命名自動映射 mapUnderscoreToCamelCase=true
namespace="對應DAO接口"
id="對應DAO接口方法名"
parameterType 類全名、別名,方法參數類型
resultType 查詢返回值類型
resultMap 定義數據庫表字段與POJO一一對應
*/
傳遞多個參數
<select id="對應DAO接口方法名" parameterType="map" resultMap="xxx">
select * from test where id = #{id}
</select>
public List<Role> getList(Map<String,String> params);
其中 params.put("name","xxx");
params.put("sex","xxx");
<select id="對應DAO接口方法名" parameterType=“map” resultMap="xxx">
select * from test where name = #{name} and sex=#{sex}
</select>
public List<Role> getList(@Param("userName")String username);
<select id="對應DAO接口方法名" resultMap="xxx">
select * from test where name = #{userName}
</select>
//userName ...與Role屬性一致
public List<Role> getList(Role role);
<select id="對應DAO接口方法名" parameterType="org.chench.test.mybatis.model.Role" resultMap="xxx">
select * from test where name = #{userName} and sex=#{sex}
</select>
<resultMap id="唯一" type="對應pojo全限定名">
<id property="id" column="id"></id>
<result property="userName" column="user_name"></result>
</resultMap>
id:標識主鍵
插入值,並返回插入的主鍵值 給 傳入的對象的對應屬性 表設計應該設置爲自增
insert into t_tole(name,sex) values(#{roleName},#{sex})
int insertRole(Role role);
Role r = new Role();
r.setName();
r.setSex();
myDao.insertRole®;
sout(r.getId()); //獲取插入的記錄的 主鍵id值
當然可以 自定義規則, 如當前表爲空則置爲1 ,否則當前基礎上+2 此時數據庫表的自增 關閉
select if(max(id) is null,1,max(id)+2) as newId from t_role
insert into t_tole(id,name,sex) values(#{id},#{roleName},#{sex})
定義參數屬性不允許換行
sql元素
<sql id = "role_columns">
id,sex,phone
</sql>
<select parameterType="long" id = "getRole" resultMap="roleMap">
select <include refid="role_columns"/> from role where id = #{id}
</select>
<sql id = "role_columns">
#{prefix}.id,#{prefix}.sex,#{prefix}.phone
</sql>
<select parameterType="string" id = "getRole" resultMap="roleMap">
select
<include refid="role_columns">
<property name="prefix" value="r"></property>
</include>
from role where id = #{id}
</select>
<sql id = "some_include">
select * from <include refid="${tableName}" />
</sql>
resultMap 作用 :定義映射規則、級聯更新、定製類型轉換器等
<resultMap> //id="唯一" type="對應pojo全限定名"
<constructor> //配置構造方法 有的javabean不存在無參數構造器
<idArg> //注入同時 爲主鍵
</idArg>
<arg>
</arg>
</constructor>
<id/> //表明爲主鍵 <id property="id" column="id"></id>
<result/> //定義映射規則 property="javabean屬性" column="sql列名" javaType
// jdbcType typeHandler自定義規則
<association/> //支持級聯的一部分 一對一、一對多、多對多 解決一對一
//property="javabean屬性" column="傳給dao方法的參數" select="指向一個dao方法"
//這個屬性在在 ProvienceDao中
//如:省份表 id 名字 別名表 id 別名 AliasDao findById(Integer id)
//javabean id 名字 別名
// property="別名" column ="id" select="com.qmylzx.base.dao.AliasDao"
//select*from provience where id = #{id} select*from alias where id = #{id}
<connection/> //支持級聯的一部分 一對一、一對多、多對多 解決一對多
// property="cities" column="id" select="base.dao.findCityByPid"/>
<discriminator> //鑑別器級聯 解決多對多
<case/>
</discriminator>
</resultMap>
public class Province {
private Long id;
private String name;
private Alias alias;
private List cities; //城市表中有一個pid字段,該字段表示這個城市是屬於哪個省份的
//省略getter/setter
}
public interface CityMapper {
List findCityByPid(Long id);
}
discriminator 定義多個resultMap extends 標記type的javabean繼承的父類
<?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="dao.ProvinceMapper">
<resultMap id="provinceResultMapper" type="org.sang.bean.Province">
<id column="id" property="id"/>
<discriminator javaType="int" column="area"> // javaType column 以這個作爲區分
<case value="1" resultMap="noodleResultMap"></case>
<case value="2" resultMap="riceResultMap"></case>
</discriminator>
</resultMap>
<resultMap id="noodleResultMap" type="org.sang.bean.Province" extends="provinceResultMapper">
<collection property="foods" column="area" select="org.sang.db.NoodleMapper.findNoodleByArea"/>
</resultMap>
<resultMap id="riceResultMap" type="org.sang.bean.Province" extends="provinceResultMapper">
<collection property="foods" column="area" select="org.sang.db.RiceMapper.findRiceByArea"/>
</resultMap>
<select id="getProvince" resultMap="provinceResultMapper">
SELECT * FROM province
</select>
</mapper>
PS: 使用級聯 超過三層 複雜度上升、查詢到無用數據,造成性能下降, 爲了解決這個問題考慮延遲加載
全局延遲加載:setting中設置 lazyLoadingEnable = true aggressiveLazyLoading=ture
//僅開啓延遲加載還是會加載所有信息 , 開啓層級加載(aggressiveLazyLoading)後纔會只加載一部分,即使用的部分
局部延遲加載association 、connection 屬性fetchType eager、lazy
使用map存儲結果集 :一般而言,任何select語句都可用map
<select id = "findColorByNote" parameterType="string" resultType="map">
select id color note from t_color where note like concat('%',#{note},'%')
</select>
使用POJO
緩存
系統緩存(一級緩存、二級緩存):默認開啓一級緩存,即同一個SQLSession查詢後,若未聲明需要刷新或無緩存超時,則再次查詢,只會從緩存中獲取數據,而不會再次發送sql到數據庫(相同的mapper、參數和方法)
往往我們需要開啓二級緩存,使得在SQLSessionFactory層面上能夠提供給各個SQLSession對象共享,
開啓二級緩存:POJO需要可序列化(implements Serializable)、並在映射xml文件配置
PS:select語句會緩存、insert、update、delete會刷新緩存,系統使用默認的LRU算法來回收
根據時間表,如NO Flush Interval(無刷新間隔),緩存不會以任何時間順序來刷新
緩存會存儲列表集合或對象的1024個引用
緩存是可讀可寫的,即對象檢索不共享,而且可以安全的被調用者修改
cache 的屬性
eviction=“LRU” //回收策略 LRU、FIFO、SOFT軟引用(基於GC)、WEAK(這裏也是LRU,更積極基於GC)
flushInterva=" " //不配置默認sql執行才刷新緩存
size //引用數目,不適合太大,容易OOM
readOnly //默認爲false
type=“com.qmylzx.MyCache” //自定義緩存,如使用redis 只需要實現mybatis 提供的接口類
//以下,在MyCache中若有setHost(String host) 方法,則在初始化的時候會調用
動態SQL
if //單條件分支判定
select id,name,note from t_role where 1=1 and name like concat('%',#{roleName},'%')choose(when、otherwise) //多條件
select id,name,note from t_role where 1=1 and id=#{roleId} and note is not nulltrim(where、set) // 用於處理一些sql拼裝問題
where
<select id="findRoles" parameterType="string" resultMap="xxx">
select id,name,note from t_role
<where> //以上 if choose where 1=1 沒有會報錯,這裏可以用 where標籤
<if test="roleName!=null and roleName!=''">
and name like concat('%',#{roleName},'%')
</if>
</where>
</select>
trim 去掉一些特殊字符串 prefixOverrides代表要去掉的字符串 prefix代表前綴
<select id="findRoles" parameterType="string" resultMap="xxx">
select id,name,note from t_role
<trim prefix="where" prefixOverrides="and">
<if test="roleName!=null and roleName!=''">
and name like concat('%',#{roleName},'%')
</if>
</trim>
</select>
set 防止更新某列導致的全部字段都要發送一次 ,節省帶寬
<update>
update role
<set>
<if test="roleName!=null and roleName!=''">
roleName=#{roleName}
</if>
<if test="sex!=null and sex!=''">
sex=#{sex}
</if>
</set>
where roleId=#{roleId}
</update>
//以上set 可以替換爲 <trim prefix="set" prefixOverrides=",">
foreach // 在in語句等列舉條件常用
select * from t_user where sex in #{sex} //其中collection爲傳入參數名稱,可以是 數組、list、set等集合 //item是循環中當前元素,index當前元素在集合的下標bind //用於 mybatis 自己的方式 實現自定義的函數語法,而不用關心數據庫實現 mysql 的concat與oracle的 ||
<select id="findRoles" parameterType="string" resultMap="xxx">
<bind name="pattern_roleName" value="'%'+roleName+'%'"></bind>
<bind name="pattern_note" value="'%'+note+'%'"></bind>
select id,name,note from t_role
where name like #{pattern_roleName}
and note like #{pattern_note}
</select>
public List<Role> findRole(@Param("roleName")String roleName ,@Param("note")String note);