原文鏈接:http://www.cnblogs.com/xdp-gacl/p/4264301.html http://www.cnblogs.com/xdp-gacl/p/4264425.html
一、優化MyBatis配置文件中的配置
1、連接數據庫的配置單獨放在一個properties文件中
之前,我們是直接將數據庫的連接配置信息寫在了MyBatis的主配置文件conf.xml文件中,如下:
1 <?xml version="1.0" encoding="UTF-8"?> 2 <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd"> 3 <configuration> 4 <environments default="development"> 5 <environment id="development"> 6 <transactionManager type="JDBC" /> 7 <!-- 配置數據庫連接信息 --> 8 <dataSource type="POOLED"> 9 <property name="driver" value="com.mysql.jdbc.Driver" /> 10 <property name="url" value="jdbc:mysql://localhost:3306/mybatis" /> 11 <property name="username" value="root" /> 12 <property name="password" value="XDP" /> 13 </dataSource> 14 </environment> 15 </environments> 16 17 </configuration>
其實我們完全可以將數據庫的連接配置信息寫在一個properties文件中,然后在conf.xml文件中引用properties文件,具體做法如下:
1、在src目錄下新建一個db.properties文件,如下圖所示:
在db.properties文件編寫連接數據庫需要使用到的數據庫驅動,連接URL地址,用戶名,密碼,如下:
1 driver=com.mysql.jdbc.Driver 2 url=jdbc:mysql://localhost:3306/mybatis 3 name=root 4 password=XDP
2、在MyBatis的主配置文件conf.xml文件中引用db.properties文件,如下:
1 <?xml version="1.0" encoding="UTF-8"?> 2 <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd"> 3 <configuration> 4 5 <!-- 引用db.properties配置文件 --> 6 <properties resource="db.properties"/> 7 <!-- 8 development : 開發模式 9 work : 工作模式 10 --> 11 <environments default="development"> 12 <environment id="development"> 13 <transactionManager type="JDBC" /> 14 <!-- 配置數據庫連接信息 --> 15 <dataSource type="POOLED"> 16 <!-- value屬性值引用db.properties配置文件中配置的值 --> 17 <property name="driver" value="${driver}" /> 18 <property name="url" value="${url}" /> 19 <property name="username" value="${name}" /> 20 <property name="password" value="${password}" /> 21 </dataSource> 22 </environment> 23 </environments> 24 25 </configuration>
2、為實體類定義別名,簡化sql映射xml文件中的引用
之前,我們在sql映射xml文件中的引用實體類時,需要寫上實體類的全類名(包名+類名),如下:
<!-- 創建用戶(Create) --> <insert id="addUser" parameterType="me.gacl.domain.User"> insert into users(name,age) values(#{name},#{age}) </insert>
parameterType="me.gacl.domain.User"這里寫的實體類User的全類名me.gacl.domain.User,每次都寫這么一長串內容挺麻煩的,而我們希望能夠簡寫成下面的形式
<insert id="addUser2" parameterType="_User"> insert into users(name,age) values(#{name},#{age}) </insert>
parameterType="_User"這樣寫就簡單多了,為了達到這種效果,我們需要在conf.xml文件中為實體類="me.gacl.domain.User"定義一個別名為"_User",具體做法如下:
在conf.xml文件中<configuration></configuration>標簽中添加如下配置:
<typeAliases> <typeAlias type="me.gacl.domain.User" alias="_User"/> </typeAliases>
這樣就可以為me.gacl.domain.User類定義了一個別名為_User,以后_User就代表了me.gacl.domain.User類,這樣sql映射xml文件中的凡是需要引用me.gacl.domain.User類的地方都可以使用_User來代替,這就達到了一個簡化實體類引用的目的。
除了可以使用<typeAlias type="me.gacl.domain.User" alias="_User"/>這種方式單獨為某一個實體類設置別名之外,我們還可以使用如下的方式批量為某個包下的所有實體類設置別名,如下:
<?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> <!-- 引用db.properties配置文件 --> <properties resource="db.properties"/> <!-- development : 開發模式 work : 工作模式 --> <environments default="development"> <environment id="development"> <transactionManager type="JDBC" /> <!-- 配置數據庫連接信息 --> <dataSource type="POOLED"> <!-- value屬性值引用db.properties配置文件中配置的值 --> <property name="driver" value="${driver}" /> <property name="url" value="${url}" /> <property name="username" value="${name}" /> <property name="password" value="${password}" /> </dataSource> </environment> </environments> <!-- 配置實體類的別名,配置實體類別名的目的是為了在引用實體類時可以使用實體類的別名來代替實體類,達到簡寫的目的 --> <typeAliases> <!-- 為實體類me.gacl.domain.User配置一個別名_User --> <!-- <typeAlias type="me.gacl.domain.User" alias="_User"/> --> <!-- 為me.gacl.domain包下的所有實體類配置別名,MyBatis默認的設置別名的方式就是去除類所在的包后的簡單的類名 比如me.gacl.domain.User這個實體類的別名就會被設置成User --> <package name="me.gacl.domain"/> </typeAliases> </configuration>
<package name="me.gacl.domain"/>就表示為這個包下面的所有實體類設置別名。MyBatis默認的設置別名的方式就是去除類所在的包后的簡單的類名,比如me.gacl.domain.User這個實體類的別名就會被設置成User。
二、解決字段名與實體類屬性名不相同的沖突
在平時的開發中,我們表中的字段名和表對應實體類的屬性名稱不一定都是完全相同的,下面來演示一下這種情況下的如何解決字段名與實體類屬性名不相同的沖突。
1、准備演示需要使用的表和數據
CREATE TABLE orders( order_id INT PRIMARY KEY AUTO_INCREMENT, order_no VARCHAR(20), order_price FLOAT ); INSERT INTO orders(order_no, order_price) VALUES('aaaa', 23); INSERT INTO orders(order_no, order_price) VALUES('bbbb', 33); INSERT INTO orders(order_no, order_price) VALUES('cccc', 22);
2、定義實體類
1 package me.gacl.domain; 2 3 /** 4 * @author gacl 5 * 定義orders表對應的實體類 6 */ 7 public class Order { 8 /** 9 * 10 CREATE TABLE orders( 11 order_id INT PRIMARY KEY AUTO_INCREMENT, 12 order_no VARCHAR(20), 13 order_price FLOAT 14 ); 15 */ 16 17 //Order實體類中屬性名和orders表中的字段名是不一樣的 18 private int id; //id===>order_id 19 private String orderNo; //orderNo===>order_no 20 private float price; //price===>order_price 21 22 public int getId() { 23 return id; 24 } 25 26 public void setId(int id) { 27 this.id = id; 28 } 29 30 public String getOrderNo() { 31 return orderNo; 32 } 33 34 public void setOrderNo(String orderNo) { 35 this.orderNo = orderNo; 36 } 37 38 public float getPrice() { 39 return price; 40 } 41 42 public void setPrice(float price) { 43 this.price = price; 44 } 45 46 @Override 47 public String toString() { 48 return "Order [id=" + id + ", orderNo=" + orderNo + ", price=" + price+ "]"; 49 } 50 }
3、編寫測試代碼
3.1、編寫SQL的xml映射文件
1、創建一個orderMapper.xml文件,orderMapper.xml的內容如下:
1 <?xml version="1.0" encoding="UTF-8" ?> 2 <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> 3 <!-- 為這個mapper指定一個唯一的namespace,namespace的值習慣上設置成包名+sql映射文件名,這樣就能夠保證namespace的值是唯一的 4 例如namespace="me.gacl.mapping.orderMapper"就是me.gacl.mapping(包名)+orderMapper(orderMapper.xml文件去除后綴) 5 --> 6 <mapper namespace="me.gacl.mapping.orderMapper"> 7 8 <!-- 9 根據id查詢得到一個order對象,使用這個查詢是查詢不到我們想要的結果的, 10 這主要是因為實體類的屬性名和數據庫的字段名對應不上的原因,因此無法查詢出對應的記錄 11 --> 12 <select id="getOrderById" parameterType="int" 13 resultType="me.gacl.domain.Order"> 14 select * from orders where order_id=#{id} 15 </select> 16 17 <!-- 18 根據id查詢得到一個order對象,使用這個查詢是可以正常查詢到我們想要的結果的, 19 這是因為我們將查詢的字段名都起一個和實體類屬性名相同的別名,這樣實體類的屬性名和查詢結果中的字段名就可以一一對應上 20 --> 21 <select id="selectOrder" parameterType="int" 22 resultType="me.gacl.domain.Order"> 23 select order_id id, order_no orderNo,order_price price from orders where order_id=#{id} 24 </select> 25 26 <!-- 27 根據id查詢得到一個order對象,使用這個查詢是可以正常查詢到我們想要的結果的, 28 這是因為我們通過<resultMap>映射實體類屬性名和表的字段名一一對應關系 --> 29 <select id="selectOrderResultMap" parameterType="int" resultMap="orderResultMap"> 30 select * from orders where order_id=#{id} 31 </select> 32 <!--通過<resultMap>映射實體類屬性名和表的字段名對應關系 --> 33 <resultMap type="me.gacl.domain.Order" id="orderResultMap"> 34 <!-- 用id屬性來映射主鍵字段 --> 35 <id property="id" column="order_id"/> 36 <!-- 用result屬性來映射非主鍵字段 --> 37 <result property="orderNo" column="order_no"/> 38 <result property="price" column="order_price"/> 39 </resultMap> 40 41 </mapper>
2、在conf.xml文件中注冊orderMapper.xml映射文件
1 <mappers> 2 <!-- 注冊orderMapper.xml文件, 3 orderMapper.xml位於me.gacl.mapping這個包下,所以resource寫成me/gacl/mapping/orderMapper.xml--> 4 <mapper resource="me/gacl/mapping/orderMapper.xml"/> 5 </mappers>
3.2、編寫單元測試代碼
1 package me.gacl.test; 2 3 import me.gacl.domain.Order; 4 import me.gacl.util.MyBatisUtil; 5 import org.apache.ibatis.session.SqlSession; 6 import org.junit.Test; 7 8 public class Test2 { 9 10 @Test 11 public void testGetOrderById(){ 12 SqlSession sqlSession = MyBatisUtil.getSqlSession(); 13 /** 14 * 映射sql的標識字符串, 15 * me.gacl.mapping.orderMapper是orderMapper.xml文件中mapper標簽的namespace屬性的值, 16 * getOrderById是select標簽的id屬性值,通過select標簽的id屬性值就可以找到要執行的SQL 17 */ 18 String statement = "me.gacl.mapping.orderMapper.getOrderById";//映射sql的標識字符串 19 //執行查詢操作,將查詢結果自動封裝成Order對象返回 20 Order order = sqlSession.selectOne(statement,1);//查詢orders表中id為1的記錄 21 //使用SqlSession執行完SQL之后需要關閉SqlSession 22 sqlSession.close(); 23 System.out.println(order);//打印結果:null,也就是沒有查詢出相應的記錄 24 } 25 26 @Test 27 public void testGetOrderById2(){ 28 SqlSession sqlSession = MyBatisUtil.getSqlSession(); 29 /** 30 * 映射sql的標識字符串, 31 * me.gacl.mapping.orderMapper是orderMapper.xml文件中mapper標簽的namespace屬性的值, 32 * selectOrder是select標簽的id屬性值,通過select標簽的id屬性值就可以找到要執行的SQL 33 */ 34 String statement = "me.gacl.mapping.orderMapper.selectOrder";//映射sql的標識字符串 35 //執行查詢操作,將查詢結果自動封裝成Order對象返回 36 Order order = sqlSession.selectOne(statement,1);//查詢orders表中id為1的記錄 37 //使用SqlSession執行完SQL之后需要關閉SqlSession 38 sqlSession.close(); 39 System.out.println(order);//打印結果:Order [id=1, orderNo=aaaa, price=23.0] 40 } 41 42 @Test 43 public void testGetOrderById3(){ 44 SqlSession sqlSession = MyBatisUtil.getSqlSession(); 45 /** 46 * 映射sql的標識字符串, 47 * me.gacl.mapping.orderMapper是orderMapper.xml文件中mapper標簽的namespace屬性的值, 48 * selectOrderResultMap是select標簽的id屬性值,通過select標簽的id屬性值就可以找到要執行的SQL 49 */ 50 String statement = "me.gacl.mapping.orderMapper.selectOrderResultMap";//映射sql的標識字符串 51 //執行查詢操作,將查詢結果自動封裝成Order對象返回 52 Order order = sqlSession.selectOne(statement,1);//查詢orders表中id為1的記錄 53 //使用SqlSession執行完SQL之后需要關閉SqlSession 54 sqlSession.close(); 55 System.out.println(order);//打印結果:Order [id=1, orderNo=aaaa, price=23.0] 56 } 57 }
執行單元測試的結果:
1、testGetOrderById方法執行查詢后返回一個null。
2、testGetOrderById2方法和testGetOrderById3方法執行查詢后可以正常得到想要的結果。
4、總結
上面的測試代碼演示當實體類中的屬性名和表中的字段名不一致時,使用MyBatis進行查詢操作時無法查詢出相應的結果的問題以及針對問題采用的兩種辦法:
解決辦法一: 通過在查詢的sql語句中定義字段名的別名,讓字段名的別名和實體類的屬性名一致,這樣就可以表的字段名和實體類的屬性名一一對應上了,這種方式是通過在sql語句中定義別名來解決字段名和屬性名的映射關系的。
解決辦法二: 通過<resultMap>來映射字段名和實體類屬性名的一一對應關系。這種方式是使用MyBatis提供的解決方式來解決字段名和屬性名的映射關系的。