MyBatis學習(3) -- 數據庫配置以及屬性名衝突問題

一、連接數據庫的配置單獨放在一個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. </configuration>

  其實我們完全可以將數據庫的連接配置信息寫在一個properties文件中,然後在conf.xml文件中引用properties文件,具體做法如下:

  1、在src目錄下新建一個db.properties文件,如下圖所示:

  

  在db.properties文件編寫連接數據庫需要使用到的數據庫驅動,連接URL地址,用戶名,密碼,如下:

 driver=com.mysql.jdbc.Driver
 url=jdbc:mysql://localhost:3306/mybatis
 name=root
 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. <!-- 引用db.properties配置文件 -->
  5. <properties resource="db.properties"/>
  6. <!--
  7. development : 開發模式
  8. work : 工作模式
  9. -->
  10. <environments default="development">
  11. <environment id="development">
  12. <transactionManager type="JDBC" />
  13. <!-- 配置數據庫連接信息 -->
  14. <dataSource type="POOLED">
  15. <!-- value屬性值引用db.properties配置文件中配置的值 -->
  16. <property name="driver" value="${driver}" />
  17. <property name="url" value="${url}" />
  18. <property name="username" value="${name}" />
  19. <property name="password" value="${password}" />
  20. </dataSource>
  21. </environment>
  22. </environments>
  23. </configuration>

二、爲實體類定義別名,簡化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來代替,這就達到了一個簡化實體類引用的目的。

  除了可以使用<typeAliastype="me.gacl.domain.User" alias="_User"/>這種方式單獨爲某一個實體類設置別名之外,我們還可以使用如下的方式批量爲某個包下的所有實體類設置別名,如下:

  1. <!-- 配置實體類的別名,配置實體類別名的目的是爲了在引用實體類時可以使用實體類的別名來代替實體類,達到簡寫的目的 -->
  2. <typeAliases>
  3. <!-- 爲實體類me.gacl.domain.User配置一個別名_User -->
  4. <!-- <typeAlias type="me.gacl.domain.User" alias="_User"/> -->
  5. <!-- 爲me.gacl.domain包下的所有實體類配置別名,MyBatis默認的設置別名的方式就是去除類所在的包後的簡單的類名
  6. 比如me.gacl.domain.User這個實體類的別名就會被設置成User
  7. -->
  8. <package name="me.gacl.domain"/>
  9. </typeAliases>

  <package name="me.gacl.domain"/>就表示爲這個包下面的所有實體類設置別名。MyBatis默認的設置別名的方式就是去除類所在的包後的簡單的類名,比如me.gacl.domain.User這個實體類的別名就會被設置成User。


在平時的開發中,我們表中的字段名和表對應實體類的屬性名稱不一定都是完全相同的,下面來演示一下這種情況下的如何解決字段名與實體類屬性名不相同的衝突。

一、準備演示需要使用的表和數據

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);

二、定義實體類

  1. package me.gacl.domain;
  2. /**
  3. * @author gacl
  4. * 定義orders表對應的實體類
  5. */
  6. public class Order {
  7. /**
  8. *
  9. CREATE TABLE orders(
  10. order_id INT PRIMARY KEY AUTO_INCREMENT,
  11. order_no VARCHAR(20),
  12. order_price FLOAT
  13. );
  14. */
  15. //Order實體類中屬性名和orders表中的字段名是不一樣的
  16. private int id; //id===>order_id
  17. private String orderNo; //orderNo===>order_no
  18. private float price; //price===>order_price
  19. public int getId() {
  20. return id;
  21. }
  22. public void setId(int id) {
  23. this.id = id;
  24. }
  25. public String getOrderNo() {
  26. return orderNo;
  27. }
  28. public void setOrderNo(String orderNo) {
  29. this.orderNo = orderNo;
  30. }
  31. public float getPrice() {
  32. return price;
  33. }
  34. public void setPrice(float price) {
  35. this.price = price;
  36. }
  37. @Override
  38. public String toString() {
  39. return "Order [id=" + id + ", orderNo=" + orderNo + ", price=" + price+ "]";
  40. }
  41. }

三、編寫測試代碼

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. 根據id查詢得到一個order對象,使用這個查詢是查詢不到我們想要的結果的,
  9. 這主要是因爲實體類的屬性名和數據庫的字段名對應不上的原因,因此無法查詢出對應的記錄
  10. -->
  11. <select id="getOrderById" parameterType="int"
  12. resultType="me.gacl.domain.Order">
  13. select * from orders where order_id=#{id}
  14. </select>
  15. <!--
  16. 根據id查詢得到一個order對象,使用這個查詢是可以正常查詢到我們想要的結果的,
  17. 這是因爲我們將查詢的字段名都起一個和實體類屬性名相同的別名,這樣實體類的屬性名和查詢結果中的字段名就可以一一對應上
  18. -->
  19. <select id="selectOrder" parameterType="int"
  20. resultType="me.gacl.domain.Order">
  21. select order_id id, order_no orderNo,order_price price from orders where order_id=#{id}
  22. </select>
  23. <!--
  24. 根據id查詢得到一個order對象,使用這個查詢是可以正常查詢到我們想要的結果的,
  25. 這是因爲我們通過<resultMap>映射實體類屬性名和表的字段名一一對應關係 -->
  26. <select id="selectOrderResultMap" parameterType="int" resultMap="orderResultMap">
  27. select * from orders where order_id=#{id}
  28. </select>
  29. <!--通過<resultMap>映射實體類屬性名和表的字段名對應關係 -->
  30. <resultMap type="me.gacl.domain.Order" id="orderResultMap">
  31. <!-- 用id屬性來映射主鍵字段 -->
  32. <id property="id" column="order_id"/>
  33. <!-- 用result屬性來映射非主鍵字段 -->
  34. <result property="orderNo" column="order_no"/>
  35. <result property="price" column="order_price"/>
  36. </resultMap>
  37. </mapper>

  2、在conf.xml文件中註冊orderMapper.xml映射文件

<mappers>        
        <!-- 註冊orderMapper.xml文件, 
        orderMapper.xml位於me.gacl.mapping這個包下,所以resource寫成me/gacl/mapping/orderMapper.xml-->
        <mapper resource="me/gacl/mapping/orderMapper.xml"/>
</mappers>

3.2、編寫單元測試代碼

  1. package me.gacl.test;
  2. import me.gacl.domain.Order;
  3. import me.gacl.util.MyBatisUtil;
  4. import org.apache.ibatis.session.SqlSession;
  5. import org.junit.Test;
  6. public class Test2 {
  7. @Test
  8. public void testGetOrderById(){
  9. SqlSession sqlSession = MyBatisUtil.getSqlSession();
  10. /**
  11. * 映射sql的標識字符串,
  12. * me.gacl.mapping.orderMapper是orderMapper.xml文件中mapper標籤的namespace屬性的值,
  13. * getOrderById是select標籤的id屬性值,通過select標籤的id屬性值就可以找到要執行的SQL
  14. */
  15. String statement = "me.gacl.mapping.orderMapper.getOrderById";//映射sql的標識字符串
  16. //執行查詢操作,將查詢結果自動封裝成Order對象返回
  17. Order order = sqlSession.selectOne(statement,1);//查詢orders表中id爲1的記錄
  18. //使用SqlSession執行完SQL之後需要關閉SqlSession
  19. sqlSession.close();
  20. System.out.println(order);//打印結果:null,也就是沒有查詢出相應的記錄
  21. }
  22. @Test
  23. public void testGetOrderById2(){
  24. SqlSession sqlSession = MyBatisUtil.getSqlSession();
  25. /**
  26. * 映射sql的標識字符串,
  27. * me.gacl.mapping.orderMapper是orderMapper.xml文件中mapper標籤的namespace屬性的值,
  28. * selectOrder是select標籤的id屬性值,通過select標籤的id屬性值就可以找到要執行的SQL
  29. */
  30. String statement = "me.gacl.mapping.orderMapper.selectOrder";//映射sql的標識字符串
  31. //執行查詢操作,將查詢結果自動封裝成Order對象返回
  32. Order order = sqlSession.selectOne(statement,1);//查詢orders表中id爲1的記錄
  33. //使用SqlSession執行完SQL之後需要關閉SqlSession
  34. sqlSession.close();
  35. System.out.println(order);//打印結果:Order [id=1, orderNo=aaaa, price=23.0]
  36. }
  37. @Test
  38. public void testGetOrderById3(){
  39. SqlSession sqlSession = MyBatisUtil.getSqlSession();
  40. /**
  41. * 映射sql的標識字符串,
  42. * me.gacl.mapping.orderMapper是orderMapper.xml文件中mapper標籤的namespace屬性的值,
  43. * selectOrderResultMap是select標籤的id屬性值,通過select標籤的id屬性值就可以找到要執行的SQL
  44. */
  45. String statement = "me.gacl.mapping.orderMapper.selectOrderResultMap";//映射sql的標識字符串
  46. //執行查詢操作,將查詢結果自動封裝成Order對象返回
  47. Order order = sqlSession.selectOne(statement,1);//查詢orders表中id爲1的記錄
  48. //使用SqlSession執行完SQL之後需要關閉SqlSession
  49. sqlSession.close();
  50. System.out.println(order);//打印結果:Order [id=1, orderNo=aaaa, price=23.0]
  51. }
  52. }

  執行單元測試的結果:

  1、testGetOrderById方法執行查詢後返回一個null。

  2、testGetOrderById2方法和testGetOrderById3方法執行查詢後可以正常得到想要的結果。

四、總結

  上面的測試代碼演示當實體類中的屬性名和表中的字段名不一致時,使用MyBatis進行查詢操作時無法查詢出相應的結果的問題以及針對問題採用的兩種辦法:

  解決辦法一: 通過在查詢的sql語句中定義字段名的別名,讓字段名的別名和實體類的屬性名一致,這樣就可以表的字段名和實體類的屬性名一一對應上了,這種方式是通過在sql語句中定義別名來解決字段名和屬性名的映射關係的。

  解決辦法二: 通過<resultMap>來映射字段名和實體類屬性名的一一對應關係。這種方式是使用MyBatis提供的解決方式來解決字段名和屬性名的映射關係的。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章