復(fù)習(xí)了下,把不難又容易遺忘的部分記錄了下來嚎卫。
demo記錄在https://github.com/wangyu19810820/MyBatisWebDemo
1.MyBatis也有一個主控配置文件
文件名隨意售担,在構(gòu)建(build)SqlSessionFactory的時候傳入
也可以通過代碼直接構(gòu)建設(shè)置
2.數(shù)據(jù)庫操作一般在SqlSession中完成
3.常用類型的別名
在配置映射關(guān)系,自定義構(gòu)造函數(shù)的時候酷宵,需要指定jdbc類型和java類型
其中java類型的別名簡寫有如下規(guī)則
Integer可用:Integer或粮,integer幽歼,int
int可用:_int
String可用:String朵锣,string
其余類推
4.映射文件中的insert語句,獲取數(shù)據(jù)庫自增主鍵甸私,需要指定useGeneratedKeys和keyProperty
<insert id="insert" useGeneratedKeys="true" keyProperty="id">
insert into USER (name) values (#{name})
</insert>
5.映射文件中的參數(shù)
有兩種猪勇,#{xxx},${xxx}颠蕴,前一種自動轉(zhuǎn)義泣刹,后一種直接拼接,會有SQL注入安全問題
單參數(shù)可寫成任何值犀被,比如:#{name}椅您,但是在動態(tài)sql中需要用_parameter,比如:<if test="_parameter != null">.......</if>
多個參數(shù)寡键,會自動轉(zhuǎn)換成map
6.鑒別器discriminator
可以用內(nèi)聯(lián)寫法或外部resultMap掀泳,但是一個resultMap內(nèi)只能一個discriminator
用外部resultMap后,這行數(shù)據(jù)整體應(yīng)用新映射
用內(nèi)聯(lián)寫法西轩,會結(jié)合原映射和新映射
沒匹配成功员舵,會使用原映射
<resultMap id="defaultResultMap" type="com.model.User" autoMapping="false">
<id column="id" property="id"></id>
<result column="name" property="name"></result>
<discriminator javaType="_int" column="usertype">
<case value="0" resultMap="studentResultMap">
</case>
<case value="1" resultType="com.model.User">
<result column="name" property="otherName"></result>
<result column="teachernumber" property="teacherNumber"></result>
</case>
</discriminator>
</resultMap>
7.一對一映射,一對多映射
一種是單條sql查詢出所有內(nèi)容藕畔,直接映射成結(jié)果對象
<association property="college" columnPrefix="c_"
resultMap="mapper.CollegeMapper.defaultResultMap">
</association>
<!-- 一對多 -->
<collection property="scoreList" columnPrefix="s_"
ofType="com.model.Score">
<id property="id" column="id"></id>
<result property="name" column="name"></result>
<result property="score" column="score"></result>
</collection>
因為不同表內(nèi)的字段很容易重名马僻,所以要單獨設(shè)置映射關(guān)系,或者指定前綴如columnPrefix="c_"
這種映射方法注服,在分頁查詢時韭邓,有分頁數(shù)量的bug難以解決
另一種是多條sql查詢內(nèi)容
<association fetchType="eager" property="college" column="COLLEGEID"
select="mapper.CollegeMapper.selectCollegeById">
</association>
<!-- 一對多 -->
<collection fetchType="lazy" property="scoreList" column="id"
ofType="com.model.Score"
select="mapper.ScoreMapper.selectScoreByUserId">
</collection>
fetchType="lazy"配置成懶加載,該屬性項只在新版本內(nèi)才有效
這種映射方法溶弟,在分頁查詢時女淑,無數(shù)量bug,比較簡單
- 自動映射
啟用自動映射可以大大減少映射文件的代碼量辜御,尤其是為新項目構(gòu)建代碼鸭你,比較方便
但是也會引入一些干擾項,最好能清楚的認識其運作機制
主控配置文件中可以設(shè)置自動映射等級autoMappingBehavior,默認值PARTIAL是本表自動映射袱巨,join表手動映射袜茧,比較合理的。官方文檔也舉例了瓣窄,用FULL的話,很容易出現(xiàn)id映射錯誤
mapUnderscoreToCamelCase指定映射規(guī)則是否進行下劃線轉(zhuǎn)駝峰轉(zhuǎn)換纳鼎,很實用
字段如果沒有被手工映射俺夕,則將被自動映射。
9.分頁
方式一:Mybatis內(nèi)置了RowBounds分頁對象贱鄙,只需在Dao方法的參數(shù)中添加RowBounds參數(shù)就可以了劝贸。但,它是通過操縱jdbc的ResultSet定位來實現(xiàn)分頁逗宁。
方式二:PageHelper插件是通過攔截修改sql映九,來實現(xiàn)數(shù)據(jù)分頁的。
11.分頁和一對多結(jié)合使用的時候瞎颗,有結(jié)果數(shù)目不正確的問題
內(nèi)置的RowBounds分頁和PageHelper插件件甥,都會有問題,解決不了
解決方案哼拔,一種是采用多條sql獲取一對多數(shù)據(jù)引有,參考第7條
另一種是變換sql寫法,將分頁參數(shù)傳入xml中
select u.ID, u.NAME, u.USERTYPE,
c.ID C_ID, c.NAME C_NAME,
s.ID S_ID, s.NAME S_NAME, s.SCORE S_SCORE
from USER u
left join COLLEGE c on u.COLLEGEID = c.id
left join SCORE s on u.ID = s.USERID
where u.ID in (select ID from USER limit #{pageSize} offset #{pageSize} * #{pageNumber})
12.動態(tài)sql倦逐,動態(tài)組裝sql
包含if,choose,trim,where,set,foreach等
sql標簽可復(fù)用sql片段
bind標簽可從OGNL表達式中創(chuàng)建一個變量并將其綁定到上下文
13.支持多數(shù)據(jù)庫
配置文件啟用數(shù)據(jù)庫廠商標識譬正,并配置“縮寫”
實際測試下來,必須要指定“縮寫”檬姥,否則無法獲取databaseId
<databaseIdProvider type="DB_VENDOR">
<property name="MySQL" value="mysql" />
<property name="H2" value="h2" />
</databaseIdProvider>
映射文件檢測databaseId
<if test="_databaseId == 'h2'">
可在Configuration中獲取當(dāng)前數(shù)據(jù)庫廠商標識
String databaseId = sqlSession.getConfiguration().getDatabaseId();
13.批量更新
有兩種批量更新方式
一種用動態(tài)sql中的foreach標簽曾我,拼接sql
一種用openSession(ExecutorType.BATCH)指定批量更新模式
實際測試下來,對于性能僅有小幅提升
14.自定義類型處理器
可擴展接口健民,或繼承自BaseTypeHandler抒巢,實現(xiàn)自定義讀寫方法
并在配置文件中配置
15.枚舉處理
類似于自定義類型處理器
內(nèi)置了兩個實現(xiàn)類
EnumTypeHandler在數(shù)據(jù)庫中存儲枚舉的字符值
EnumOrdinalTypeHandler存儲枚舉的索引值
16.插件
插件實現(xiàn)Interceptor接口,用注解標記攔截方法秉犹,并在配置文件中注冊插件
其中intercept方法是主體功能所在方法
plugin方法虐秦,用于多個插件按序調(diào)用,一般如下寫死
public Object plugin(Object target) {
return Plugin.wrap(target, this);
}
setProperties方法凤优,從配置文件中獲取參數(shù)悦陋,然后存入類字段中
17.二級緩存
確保配置文件中開啟二級緩存
<setting name="cacheEnabled" value="true" />
映射文件中
<cache />
如果只是最簡單的內(nèi)存緩存,可用僅僅寫一個cach標簽
自定義實現(xiàn)類筑辨,需指定type屬性
18.redis作為二級緩存
官方提供了mybatis-redis庫俺驶,在maven2下可用
在classpath下新建redis.properties,配置redis連接
映射文件中配置<cache type="org.mybatis.caches.redis.RedisCache" />
具體參考http://www.mybatis.org/redis-cache/index.html
x.和spring集成
仍然可以在spring中配置mybatis的配置文件,但是數(shù)據(jù)源暮现,事務(wù)还绘,映射文件一般都在spring中配置
mybatis和mybatis-sprin的類庫版本要匹配,最好都用最新的穩(wěn)定版本
因為掃描映射類(Mapper類)處于spring加載的時期栖袋,會導(dǎo)致自動映射properties特性失效拍顷。一般改為延遲加載,指定sqlSessionFactoryBeanName而非sqlSessionFactoryBean塘幅。
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<!-- configLocation:用于指定Mybatis的配置文件位置 -->
<property name="configLocation" value="classpath:mybatis-config-spring.xml"></property>
<!-- 指定映射文件 -->
<property name="mapperLocations" value="classpath*:mapper/**/*.xml"></property>
</bean>
<!-- 尋找Mapper類(Dao類) -->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="com.dao" />
<property name="sqlSessionFactoryBeanName" value="sqlSessionFactory" />
</bean>
或
@Bean
public SqlSessionFactory sqlSessionFactory() throws Exception {
PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
sqlSessionFactoryBean.setDataSource(dataSource());
sqlSessionFactoryBean.setConfigLocation(new ClassPathResource("mybatis-config-spring.xml"));
sqlSessionFactoryBean.setMapperLocations(resolver.getResources("classpath:/mapper/**/*.xml"));
return sqlSessionFactoryBean.getObject();
}
@Bean
public MapperScannerConfigurer getMapperScannerConfigurer() {
MapperScannerConfigurer configurer = new MapperScannerConfigurer();
configurer.setBasePackage("com.dao");
configurer.setSqlSessionFactoryBeanName("sqlSessionFactory");
return configurer;
}