[Re] MyBatis-2
阿新 • • 發佈:2020-09-19
動態 SQL
如果你有使用 JDBC 或其他類似框架的經驗,你就能體會到根據不同條件拼接 SQL 語句有多麼痛苦。拼接的時候要確保不能忘了必要的空格,還要注意省掉列名列表最後的逗號。利用動態 SQL 這一特性可以徹底擺脫這種痛苦。
- 動態 SQL 是 MyBatis 強大特性之一。極大的簡化我們拼裝 SQL 的操作。
- 動態 SQL 元素和使用 JSTL 或其他類似基於 XML 的文字處理器相似。
- MyBatis 採用功能強大的基於 OGNL 的表示式來簡化操作。
if、where
<!-- List<Teacher> getTeacherByConditions(Teacher teacher); --> <select id="getTeacherByConditions" resultMap="teacherMap"> SELECT * FROM teacher <!-- <where>可以刪除前面多餘的 AND:SQL 查詢條件的 AND 一定要寫前面 --> <!-- <bind> 可以將 OGNL 表示式的值繫結到一個變數中,方便後來引用這個變數的值(沒用) --> <bind name="_tname" value="'%'+tname+'%'"> <where> <!-- ↓ 判斷條件,取出傳入的JavaBean的屬性,判斷其是否為空 --> <if test="tname!=null"> AND id > #{_tname} </if> <if test="subject!=null && !subject.equals("")"> AND subject LIKE #{subject} </if> <if test="birthday!=null"> AND birth_date < #{birthday} </if> </where> </select>
trim、sql (include)
<!-- 抽取可重用 SQL --> <sql id="selectTeacher">SELECT * FROM teacher</sql> <!-- List<Teacher> getTeacherByConditions(Teacher teacher); --> <select id="getTeacherByConditions" resultMap="teacherMap"> <!--引用可重用 SQL--> <include refid="selectTeacher"></include> <!-- <trim> 自定義字串擷取規則 prefix: 新增一個字首 suffix: 新增一個字尾 prefixOverrides: 如果字串開頭為指定值,則去除 suffixOverrides: 如果字串尾部為指定值,則去除 --> <trim prefix="WHERE" suffixOverrides="AND"> <if test="tid!=null"> id > #{tid} AND </if> <if test="subject!=null && !subject.equals("")"> subject LIKE #{subject} AND </if> <if test="birthday!=null"> birth_date < #{birthday} AND </if> </trim> </select>
choose (when, otherwise)
<!-- List<Teacher> getTeacherByOneCondition(Teacher teacher) --> <select id="getTeacherByOneCondition" resultMap="teacherMap"> SELECT * FROM teacher <where> <choose> <when test="tid!=null"> id > #{tid} </when> <when test="subject!=null && !subject.equals("")"> subject LIKE #{subject} </when> <when test="birthday!=null"> birth_date < #{birthday} </when> <otherwise>1=1</otherwise> </choose> </where> </select>
set
<!--
// 帶哪些欄位,更新哪些欄位 → 致使 @ModelAttribute 無使用場景
public int updateTeacher(Teacher teacher);
-->
<update id="updateTeacher">
UPDATE teacher
<!-- UPDATE teacher SET <trim suffix="WHERE" suffixOverrides=","> -->
<!-- set 去除末尾多餘的',' -->
<set>
<if test="tname!=null && !tname.equals("")">
tname=#{tname},
</if>
<if test="subject!=null && !subject.equals("")">
subject=#{subject},
</if>
<if test="address!=null && !address.equals("")">
address=#{address},
</if>
<if test="birthday!=null">
birth_date=#{birthday},
</if>
</set>
<where>
tid = #{tid}
</where>
</update>
foreach
動態 SQL 的另外一個常用的必要操作是需要對一個集合進行遍歷,通常是在構建 IN 條件語句的時候。
<!-- List<Teacher> getTeacherByIdIn(List<Integer> ids) -->
<select id="getTeacherByIdIn" resultMap="teacherMap">
SELECT * FROM teacher WHERE tid IN
<!--
collection="" 要遍歷的集合
遍歷的是 List:
> index 儲存當前索引
> item 將當前遍歷出的元素賦值給指定的變數
遍歷的是 Map:
> index 指定的變數就是儲存當前遍歷的 entry 的 key
> item 指定的變數儲存當前遍歷的 entry 的 value
·······················
separator="" 元素之間的分隔符
open="" 以什麼開始
close="" 以什麼結束
-->
<if test="ids.size > 0">
<foreach collection="list" separator="," index="" item="id" open="(" close=")">
#{id}
</foreach>
</if>
</select>
<!-- void addTeachers(@Param("teachers") List<Teacher> teachers) -->
<insert id="addTeachers">
INSERT INTO teacher(tname, subject) VALUES
<foreach collection="teachers" separator="," item="teacher">
(#{teacher.tname}, #{teacher.subject})
</foreach>
</insert>
<!--
MYSQL:
除了將 VALUES 後的語句迴圈執行外,還可以將整條 SQL 語句都放入迴圈體中,語句末尾用';'
除此之外,連線 DB 的 url 末尾還必須要增添一個連線屬性:allowMultiQueries=true
Oracle: 多條插入 SQL 要放在 begin...end; 中
-->
OGNL
在 MyBatis 中,傳入的引數可以用來做判斷,額外的還有兩個內建引數:
_parameter:
若傳入了單個引數,就代表這個引數
若傳入了多個引數,就代表這多個引數封裝起來的Map
_databaseId: 如果配置了 databaseIdProvider,則該引數代表當前環境
<if test="_databaseId == 'mysql'"> ... </if>
<if test="_databaseId == 'oracle'"> ... </if>
快取機制
快取:暫時儲存一些資料,可以極大的提升查詢效率。MyBatis 系統中預設定義了兩級快取。
- 一級快取:執行緒級別的快取;基於 SqlSession 級別的,也稱為本地快取;預設開啟
- 二級快取:全域性範圍的快取;基於 namespace 級別的快取。除過當前執行緒的 SqlSession 能用外,其他也可以二級快取。需要手動開啟和配置
一級快取
簡述
- 一級快取(local cache),即本地快取,作用域預設為 SqlSession。當 Session flush 或 close 後,該 Session 中的所有 Cache 將被清空。
- 本地快取不能被關閉,但可以呼叫 clearCache() 來清空本地快取, 或者改變快取的作用域。
- 在 Mybatis 3.1 之後,可以配置本地快取的作用域(在 mybatis.xml 中配置)
演示
@Test
public void test() {
SqlSession sqlSession = sqlSessionFactory.openSession(true);
TeacherMapper mapper = sqlSession.getMapper(TeacherMapper.class);
Teacher teacher1 = mapper.getTeacherByTid(1);
System.out.println(teacher1);
Teacher teacher2 = mapper.getTeacherByTid(1);
System.out.println(teacher2);
System.out.println(teacher1 == teacher2); // true
}
同一次會話期間只要查詢過的資料都會儲存在當前 SqlSession 的一個 HashMap 中。
失效情況
每次查詢,先看一級快取(SqlSession 級別的快取) 中有沒有,如果沒有再去發新的 SQL。
- 不同的 SqlSession,使用不同的一級快取;只有在同一個 SqlSession 期間查詢到的資料會儲存在這個 SqlSession 的快取中;下次這個 SqlSession 再去查詢會先在它自己的快取中去找。
- 同一條 SQL 語句,但是引數不同,就會導致 key 有變化,所以還會發新的 SQL
- 在這個 SqlSession 執行期間執行任何一次增刪改操作,都會致使快取被清空
- 同一個 SqlSession 兩次查詢期間手動清空了快取
原始碼
public class PerpetualCache implements Cache {
private String id;
// 底層就是一個 Map
private Map<Object, Object> cache = new HashMap<Object, Object>();
public PerpetualCache(String id) {
this.id = id;
}
@Override
public String getId() {
return id;
}
@Override
public int getSize() {
return cache.size();
}
@Override
public void putObject(Object key, Object value) {
cache.put(key, value);
}
@Override
public Object getObject(Object key) {
return cache.get(key);
}
@Override
public Object removeObject(Object key) {
return cache.remove(key);
}
@Override
public void clear() {
cache.clear();
}
@Override
public ReadWriteLock getReadWriteLock() {
return null;
}
@Override
public boolean equals(Object o) {
if (getId() == null) {
throw new CacheException("Cache instances require an ID.");
}
if (this == o) {
return true;
}
if (!(o instanceof Cache)) {
return false;
}
Cache otherCache = (Cache) o;
return getId().equals(otherCache.getId());
}
@Override
public int hashCode() {
if (getId() == null) {
throw new CacheException("Cache instances require an ID.");
}
return getId().hashCode();
}
}
BaseExecutor
@SuppressWarnings("unchecked")
@Override
public <E> List<E> query(MappedStatement ms, Object parameter
, RowBounds rowBounds, ResultHandler resultHandler
, CacheKey key, BoundSql boundSql) throws SQLException {
ErrorContext.instance().resource(ms.getResource())
.activity("executing a query").object(ms.getId());
if (closed) {
throw new ExecutorException("Executor was closed.");
}
if (queryStack == 0 && ms.isFlushCacheRequired()) {
clearLocalCache();
}
List<E> list;
try {
queryStack++;
// 快取中有沒有
list = resultHandler == null ? (List<E>) localCache.getObject(key) : null;
if (list != null) { // 有
handleLocallyCachedOutputParameters(ms, key, parameter, boundSql);
} else { // 沒有
list = queryFromDatabase(ms, parameter, rowBounds, resultHandler, key, boundSql);
}
} finally {
queryStack--;
}
if (queryStack == 0) {
for (DeferredLoad deferredLoad : deferredLoads) {
deferredLoad.load();
}
// issue #601
deferredLoads.clear();
if (configuration.getLocalCacheScope() == LocalCacheScope.STATEMENT) {
// issue #482
clearLocalCache();
}
}
return list;
}
二級快取
簡述
- 二級快取(second level cache),全域性作用域快取
- MyBatis 提供二級快取的介面以及實現,快取實現要求 POJO 實現 Serializable 介面
- 二級快取在 SqlSession 關閉或提交之後才會生效 → 這也就意味著不可能會出現一級快取和二級快取中有同一個資料!
- 二級快取中:不關就會一直放在一級快取;只有一級快取關閉,資料才會被遷移至二級快取
- 一級快取中:二級快取中沒有此資料,就會看一級快取,一級快取中沒有就會去查 DB。DB 的查詢結果放在一級快取中了
- 任何時候都是先看二級快取,再看一級快取
原理
二級快取基於 namespace。沒有配置 <cache>
的 Mapper.xml 就沒有二級快取。並且,在二級快取中,不同 Mapper 的資料都是存放在各自的 Map 中。
快取相關屬性
- eviction="LRU" 快取回收策略
- LRU – 最近最少使用的:移除最長時間不被使用的物件。
- FIFO – 先進先出:按物件進入快取的順序來移除它們。
- SOFT – 軟引用:移除基於垃圾回收器狀態和軟引用規則的物件。
- WEAK – 弱引用:更積極地移除基於垃圾收集器狀態和弱引用規則的物件。
- flushInterval 重新整理間隔
- 單位毫秒
- 預設情況是不設定,也就是沒有重新整理間隔,快取僅僅呼叫語句時重新整理
- size:引用數目
- 正整數
- 代表快取最多可以儲存多少個物件,太大容易導致記憶體溢位
- readOnly:只讀
- true:只讀快取;會給所有呼叫者返回快取物件的引用。因此這些物件不能被修改。這提供了很重要的效能優勢。
- false:讀寫快取;會返回快取物件的拷貝(通過反序列化)。這會慢一些,但是安全,因此預設是 false。
快取有關設定
- 全域性 setting 的 cacheEnable:配置二級快取的開關
<setting name="cacheEnabled" value="true"/>
<select>
的 useCache 屬性:配置這個 select 是否使用二級快取 (一級快取一直是使用的)- 增刪改標籤的 flushCache 屬性:增刪改預設
flushCache=true
,查詢預設flushCache=false
。SQL 執行以後,會同時清空一級和二級快取。 sqlSession.clearCache()
只是用來清除一級快取- 當在某一個作用域 (一級快取Session/二級快取Namespaces) 進行了 C/U/D 操作後,預設該作用域下所有 select 中的快取將被 clear。
整合第三方快取
- MyBatis 定義了 Cache 介面方便我們進行自定義擴充套件。
- EhCache 是一個純 Java 的程序內快取框架,具有快速、精幹等特點,是 Hibernate 中預設的 CacheProvider。
- EhCache 使用步驟
- 匯入 ehcache 包,以及整合包,日誌包
ehcache-core-2.6.8.jar (ehcache 核心包) mybatis-ehcache-1.0.3.jar (ehcache 整合包) slf4j-api-1.6.1.jar slf4j-log4j12-1.6.2.jar
- 編寫 ehcache.xml 配置檔案
<?xml version="1.0" encoding="UTF-8"?> <ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../config/ehcache.xsd"> <!-- 磁碟儲存路徑 --> <diskStore path="U:\ehcache" /> <defaultCache maxElementsInMemory="3000" maxElementsOnDisk="10000000" eternal="false" overflowToDisk="true" timeToIdleSeconds="120" timeToLiveSeconds="120" diskExpiryThreadIntervalSeconds="120" memoryStoreEvictionPolicy="LRU"> </defaultCache> </ehcache>
- 在 Mapper.xml 中配置 cache 標籤
<cache type="org.mybatis.caches.ehcache.EhcacheCache"></cache>
- 匯入 ehcache 包,以及整合包,日誌包
- Tips
- POJO 可以不用實現 Serializable 介面
- 參照快取:若想在名稱空間中共享相同的快取配置和例項。可用
<cache-ref>
來引用另外一個快取。<cache-ref namespace="cn.edu.nuist.mapper.TeacherMapper" />
SSM 整合
導包
Spring
[AOP核心]
com.springsource.net.sf.cglib-2.2.0.jar
com.springsource.org.aopalliance-1.0.0.jar
com.springsource.org.aspectj.weaver-1.6.8.RELEASE.jar
spring-aspects-4.0.0.RELEASE.jar
[IOC核心]
commons-logging-1.1.3.jar
spring-aop-4.0.0.RELEASE.jar
spring-beans-4.0.0.RELEASE.jar
spring-context-4.0.0.RELEASE.jar
spring-core-4.0.0.RELEASE.jar
spring-expression-4.0.0.RELEASE.jar
[JDBC核心]
spring-jdbc-4.0.0.RELEASE.jar
spring-orm-4.0.0.RELEASE.jar
spring-tx-4.0.0.RELEASE.jar
SpringMVC
[Ajax]
jackson-annotations-2.1.5.jar
jackson-core-2.1.5.jar
jackson-databind-2.1.5.jar
[資料校驗]
hibernate-validator-5.0.0.CR2.jar
hibernate-validator-annotation-processor-5.0.0.CR2.jar
classmate-0.8.0.jar
jboss-logging-3.1.1.GA.jar
validation-api-1.1.0.CR1.jar
[上傳下載]
commons-fileupload-1.2.1.jar
commons-io-2.0.jar
[jstl]
jstl.jar
standard.jar
[SpringMVC核心]
spring-web-4.0.0.RELEASE.jar
spring-webmvc-4.0.0.RELEASE.jar
MyBatis
[MyBatis核心]
mybatis-3.4.1.jar
mybatis-spring-1.3.0.jar
[ehcache整合]
ehcache-core-2.6.8.jar
mybatis-ehcache-1.0.3.jar
log4j-1.2.17.jar
slf4j-api-1.7.21.jar
slf4j-log4j12-1.7.21.jar
database
mysql-connector-java-5.1.37-bin.jar
c3p0-0.9.1.2.jar
寫配置
web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app ...>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
<!-- 編碼過濾器 -->
<filter>
<filter-name>CharacterEncodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>utf-8</param-value>
</init-param>
<init-param>
<param-name>forceEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>CharacterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!-- REST 過濾器 -->
<filter>
<filter-name>HiddenHttpMethodFilter</filter-name>
<filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>HiddenHttpMethodFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!-- 配置 spring 容器啟動 -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring/applicationContext.xml</param-value>
</context-param>
<!-- Bootstraps the root web application context before servlet initialization -->
<listener>
<listener-class>
org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>
<!-- 配置 SpringMVC 前端控制器 -->
<servlet>
<servlet-name>springDispatcherServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring/applicationContext-mvc.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<!-- Map all requests to the DispatcherServlet for handling -->
<servlet-mapping>
<servlet-name>springDispatcherServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
SpringMVC 配置檔案
applicationContext-mvc.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans ...>
<context:component-scan base-package="cn.edu.nuist" use-default-filters="false">
<context:include-filter type="annotation"
expression="org.springframework.stereotype.Controller"/>
</context:component-scan>
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/pages/"></property>
<property name="suffix" value=".jsp"></property>
</bean>
<!-- 檔案上傳解析器 -->
<bean id="multipartResolver"
class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<property name="defaultEncoding" value="UTF-8"></property>
<property name="maxUploadSize" value="#{1024*1024*20}"></property>
</bean>
<!-- 掃靜態 -->
<mvc:default-servlet-handler/>
<!-- 掃動態 -->
<mvc:annotation-driven></mvc:annotation-driven>
</beans>
Spring配置檔案
applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans ...>
<!-- 1. 包掃描 -->
<context:component-scan base-package="cn.edu.nuist">
<context:exclude-filter type="annotation"
expression="org.springframework.stereotype.Controller"/>
</context:component-scan>
<!-- 2. 匯入外部配置檔案 -->
<context:property-placeholder location="classpath:dbconfig.properties"/>
<!-- 3. 配資料來源 -->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="${jdbc.driverClass}"/>
<property name="jdbcUrl" value="${jdbc.jdbcUrl}"/>
<property name="user" value="${jdbc.user}"/>
<property name="password" value="${jdbc.password}"/>
<property name="maxPoolSize" value="${jdbc.maxPoolSize}"></property>
<property name="minPoolSize" value="${jdbc.minPoolSize}"></property>
</bean>
<!-- 4. 整合 MyBatis !!! -->
<!-- 4.1 根據配置檔案,生產 SqlSessionFactory 的工廠 bean -->
<bean id="sqlSessionFactoryBean" class="org.mybatis.spring.SqlSessionFactoryBean">
<!-- 指定 MyBatis 全域性配置檔案的位置 -->
<property name="configLocation" value="classpath:mybatis/mybatis-config.xml"></property>
<!-- 引用 Spring 建立的資料來源 (事務控制是 Spring 在做) -->
<property name="dataSource" ref="dataSource"></property>
<!-- 指定 Mapper 對映檔案的位置 -->
<property name="mapperLocations" value="classpath:mybatis/mapper/*.xml"></property>
</bean>
<!-- 4.2 該 bean 把每一個 Mapper<I> 代理實現加入到 IOC 容器中 -->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<!-- 指定 Mapper<I> 所在包 -->
<property name="basePackage" value="cn.edu.nuist.mapper"></property>
</bean>
<!-- <mybatis-spring:scan base-package="cn.edu.nuist.mapper"> -->
<!-- 5. [事務控制] 配置事務管理器,讓其控制資料來源中連線的關閉和提交 -->
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean>
<!-- 6. 基於 XML 配置事務,詳見 [Re:Spring-2]#7.6 -->
<aop:config>
<!-- 配置切入點表示式((哪些方法切入事務) -->
<aop:pointcut expression="execution(* cn.edu.nuist.service.*.*(..))" id="txPoint"/>
<aop:advisor advice-ref="myTx" pointcut-ref="txPoint"/>
</aop:config>
<!-- 7. 事務增強(屬性)-->
<tx:advice id="myTx" transaction-manager="transactionManager">
<!-- 配置事務屬性 -->
<tx:attributes>
<tx:method name="*" rollback-for="java.lang.Exception"/>
<tx:method name="get*" read-only="true"/>
</tx:attributes>
</tx:advice>
</beans>
mybatis 配置檔案
<?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>
<plugins>
<plugin interceptor="com.github.pagehelper.PageInterceptor"></plugin>
</plugins>
</configuration>
其他配置檔案
dbconfig.properties
jdbc.user=root
jdbc.password=root
jdbc.jdbcUrl=jdbc:mysql:///test
jdbc.driverClass=com.mysql.jdbc.Driver
jdbc.maxPoolSize=100
jdbc.minPoolSize=10
測試
略
MBG
MyBatis Generator,簡稱 MBG,是一個專門為 MyBatis 框架使用者定製的程式碼生成器,可以快速的根據表生成對應的對映檔案、介面以及 bean 類。支援基本的增刪改查,以及 QBC 風格的條件查詢。但是表連線、儲存過程等這些複雜 SQL 的定義需要我們手工編寫。
mybatis-generator-core-1.3.2.jar
MBG 配置檔案
- javaModelGenerator 配置 JavaBean 的生成策略
- sqlMapGenerator 配置 SQL 對映檔案的生成策略
- javaClientGenerator 配置 Mapper 介面的生成策略
- table 配置要逆向解析的資料表
- tableName:表名
- domainObjectName:對應的 JavaBean 名字
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE generatorConfiguration
PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"
"http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">
<generatorConfiguration>
<!--
targetRuntime
MyBatis3Simple:基礎版 CRUD
MyBatis3:複雜版(帶動態 SQL) CRUD
-->
<context id="DB2Tables" targetRuntime="MyBatis3">
<commentGenerator>
<property name="suppressAllComments" value="true"/>
</commentGenerator>
<!-- jdbcConnection:指導連線到哪個資料庫 -->
<jdbcConnection
driverClass="com.mysql.jdbc.Driver"
connectionURL="jdbc:mysql:///test"
userId="root"
password="root">
</jdbcConnection>
<javaTypeResolver>
<property name="forceBigDecimals" value="false" />
</javaTypeResolver>
<!--
javaModelGenerator:生成 POJO
targetPackage:生成的 POJO 放在哪個包
targetProject:放在哪個工程下
-->
<javaModelGenerator
targetPackage="cn.edu.nuist.bean"
targetProject=".\src">
<property name="enableSubPackages" value="true" />
<property name="trimStrings" value="true" />
</javaModelGenerator>
<!--sqlMapGenerator:SQL 對映檔案生成器;指定對映檔案生成的地方 -->
<sqlMapGenerator
targetPackage="cn.edu.nuist.mapper"
targetProject=".\conf">
<property name="enableSubPackages" value="true" />
</sqlMapGenerator>
<!-- javaClientGenerator:Mapper<I> 生成的地方 -->
<javaClientGenerator type="XMLMAPPER"
targetPackage="cn.edu.nuist.mapper"
targetProject=".\src">
<property name="enableSubPackages" value="true" />
</javaClientGenerator>
<!--
table:指定要逆向生成哪個資料表
tableName="t_cat":表名
domainObjectName="":這個表對應的物件名
-->
<table tableName="teacher" domainObjectName="Teacher"></table>
<table tableName="emp" domainObjectName="Employee"></table>
<table tableName="dept" domainObjectName="Department"></table>
</context>
</generatorConfiguration>
執行程式碼生成器生成程式碼
public class TestMBG {
public static void main(String[] args) throws Exception {
List<String> warnings = new ArrayList<String>();
boolean overwrite = true;
File configFile = new File("mbg.xml");
ConfigurationParser cp = new ConfigurationParser(warnings);
Configuration config = cp.parseConfiguration(configFile);
DefaultShellCallback callback = new DefaultShellCallback(overwrite);
MyBatisGenerator myBatisGenerator
= new MyBatisGenerator(config, callback, warnings);
// 程式碼生成
myBatisGenerator.generate(null);
System.out.println("生成了!");
}
}