MyBatis是GitHub上一個開源框架,它支持定製化 SQL、存儲過程以及高級映射的優秀的持久層(sql映射)框架。
Mybatis與JdbcTemplate的區別在於,後者是一個工具,只對一些簡單的功能進行了封裝,且是硬編碼在程序中,數據庫層的和java編碼耦合,不利於修改。但前者是sql映射整體解決方案,考慮緩存、考慮異常處理問題、考慮部分字段映射問題等等問題
與Hibernate對比:
Hibernate也是一個與數據庫交互的框架(ORM(Object Relation Mapping:對象關係映射)),它是一個全自動的框架,只需要創建好javaBean對象,其他的事情都交由Hibernate。但同時它不能自己定製sql語句,如果要定製sql,就要學習HQL語言,增加了學習成本。而且全映射框架在只需要查詢一兩個字段,會嚴重影響效率,因爲類中所有的字段都要與表對應。
Mybatis小結
- 1.開發環境配置
- 2.Mybatis全局配置文件細節
- 1)properties 屬性:和spring的context-placeholder一樣,用來引用外部配置文件
- 2)settings 設置:改變MyBatis運行時行爲
- 3)typeAliases 別名處理器:爲Java類型設置一個簡單的別名
- 4)typeHandlers 類型處理器:配置自定義類型處理器,實現 org.apache.ibatis.type.TypeHandler 接口,或繼承一個很便利的類 org.apache.ibatis.type.BaseTypeHandler
- 5)objectFactory 對象工廠
- 6)plugins插件
- 7)environments 環境:將 SQL 映射應用於多種數據庫之中
- 8)databaseIdProvider 數據庫廠商標識
- 9)mappers 映射器:指明sql映射文件的位置
- 3.sql映射文件
- 1)增刪改標籤:insert/delete/update
- 2)select標籤
- 3)cache/cache-ref:和緩存有關
- 4)resultMap標籤:見select標籤自定義封裝規則
- 5)sql標籤:查看動態sql的sql標籤
- 6)databaseId標籤:指定這個CRUD屬於哪個數據庫的
- 7)Dao方法參數的映射總結
- 8)動態sql
- 4.MyBatis緩存機制
- 5.MBG逆向工程
- 6.SSM整合
1.開發環境配置
1)導入包:
mysql-connector-java-5.1.37-bin.jar
mybatis-3.4.1.jar
log4j-1.2.17.jar(在mybatis關鍵的環節就會有日誌打印)
maven配置:
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.5</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.32</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
log4j依賴類路徑下一個log4j.properties配置文件
# Set root category priority to INFO and its only appender to CONSOLE.
#log4j.rootCategory=INFO, CONSOLE debug info warn error fatal
log4j.rootCategory=debug, CONSOLE, LOGFILE
# Set the enterprise logger category to FATAL and its only appender to CONSOLE.
log4j.logger.org.apache.axis.enterprise=FATAL, CONSOLE
# CONSOLE is set to be a ConsoleAppender using a PatternLayout.
log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender
log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout
log4j.appender.CONSOLE.layout.ConversionPattern=%d{ISO8601} %-6r [%15.15t] %-5p %30.30c %x - %m\n
# LOGFILE is set to be a File appender using a PatternLayout.
log4j.appender.LOGFILE=org.apache.log4j.FileAppender
log4j.appender.LOGFILE.File=d:\axis.log
log4j.appender.LOGFILE.Append=true
log4j.appender.LOGFILE.layout=org.apache.log4j.PatternLayout
log4j.appender.LOGFILE.layout.ConversionPattern=%d{ISO8601} %-6r [%15.15t] %-5p %30.30c %x - %m\n
### 2)建立數據庫、Dao接口、JAVABean對象
### 3)mybatis配置文件
#### (1)dao接口的實現文件
<?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">
<!--namespace:名稱空間;寫接口的全類名,相當於告訴MyBatis這個配置文件是實現哪個接口的; -->
<mapper namespace="com.dao.EmployeeDao">
<!-- public Employee getEmpById(Integer id); -->
<!--
select:用來定義一個查詢操作
id:方法名,相當於這個配置是對於某個方法的實現
resultType:指定方法運行後的返回值類型,全類名;(查詢操作必須指定的)
#{屬性名}:代表取出傳遞過來的某個參數的值,如果傳入一個JAVABEAN對象,直接寫對象中的屬性名,不要寫成級聯屬性
-->
<select id="getEmpById" resultType="com.bean.Employee">
select * from t_employee where id=#{id}
</select>
</mapper>
(2)全局配置文件
<?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>
<!-- 配置日誌文件-->
<settings>
<setting name="logImpl" value="LOG4J"/>
</settings>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC" />
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://localhost:3306/mybatis" />
<property name="username" value="root" />
<property name="password" value="123456" />
</dataSource>
</environment>
</environments>
<databaseIdProvider type="DB_VENDOR">
<property name="MySQL" value="mysql"/>
</databaseIdProvider>
<!-- 引入我們自己編寫的每一個接口的實現文件 -->
<mappers>
<!--resource:表示從類路徑下開始找資源 -->
<mapper resource="mybatis/EmployeeDao.xml"/>
</mappers>
</configuration>
4)測試
public void init(){
//1、先創建一個sqlSessionFactory
String resource = "mybatis-config.xml";
SqlSession sqlSession =null;
try {
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
sqlSession = ssf.openSession();
EmployeeDao empDao = sqlSession.getMapper(EmployeeDao.class);
Employee emp = empDao.getUserById(1);
System.out.println(emp);
} catch (IOException e) {
e.printStackTrace();
sqlSession.close();
}
}
兩個細節:1.獲取到的是接口的代理對象,是mybatis自動創建的
2.SqlSessionFactory創建SqlSession對象,Factory只需要創建一次就行,但是每進行一次會話就應該創建一個SqlSession對象
2.Mybatis全局配置文件細節
configuration子標籤:按照順序配置,如果順序錯誤,就會報“The content of element type “configuration” must match “(properties?,settings?,typeAliases?,typeHandlers?,objectFactory?,objectWrapperFactory?,reflectorFactory?,plugins?,environments?,databaseIdProvider?,mappers?)”.”錯誤
1)properties 屬性:和spring的context-placeholder一樣,用來引用外部配置文件
resource:引用類路徑下文件
url:引用磁盤路徑或網絡路徑資源
2)settings 設置:改變MyBatis運行時行爲
例如JAVA命名遵循駝峯命名規則,但是sql不區分大小寫,如果要在sql中列名用大寫,則在前面加一個“_”,例如loginAccount(JAVA)對應login_account(mysql),就要在設置中配置用駝峯命名規則才能查詢到正確結果
<settings>
<setting name="mapUnderscoreToCamelCase" value="true"/>
</settings>
3)typeAliases 別名處理器:爲Java類型設置一個簡單的別名
<typeAliases>
<typeAlias type="com.dao.UserDao" alias="userDao"/>
</typeAliases>
還可以批量取別名(給某個包下所有類取別名,默認就是個這個包下各自的類名):
<typeAliases>
<typeAlias type="com.dao"/>
</typeAliases>
但如果要爲該包下某個類取一個別名而非默認類名,可以在該類上加一個註解@Alias,括號內的就爲該類的別名
不過推薦還是配置爲全類名,方便定位。而且取別名的時候不能佔用系統已有的類型別名,比如date、_byte等
4)typeHandlers 類型處理器:配置自定義類型處理器,實現 org.apache.ibatis.type.TypeHandler 接口,或繼承一個很便利的類 org.apache.ibatis.type.BaseTypeHandler
無論是 MyBatis 在預處理語句(PreparedStatement)中設置一個參數時,還是從結果集中取出一個值時, 都會用類型處理器將獲取的值以合適的方式轉換成 Java 類型。
從 3.4.5 開始,MyBatis 默認支持 JSR-310(日期和時間 API)
5)objectFactory 對象工廠
默認的對象工廠需要做的僅僅是實例化目標類,要麼通過默認無參構造方法,要麼通過存在的參數映射來調用帶有參數的構造方法。 如果想覆蓋對象工廠的默認行爲,可以通過創建自己的對象工廠來實現。但是一般不用。
6)plugins插件
插件是MyBatis提供的一個非常強大的機制,我們可以通過插件來修改MyBatis的一些核心行爲。插件通過動態代理機制,可以介入四大對象的任何一個方法的執行。
- Executor (update, query, flushStatements, commit, rollback, getTransaction, close, isClosed)
- ParameterHandler (getParameterObject, setParameters)
- ResultSetHandler (handleResultSets, handleOutputParameters)
- StatementHandler (prepare, parameterize, batch, update, query)
7)environments 環境:將 SQL 映射應用於多種數據庫之中
在實際開發中,一般有多種數據庫環境,比如開發環境,測試環境要切換數據庫,用default屬性切換默認數據庫。
每個數據庫對應一個 SqlSessionFactory 實例,爲了指定創建哪種環境,只要將它作爲可選的參數傳遞給 SqlSessionFactoryBuilder 即可。
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(reader, environment);
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(reader, environment, properties);
屬性:
1.事務管理器(transactionManager)
在 MyBatis 中有兩種類型的事務管理器(也就是 type="[JDBC|MANAGED]"):
JDBC – 這個配置直接使用了 JDBC 的提交和回滾設施,它依賴從數據源獲得的連接來管理事務作用域。
MANAGED – 這個配置幾乎沒做什麼。它從不提交或回滾一個連接,而是讓容器來管理事務的整個生命週期(比如 JEE應用服務器的上下文)。默認情況下它會關閉連接。
2.數據源(dataSource)
1)UNPOOLED– 這個數據源的實現會每次請求時打開和關閉連接。雖然有點慢,但對那些數據庫連接可用性要求不高的簡單應用程序來說,是一個很好的選擇。 性能表現則依賴於使用的數據庫,對某些數據庫來說,使用連接池並不重要,這個配置就很適合這種情形。
2)POOLED– 這種數據源的實現利用“池”的概念將 JDBC 連接對象組織起來,避免了創建新的連接實例時所必需的初始化和認證時間。 這種處理方式很流行,能使併發 Web 應用快速響應請求。
3)JNDI – 這個數據源實現是爲了能在如 EJB 或應用服務器這類容器中使用,容器可以集中或在外部配置數據源,然後放置一個 JNDI 上下文的數據源引用。
實際開發中,則沒有必要配置事務管理器,因爲 Spring 模塊會使用自帶的管理器來覆蓋前面的配置。
8)databaseIdProvider 數據庫廠商標識
databaseIdProvider 對應的 DB_VENDOR 實現會將 databaseId 設置爲 DatabaseMetaData#getDatabaseProductName() 返回的字符串。由於通常情況下這些字符串都非常長,而且相同產品的不同版本會返回不同的值,可以通過設置屬性別名(value屬性)來使其變短。
<databaseIdProvider type="DB_VENDOR">
<property name="MySQL" value="mysql"/>
<property name="Oracle" value="ora"/>
<property name="SQL Sever" value="sqlserver"/>
</databaseIdProvider>
如果切換數據庫,會分別執行該databaseID下的sql語句,如果能精確匹配就匹配,如果不能匹配就是用默認的(第一個)
<delete id="deleteEmployee" >
DELETE FROM t_employee WHERE id=#{id}
</delete>
<delete id="deleteEmployee" databaseId="mysql">
DELETE FROM t_employee WHERE id=#{id}
</delete>
<delete id="deleteEmployee" databaseId="ora">
DELETE FROM t_employee WHERE id=#{id}
</delete>
9)mappers 映射器:指明sql映射文件的位置
- url:使用完全限定資源定位符(URL)從磁盤或網絡路徑
<mappers>
<mapper url="file:///var/mappers/AuthorMapper.xml"/>
<mapper url="file:///var/mappers/BlogMapper.xml"/>
<mapper url="file:///var/mappers/PostMapper.xml"/>
</mappers>
- resource:使用相對於類路徑的資源引用
<mappers>
<mapper resource="org/mybatis/builder/AuthorMapper.xml"/>
<mapper resource="org/mybatis/builder/BlogMapper.xml"/>
<mapper resource="org/mybatis/builder/PostMapper.xml"/>
</mappers>
- class:使用映射器接口實現類的完全限定類名
注意如果使用類名,則Dao接口文件應和sql映射文件在同一包內,且文件名要保持一致
如:
或直接在Dao接口的方法上註解
public interface UserDao {
@Select("select * from user where id=#{id}")
UserInfo getUserById(Integer id);
}
- 還可以將包內的映射器接口實現全部註冊爲映射器
<mappers>
<package name="org.mybatis.builder"/>
</mappers>
可以在conf文件夾下建一個與接口文件相同的包文件夾,這樣就可以分開放置配置文件和接口類了
3.sql映射文件
映射文件指導着MyBatis如何進行數據庫增刪改查
1)增刪改標籤:insert/delete/update
標籤屬性
id:與方法名相同,所以不能出現方法重載
useGeneratedKeys底層調用的是原生jdbc獲取自增主鍵的方法
keyProperty指明自增的id封裝給哪個屬性
<!-- public int insertEmployee(Employee employee); -->
<insert id="insertEmployee" useGeneratedKeys="true"
keyProperty="id">
INSERT INTO t_employee(empname,gender,email)
VALUES(#{empName},#{gender},#{email})
</insert>
這樣對於插入數據時沒有插入主鍵值主鍵值也會自動自增
@Test
public void test01() {
SqlSession openSession = sqlSessionFactory.openSession();
try {
EmployeeDao employeeDao = openSession.getMapper(EmployeeDao.class);
Employee employee = new Employee(null, "haah", "aaa", 0);
employeeDao.insertEmployee2(employee);
System.out.println(employee.getId());
openSession.commit();
} finally {
openSession.close();
}
}
對於不支持主鍵自增的數據庫,可以直接寫一個子句查詢其主鍵id :,然後進行主鍵自增:在sql插入語句執行前執行查詢最大id,然後將其寫入到id屬性中
<!-- public int insertEmployee2(Employee employee); -->
<insert id="insertEmployee2">
<!--查詢主鍵
order="BEFORE":在覈心sql語句之前先運行一個查詢sql查到id;將查到的id賦值給javaBean的哪個屬性-->
<selectKey order="BEFORE" resultType="integer" keyProperty="id">
select max(id)+1 from t_employee
</selectKey>
INSERT INTO t_employee(id,empname,gender,email)
VALUES(#{id},#{empName},#{gender},#{email})
</insert>
2)select標籤
返回值類型總結
(1)返回List:直接寫List泛型類型
<!-- List<UserInfo> getUserAll();-->
<select id="getUserAll" resultType="com.domain.UserInfo">
select * from user
</select>
(2)返回一條記錄Map:直接寫Map
<!--Map<String,Object> getUserMapById(Integer id);-->
<select id="getUserMapById" resultType="map">
select * from user where id=#{id}
</select>
結果:
{qq=8402349, password=123, address=地球, gender=男, name=zhangsan, id=1, age=18, email=sdfdsf, username=lili}
(3)返回多條記錄Map:用@MapKey指定鍵名,返回類型爲值類型
可以不用主鍵做鍵名,但是要保證該屬性是唯一性
@MapKey("name")
Map<String,UserInfo> getUserMapAll();
<!-- Map<Integer,UserInfo> getUserMapAll();-->
<select id="getUserMapAll" resultType="com.domain.UserInfo">
select * from user
</select>
(4)自定義封裝規則
如果JavaBean的屬性名和數據庫的列名不同,則需要自定義封裝規則,例如在javabean中屬性爲name,age,gender但是在數據庫中列名爲cname,cage,cgender,此時只能取別名或自定義結果集
- 取別名
<select id="getUserById" resultType="com.domain.UserInfo">
select cname name,cgender gender from user where id=#{id}
</select>
- 自定義結果集(ResultMap)
即ResultType使用的Mybatis默認的封裝規則,如果需要自定義封裝規則時,則使用ResultMap定義返回結果
id定義主鍵封裝規則
result定義其他鍵封裝規則
<!-- UserInfo getUserById(Integer id);-->
<select id="getUserById" resultMap="userResMap">
select * from user where id=#{id}
</select>
<resultMap id="userResMap" type="com.domain.UserInfo">
<id property="id" column="cid"/>
<result property="name" column="cname"/>
<result property="gender" column="cgender"/>
<result property="age" column="cage"/>
</resultMap>
- 返回類型中存在屬性也是對象的情況,在數據庫中就是存在外鍵情況
public class Lock {
private Integer id;
private String lockName;
private List<Key> keys;
}
public class Key {
private Integer id;
private String keyName;
private Lock lock;//屬性也是一個對象
}
1.使用級聯屬性
<!-- getKeyById(Integer) -->
<!-- 查詢列:id keyname lockid lid lockName -->
<select id="getKeyById" resultMap="mykey">
select k.id,k.`keyname`,k.`lockid`,
l.`id` lid,l.`lockName` from t_key k
left join t_lock l on k.`lockid`=l.`id`
where k.`id`=#{id}
</select>
<resultMap type="com.bean.Key" id="mykey">
<id property="id" column="id"/>
<result property="keyName" column="keyname"/>
<result property="lock.id" column="lid"/>
<result property="lock.lockName" column="lockName"/>
</resultMap>
2.使用association標籤定義嵌套結果集—聯合查詢(mybatis推薦)
<resultMap type="com.bean.Key" id="mykey">
<id property="id" column="id"/>
<result property="keyName" column="keyname"/>
<!-- 接下來的屬性是一個對象,自定義這個對象的封裝規則;
使用association表示聯合了一個對象 -->
<!-- javaType:指定這個屬性的類型 -->
<association property="lock" javaType="com.bean.Lock">
<!-- 定義lock屬性對應的這個Lock對象如何封裝 -->
<id property="id" column="lid"/>
<result property="lockName" column="lockName"/>
</association>
</resultMap>
3.使用collection標籤定義集合的封裝規則—聯合查詢
<!-- public Lock getLockById(Integer id);
id lockName kid keyname lockid
-->
<select id="getLockById" resultMap="mylock">
select l.*,k.id kid,k.`keyname`,k.`lockid` from t_lock l
left join t_key k on l.`id`=k.`lockid`
where l.id=#{id}
</select>
<resultMap type="com.bean.Lock" id="mylock">
<id property="id" column="id"/>
<result property="lockName" column="lockName"/>
<!--
collection:定義集合元素的封裝
property="":指定哪個屬性是集合屬性
javaType:association中指定對象類型;
ofType="":指定集合裏面元素的類型
-->
<collection property="keys" ofType="com.bean.Key">
<!-- 標籤體中指定集合中這個元素的封裝規則 -->
<id property="id" column="kid"/>
<result property="keyName" column="keyname"/>
<!--可以不定義lock屬性-->
<!--<association property="lock" javaType="com.bean.Lock">-->
<!--<id property="id" column="lid"/>-->
<!--<result property="lockname" column="lockName"/>-->
<!--</association>-->
</collection>
</resultMap>
4.select分步查詢
比如要查詢某個鑰匙可以開哪把鎖,可以先查詢出key對象,再根據key中lockid查詢鎖
association分步查詢:
<!-- public Key getKeyByIdSimple(Integer id); -->
<!--
private Integer id;
private String keyName;
private Lock lock;
-->
<!-- id keyname lockid -->
<select id="getKeyByIdSimple" resultMap="mykey02">
select * from t_key where id=#{id}
</select>
<resultMap type="com.bean.Key" id="mykey02">
<id property="id" column="id"/>
<result property="keyName" column="keyname"/>
<!--告訴mybatis自己去調用一個查詢查鎖子
select="":指定一個查詢sql的唯一標識;mybatis自動調用指定的sql將查出的lock封裝進來
public Lock getLockByIdSimple(Integer id);需要傳入鎖子id
告訴mybatis把哪一列的值傳遞過去
column:指定將哪一列的數據傳遞過去
fetchType:覆蓋全局配置文件的延遲加載屬性
-->
<association property="lock"
select="com.dao.LockDao.getLockByIdSimple"
column="lockid" fetchType="lazy"></association>
</resultMap>
collection分步查詢:
<!-- public Lock getLockByIdByStep(Integer id);
id lockName
1 1號鎖
-->
<select id="getLockByIdByStep" resultMap="mylockstep">
select * from t_lock where id=#{id}
</select>
<!-- collection分步查詢 -->
<resultMap type="com.bean.Lock" id="mylockstep">
<id property="id" column="id"/>
<result property="lockName" column="lockName"/>
<!-- collection指定集合類型的屬性封裝規則 -->
<collection property="keys"
select="com.dao.KeyDao.getKeysByLockId"
column="{id=id}"></collection>
<!-- 在分步查詢的時候,如果有多個列名需要傳入:column={參數key1=列名1,參數key2=列名2....} -->
</resultMap>
這樣mysql會執行兩次sql語句,如果只需要查詢鑰匙的名字,寫這麼多sql查詢會影響效率,所以可以在mybatis的全局配置文件中設置延遲加載。
lazyLoadingEnabled是控制association和collection標籤的對象是否懶加載,而aggressiveLazyLoading是控制擁有懶加載特性的對象是否延遲加載,true表示如果對具有懶加載特性的對象的任意調用會導致這個對象的完整加載,false表示每種屬性按照需要加載。
一般來說簡單查詢和複雜查詢寫成兩個方法比較好
3)cache/cache-ref:和緩存有關
4)resultMap標籤:見select標籤自定義封裝規則
5)sql標籤:查看動態sql的sql標籤
6)databaseId標籤:指定這個CRUD屬於哪個數據庫的
7)Dao方法參數的映射總結
(1)單參數
- 基本類型取值:#{任意名稱}
- POJO對象取值: #{屬性名}
(2)多參數
- 0,1…(參數索引)或者param1,param2…(param序號)
<!-- public Employee getEmpByIdAndEmpName(Integer id,String empName);-->
<select id="getEmployeeByIdAndEmpName" resultType="com.bean.Employee">
select * from t_employee where id = #{param1} and empname = #{param2}
</select>
原理:傳入多參數時,MyBatis會自動的將這些參數封裝到一個map集合中,鍵名爲參數的索引和param序號,所以#{鍵名}就相當於取參數值
- @Param(命名參數)指定參數的名稱(常用)
指定封裝爲Map集合時的鍵名而非用默認鍵名
注意:對於多個參數方法,如果某些參數加了@Param而有些沒有加,則可以混合取值:
(3)傳入Map
直接使用鍵名:#{鍵名}
<!-- public Employee getEmployeeByIdAndEmpName(Map<String, Object> map); -->
<select id="getEmployeeByIdAndEmpName" resultType="com.bean.Employee">
select * from ${tableName} where id=#{id} and empname=#{empName}
</select>
public void test02() {
SqlSession openSession = sqlSessionFactory.openSession();
try {
EmployeeDao employeeDao = openSession.getMapper(EmployeeDao.class);
Map<String, Object> map = new HashMap<String, Object>();
map.put("id", 1);
map.put("empName", "admin");
map.put("tableName", "t_employee");
Employee name = employeeDao.getEmployeeByIdAndEmpName(map);
System.out.println(name);
} finally {
openSession.close();
}
}
(4)傳入參數時,設置參數屬性
#{key}取值的時候可以設置一些屬性,例如:id=#{id,jdbcType=INT}
屬性類型:javaType、jdbcType(常用)、mode、numericScale、resultMap、typeHandler、jdbcTypeName、expression
Tips:1.默認不指定jdbcType,萬一傳入的數據是null,mysql插入null沒問題,Oracle不知道null到底是什麼類型會報錯。所以上面的例子如果id爲integer類型傳入null值,還是需要指定jdbcType。
2.mode 屬性允許指定 IN,OUT 或 INOUT 參數。如果參數爲 OUT 或 INOUT,參數對象屬性的真實值將會被改變,就像在獲取輸出參數時所期望的那樣。
(5)傳入參數有兩種取值方式:#{}和${}
#{屬性名}:是參數預編譯的方式,參數的位置都是用?替代,參數後來都是預編譯設置進去的。不會有sql注入問題,所以安全
${屬性名}:不是參數預編譯,而是直接和sql語句進行拼串,不安全。但是隻有參數位置傳值才能預編譯,所以如果是表名則需用此方式。
8)動態sql
動態 SQL是MyBatis強大特性之一,極大的簡化我們拼裝SQL的操作。動態 SQL 元素和使用 JSTL 或其他類似基於 XML 的文本處理器相似。
MyBatis 採用功能強大的基於 OGNL 的表達式來簡化操作。
OGNL( Object Graph Navigation Language )是一種對象圖導航語言,這是一種強大的
表達式語言,通過它可以非常方便的來操作對象屬性。 類似於我們的EL,SpEL等
在mybatis中,不止傳入的參數可以用來做判斷,額外還有兩個東西可以用來判斷
_parameter:代表傳入來的參數
1)、傳入了單個參數:_parameter就代表這個參數
2)、傳入了多個參數:_parameter就代表多個參數集合起來的map
<if test="_parameter!=null">id=#{id}</if>
_databaseId:代表當前數據庫環境,如果配置了databaseIdProvider:_databaseId就有值
<if test="_databaseId='mysql'">select * from mysqltable</if>
<if test="_databaseId='ora'">select * from oracletable</if>
(1)if
<!-- UserInfo getUserByIf(UserInfo user);-->
<select id="getUserByIf" resultType="com.domain.UserInfo">
select * from user where
<!-- test中傳入的爲判斷條件,爲OGNL表達式,如果寫&或“等,需要轉義-->
<if test="id!=null">id>#{id} and </if>
<if test="name!=null and name !=''">name like #{name} and </if>
<if test="age!=null">age >15 </if>
</select>
@Test
public void test03(){
SqlSession sqlSession=null;
try {
sqlSession = ssf.openSession();
UserDao user = sqlSession.getMapper(UserDao.class);
UserInfo u = new UserInfo();
u.setAge(15);
u.setId(0);
u.setName("%張%");
UserInfo userinfo = user.getUserByIf(u);
System.out.println(userinfo);
}
finally {
sqlSession.close();
}
}
//日誌信息:
Preparing: select * from user where id>? and name like ? and age >15
注意:if標籤不會自動去除裏面的連接詞,所以使用時要小心
添加where標籤:
<select id="getUserByIf" resultType="com.domain.UserInfo">
select * from user
<!-- 在where標籤中必須要返回一個條件,且如果子句以and或or開頭,會自動去除-->
<where>
<if test="id!=null">id>#{id} </if>
<if test="name!=null and name !=''">and name like #{name} </if>
<if test="age!=null">and age > 15</if>
</where>
</select>
@Test
public void test03(){
SqlSession sqlSession=null;
try {
sqlSession = ssf.openSession();
UserDao user = sqlSession.getMapper(UserDao.class);
UserInfo u = new UserInfo();
u.setAge(15);
// u.setId(0);
u.setName("%張%");
UserInfo userinfo = user.getUserByIf(u);
System.out.println(userinfo);
}
finally {
sqlSession.close();
}
}
//日誌打印
Preparing: select * from user WHERE name like ? and age > 15
(2)choose
相當於if/else,當第一個when標籤滿足,後面的都不進入了
當沒有一個when標籤滿足,則進入otherwise
<!-- UserInfo getUserByIf(UserInfo user);-->
<select id="getUserByIf" resultType="com.domain.UserInfo">
select * from user
<where>
<choose>
<when test="id!=null">id=#{id}</when>
<when test="name!=null and name!=''">name=#{name}</when>
<otherwise>age>15</otherwise>
</choose>
</where>
</select>
(3)trim
<!-- UserInfo getUserByIf(UserInfo user);-->
<select id="getUserByIf" resultType="com.domain.UserInfo">
select * from user
<!--prefix:前綴,一般以where作爲前綴,這樣即使後面子句爲空也不會報錯
prefixOverrides:去除前綴多餘字符
suffix:後綴
suffixOverrides:去除後綴多餘字符
-->
<trim prefix="where" prefixOverrides="and" suffixOverrides="and">
<if test="id!=null">id>#{id} and</if>
<if test="name!=null and name !=''"> name like #{name} and</if>
<if test="age!=null"> age > 15 and</if>
</trim>
</select>
(4)foreach
<!--List<UserInfo> getUserByForeach(List<Integer> ids);-->
<select id="getUserByForeach" resultType="com.domain.UserInfo">
select * from user where id in
<!--collection直接寫list,如果想取別名,在方法參數前@Param更換即可
collection="":指定要遍歷的集合的key
close="":以什麼結束
open="":以什麼開始
separator="":每次遍歷的元素的分隔符
index="i":索引
item:就是保存當前遍歷的元素的值;item="變量名":每次遍歷出的元素起一個變量名方便引用
如果遍歷的是一個list;
index:指定的變量保存了當前索引
item:保存當前遍歷的元素的值
如果遍歷的是一個map:
index:指定的變量就是保存了當前遍歷的元素的key
-->
<foreach collection="list" open="(" close=")" separator="," item="id">
#{id}
</foreach>
</select>
(5)set
自動去除多餘逗號
<!--UserInfo updateUserById(UserInfo user);-->
<update id="updateUserById" >
update user
<set>
<if test="age!=null">age=#{age}</if>
<if test="name!=null and name!=''">name = #{name}</if>
</set>
<where>id=#{id}</where>
</update>
(6)bind
將某個變量綁定到固定的表達式中,常用於模糊查詢
<!-- void getUserByIf(UserInfo user);-->
<select id="getUserByIf" resultType="com.domain.UserInfo">
select * from user
<bind name="_name" value="'%'+name+'%'"/>
<where>
<if test="id!=null">id=#{id}</if>
<if test="name!=null and name!=''">and name like #{_name}</if>
<if test="age!=null">and age>15</if>
</where>
</select>
(7)sql/include
抽取可重用sql
<sql id="sql1">select * from user</sql>
<!-- UserInfo getUserByIf(UserInfo user);-->
<select id="getUserByIf" resultType="com.domain.UserInfo">
<include refid="sql1"/>
<bind name="_name" value="'%'+name+'%'"/>
<where>
<if test="id!=null">id=#{id}</if>
<if test="name!=null and name!=''">and name like #{_name}</if>
<if test="age!=null">and age>15</if>
</where>
</select>
4.MyBatis緩存機制
MyBatis 包含一個非常強大的查詢緩存特性,它可以非常方便地配置和定製。緩存可以極大的提升查詢效率。MyBatis系統中默認定義了兩級緩存:一級緩存和二級緩存。
1、默認情況下,只有一級緩存(SqlSession級別的緩存,也稱爲本地緩存)開啓。
2、二級緩存需要手動開啓和配置,他是基於全局級別的緩存。
3、爲了提高擴展性。MyBatis定義了緩存接口Cache。我們可以通過實現Cache接口來自定義二級緩存
1)一級緩存
SqlSesion級別的緩存,默認就一直存在,不用開啓和關閉,也關閉不了。
機制:只要之前查詢過的數據,mybatis就會保存在一個緩存中(Map),下次獲取直接從緩存中拿。
@Test
public void test03(){
SqlSession sqlSession=null;
try {
sqlSession = ssf.openSession();
UserDao user = sqlSession.getMapper(UserDao.class);
UserInfo u = new UserInfo();
u.setName("張");
UserInfo userinfo = user.getUserByIf(u);
UserInfo userinfo1 = user.getUserById(1);
UserInfo userinfo2 = user.getUserByIf(u);
System.out.println(userinfo);
}
finally {
sqlSession.close();
}
}
//日誌打印
com.dao.UserDao.getUserByIf - ==> Preparing: select * from user WHERE name like ?
com.dao.UserDao.getUserByIf - ==> Parameters: %張%(String)
com.dao.UserDao.getUserByIf - <== Total: 1
com.dao.UserDao.getUserById - ==> Preparing: select * from user where id=?
com.dao.UserDao.getUserById - ==> Parameters: 1(Integer)
com.dao.UserDao.getUserById - <== Total: 0
一級緩存失效的幾種情況:
- 1、不同的SqlSession對應不同的一級緩存
- 2、同一個SqlSession但是查詢條件不同
- 3、同一個SqlSession兩次查詢期間執行了任何一次增刪改操作:任何一次增刪改都會清空緩存
- 4、同一個SqlSession兩次查詢期間調用 clearCache()方法手動清空
@Test
public void test03(){
SqlSession sqlSession=null;
try {
sqlSession = ssf.openSession();
UserDao user = sqlSession.getMapper(UserDao.class);
UserInfo u = new UserInfo();
u.setName("張");
UserInfo userinfo = user.getUserByIf(u);
sqlSession.clearCache();
UserInfo userinfo1 = user.getUserById(1);
UserInfo userinfo2 = user.getUserByIf(u);
System.out.println(userinfo);
}
finally {
sqlSession.close();
}
}
//日誌打印
com.dao.UserDao.getUserByIf - ==> Preparing: select * from user WHERE name like ?
com.dao.UserDao.getUserByIf - ==> Parameters: %張%(String)
com.dao.UserDao.getUserByIf - <== Total: 1
com.dao.UserDao.getUserById - ==> Preparing: select * from user where id=?
com.dao.UserDao.getUserById - ==> Parameters: 1(Integer)
com.dao.UserDao.getUserById - <== Total: 0
com.dao.UserDao.getUserByIf - ==> Preparing: select * from user WHERE name like ?
com.dao.UserDao.getUserByIf - ==> Parameters: %張%(String)
com.dao.UserDao.getUserByIf - <== Total: 1
每次查詢操作都會去查找一級緩存中有沒有,每個sqlSession都擁有自己的一級緩存
一級緩存的本質就是一個map,所以在查找緩存的時候,方法只要有任何不一樣,都不會用這個key
2)二級緩存
- 二級緩存默認不開啓,需要手動配置
- MyBatis提供二級緩存的接口以及實現,緩存實現要求POJO實現Serializable接口
- 二級緩存在 SqlSession 關閉或提交之後纔會生效,即一級緩存的數據在 SqlSession 關閉或提交之後會放在二級緩存中,如果sqlSession正在使用,則不會放到二級緩存中
(1)二級緩存的配置
a.全局配置文件中開啓二級緩存
<!-- 開啓全局緩存開關; -->
<setting name="cacheEnabled" value="true"/>
b.需要使用二級緩存的映射文件處使用<cache/>配置緩存
<mapper namespace="com.dao.UserDao">
<cache/>
<!--UserInfo getUserById(Integer id);-->
<select id="getUserById" resultType="com.domain.UserInfo">
select * from user where id=#{id}
</select>
....
注意:使用二級緩存的JavaBean對象必須實現序列化接口,實現即可,裏面並沒有方法
(2)cache標籤屬性
3)執行順序
- 任何時候查詢都會先看二級緩存,如果二級緩存沒有再查詢一級緩存,如果一級緩存沒有則查詢數據庫將查詢結果放入一級緩存中。所以二級緩存和一級緩存同時出現同一查詢結果
- 每一個Dao映射都有自己的一個二級緩存
4)緩存有關設置
- 全局設置二級緩存開關:cacheEnabled
- select標籤局部設置是否使用二級緩存:useCache
- C/R/U/D標籤設置是否清空二級緩存:flushCache。C/U/D默認爲true,select標籤默認爲false
- sqlSession.clearCache():清空一級緩存
5)整合第三方緩存
MyBatis的緩存庫做的不好,所以開放了Cache接口(二級緩存)供第三方整合:
EhCache 是一個純Java的進程內緩存框架,具有快速、精幹等特點,是Hibernate中默認的CacheProvider
使用方法:
1.導包
ehcache-core-2.6.8.jar(ehcache核心包)
mybatis-ehcache-1.0.3.jar(ehcache的整合包,即實現了cache接口的類,可以直接存取ehcache庫)
ehcache要運行還依賴日至包:
slf4j-api-1.7.21.jar
slf4j-log4j12-1.7.21.jar
2.ehcache要工作有一個配置文件,文件名(必須)叫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="D:\44\ehcache" />
<defaultCache
maxElementsInMemory="1"
maxElementsOnDisk="10000000"
eternal="false"
overflowToDisk="true"
timeToIdleSeconds="120"
timeToLiveSeconds="120"
diskExpiryThreadIntervalSeconds="120"
memoryStoreEvictionPolicy="LRU">
</defaultCache>
</ehcache>
<!--
屬性說明:
l diskStore:指定數據在磁盤中的存儲位置。
l defaultCache:當藉助CacheManager.add("demoCache")創建Cache時,EhCache便會採用<defalutCache/>指定的的管理策略
以下屬性是必須的:
l maxElementsInMemory - 在內存中緩存的element的最大數目
l maxElementsOnDisk - 在磁盤上緩存的element的最大數目,若是0表示無窮大
l eternal - 設定緩存的elements是否永遠不過期。如果爲true,則緩存的數據始終有效,如果爲false那麼還要根據timeToIdleSeconds,timeToLiveSeconds判斷
l overflowToDisk - 設定當內存緩存溢出的時候是否將過期的element緩存到磁盤上
以下屬性是可選的:
l timeToIdleSeconds - 當緩存在EhCache中的數據前後兩次訪問的時間超過timeToIdleSeconds的屬性取值時,這些數據便會刪除,默認值是0,也就是可閒置時間無窮大
l timeToLiveSeconds - 緩存element的有效生命期,默認是0.,也就是element存活時間無窮大
diskSpoolBufferSizeMB 這個參數設置DiskStore(磁盤緩存)的緩存區大小.默認是30MB.每個Cache都應該有自己的一個緩衝區.
l diskPersistent - 在VM重啓的時候是否啓用磁盤保存EhCache中的數據,默認是false。
l diskExpiryThreadIntervalSeconds - 磁盤緩存的清理線程運行間隔,默認是120秒。每個120s,相應的線程會進行一次EhCache中數據的清理工作
l memoryStoreEvictionPolicy - 當內存緩存達到最大,有新的element加入的時候, 移除緩存中element的策略。默認是LRU(最近最少使用),可選的有LFU(最不常使用)和FIFO(先進先出)
-->
3.將cache標籤替換,且JavaBean對象不用實現序列化接口了
<!-- 使用mybatis默認二級緩存<cache></cache> -->
<cache type="org.mybatis.caches.ehcache.EhcacheCache"></cache>
4.多個Dao共用同一塊緩存
<!-- 和別的dao共用一塊緩存-->
<cache-ref namespace="com.dao.UserDao"/>
5.MBG逆向工程
MyBatis Generator:代碼生成器,MyBatis官方提供的代碼生成器;幫我們逆向生成Mysql代碼
正向:
數據庫表----javaBean—UserDao—dao.xml
逆向工程:
根據數據表table,逆向分析數據表,自動生成javaBean以及UserDao以及dao.xml
6.SSM整合
1)Eclipse版本
(1)導包
- 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
【測試】
spring-test-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-jsp標準標籤庫】
jstl.jar
standard.jar
【驗證碼】
kaptcha-2.3.2.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【和Spring整合包】
【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
- 數據庫
mysql-connector-java-5.1.37-bin.jar
c3p0-0.9.1.2.jar
(2)配置文件
a.web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0">
<display-name>7.SSM</display-name>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
<!-- 配置Spring容器啓動: -->
<!-- needed for ContextLoaderListener -->
<context-param>
<param-name>contextConfigLocation</param-name>
<!--指定spring配置文件位置 -->
<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的前端控制器 -->
<!-- The front controller of this Spring Web application, responsible for handling all application requests -->
<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>
<!-- 兩個標準配置-->
<!-- 字符編碼 -->
<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>
</web-app>
b.spring.xml
<!-- Spring除過控制器不要,剩下的業務邏輯組件都要,包括dao,包括service -->
<context:component-scan base-package="com.atguigu" >
<!-- 掃描排除不寫use-default-filters="false" -->
<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>
<!--0、導入外部配置文件 -->
<context:property-placeholder location="classpath:dbconfig.properties"/>
<!--1、配數據源 -->
<bean id="ds" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="user" value="${jdbc.user}"></property>
<property name="password" value="${jdbc.password}"></property>
<property name="driverClass" value="${jdbc.driverClass}"></property>
<property name="jdbcUrl" value="${jdbc.jdbcUrl}"></property>
<property name="maxPoolSize" value="${jdbc.maxPoolSize}"></property>
<property name="minPoolSize" value="${jdbc.minPoolSize}"></property>
</bean>
<!--2、配置JdbcTemplate操作數據庫。用mybatis了,pass -->
<!--3、配置使用mybatis操作數據庫 -->
<!-- 可以根據配置文件得到sqlSessionFactory -->
<bean id="sqlSessionFactoryBean" class="org.mybatis.spring.SqlSessionFactoryBean">
<!-- 指定全局配置文件位置 -->
<property name="configLocation" value="classpath:mybatis/mybatis-config.xml"></property>
<property name="dataSource" ref="ds"></property>
<!-- 指定xml映射文件的位置 -->
<property name="mapperLocations" value="classpath:mybatis/mapper/*.xml"></property>
</bean>
<!-- 我們要把每一個dao接口的實現加入到ioc容器,不僅僅是加了這些接口進入容器 -->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<!-- 指定dao接口所在的包 -->
<property name="basePackage" value="com.atguigu.dao"></property>
</bean>
<!-- 上面的MapperScannerConfigurerbean等效於 <mybatis-spring:scan base-package="com.atguigu.dao"/> -->
<!--4、配置事務控制;配置事務管理器,讓他控制住數據源裏面的鏈接的關閉和提交 -->
<bean id="tm" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="ds"></property>
</bean>
<!--5、基於xml配置,配置事務;哪些方法切入事務還要寫切入點表達式 -->
<aop:config>
<!--配置切入點表達式 -->
<aop:pointcut expression="execution(* com.atguigu.service.*.*(..))" id="txPoint"/>
<aop:advisor advice-ref="myTx" pointcut-ref="txPoint"/>
</aop:config>
<!--6、配置事務增強、事務屬性、事務建議
transaction-manager="tm":指定要配置的事務管理器的id
-->
<tx:advice id="myTx" transaction-manager="tm">
<!-- 配置事務屬性 -->
<tx:attributes>
<tx:method name="*" rollback-for="java.lang.Exception"/>
<tx:method name="get*" read-only="true"/>
<!-- <tx:method name="insertEmp" isolation="READ_UNCOMMITTED"/> -->
</tx:attributes>
</tx:advice>
c.springmvc.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd">
<!-- SpringMVC只掃描控制器;禁用默認的規則 -->
<context:component-scan base-package="com.atguigu" 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>
d.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>
<settings>
<setting name="lazyLoadingEnabled" value="true"/>
<setting name="aggressiveLazyLoading" value="false"/>
<setting name="cacheEnabled" value="true"/>
</settings>
</configuration>
2)maven依賴
<properties>
<spring.version>5.0.2.RELEASE</spring.version>
<slf4j.version>1.6.6</slf4j.version>
<log4j.version>1.2.12</log4j.version>
<shiro.version>1.2.3</shiro.version>
<mysql.version>5.1.6</mysql.version>
<mybatis.version>3.4.5</mybatis.version>
</properties>
<dependencies>
<!-- spring -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.6.8</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-orm</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>${mysql.version}</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.5.2</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.5.2</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>jsp-api</artifactId>
<version>2.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>jstl</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
<!-- log start -->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>${log4j.version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>${slf4j.version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>${slf4j.version}</version>
</dependency>
<!-- log end -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>${mybatis.version}</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>1.3.0</version>
</dependency>
<dependency>
<groupId>c3p0</groupId>
<artifactId>c3p0</artifactId>
<version>0.9.1.2</version>
<type>jar</type>
<scope>compile</scope>
</dependency>
</dependencies>