用過hibernate的小伙伴都知道無論是采用注解還是對象關系映射文件,都會把實體類的屬性和數據表的列聯系起來。比如說Student 就有一個Student.hbm.xml文件,這個對象關系映射文件有id 也有property等標簽。這樣就能很好的做到表和實體關聯。
MyBatis也需要進行表和實體 的關聯。我們查詢的是表,返回的結果是實體類。這之間有一個對應關系。
如果說實體類的屬性和表的列名一一對應,名字一樣,那就自動解決了這個問題。但是如果實體類的屬性和表的列名不一致,這就需要我們手動的把它們關聯起來。
我們查官方文檔,能看到這樣一個配置:是否開啟駝峰命名規則,這個稍后再說。
先創建一個數據表book
create table book( book_id int not null auto_increment COMMENT '書籍ID', book_name varchar(120) not null COMMENT '書籍名稱', primary key(book_id) )ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8 COMMENT '書籍';
insert into book(book_name) values('冰與火之歌');
再創建一個實體類Book,這里我刻意的讓實體類屬性和表的列名不一致
package com.zhao.entity; public class Book { private int id; private String bookName; public int getId() { return id; } public void setId(int id) { this.id = id; } public String getBookName() { return bookName; } public void setBookName(String bookName) { this.bookName = bookName; } @Override public String toString() { return "Book [id=" + id + ", bookName=" + bookName + "]"; } }
現在能看到 表book 列 book_id book_name; 實體類Book 屬性 id bookName。
我依舊采用xml和dao接口組合使用的方法進行數據表操作
package com.zhao.dao; import com.zhao.entity.Book; public interface BookDao { /* * 插入書籍信息 */ public int insertBook(Book book); /* * 根據Id查詢Book信息 */ public Book queryById(int id); }
在接口中我們定義了兩個方法,一個插入 一個查詢。
接下來看BookDao.xml
<?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"> <mapper namespace="com.zhao.dao.BookDao"> <insert id="insertBook" parameterType="Book"> insert into book(book_name) values(#{bookName}) </insert> <select id="queryById" resultType="Book"> select * from book where book_id=#{id} </select> </mapper>
現在進行簡答的測試
package com.zhao.dao; import java.io.IOException; import java.io.Reader; import org.apache.ibatis.io.Resources; import org.apache.ibatis.session.SqlSession; import org.apache.ibatis.session.SqlSessionFactory; import org.apache.ibatis.session.SqlSessionFactoryBuilder; import org.junit.After; import org.junit.Before; import org.junit.Test; import com.zhao.entity.Book; public class BookDaoTest { private String resource = "mybatis-config.xml"; private Reader reader; private SqlSessionFactory sqlSessionFactory; private SqlSession sqlSession; private BookDao bookDao; @Before public void before() throws IOException { reader = Resources.getResourceAsReader(resource); sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader); sqlSession = sqlSessionFactory.openSession(); bookDao=(BookDao)sqlSession.getMapper(BookDao.class); } @After public void after() { sqlSession.close(); } @Test public void testInsertBook() { Book book=new Book(); book.setBookName("冰與火之歌"); int insertCount=bookDao.insertBook(book); //一定要記得提交 事務 sqlSession.commit(); System.out.println("InsertCount: "+insertCount); } @Test public void testQueryById() { Book book=bookDao.queryById(3); System.out.println(book); } }
測試結果
思路特別簡單,就是把從數據表book查到結果賦給Book對象。程序運行沒有報錯,結果不正確只是因為數據表和實體類沒有進行關聯。實際上我們已經從表中查出了數據,只是在賦給Book這一步失敗了。
解決辦法:
1:給數據表的列定義別名
修改BookDao.xml
<select id="queryById" resultType="Book"> select book_id as id, book_name as bookName from book where book_id=#{id} </select>
把剛才的select * 進行了修改,把結果增加了別名。這個別名對應着Book的屬性。
查看結果
2:resultMap手動配置關聯
我們的目的依舊是把表的列和實體類的屬性進行關聯,上面也提到hibernate的對象關系映射,其實mybatis的配置resultMap和hibernate的對象關系映射很相似。
修改BookDao.xml
<select id="queryById" resultMap="BookResultMap"> select * from book where book_id=#{id} </select> <resultMap type="Book" id="BookResultMap"> <id property="id" column="book_id"/> <result property="bookName" column="book_name"/> </resultMap>
只用select * 肯定是失敗的。但是我們可以配置實體類的屬性和數據表的列之間的一一對應關系。
查詢結果
3:用了上面兩種方法,我覺得還是有點繁瑣。有沒有更簡單的方法 ,有。
就用上面提到的是否開啟駝峰規則。
一般情況下,數據庫表的列是以 A_column的格式定義的,而實體類的屬性是以aColumn的格式定義的。就像上面用到的
book_name和bookName。
這兩天我整理的xml和dao層組合使用進行mybatis操作,並沒有使用上面所說的定義別名或者定義resultMap。而是使用了開啟駝峰規則。
在mybatis-config.xml中
<settings> <setting name="mapUnderscoreToCamelCase" value="true" /> <setting name="useGeneratedKeys" value="true" /> </settings>
當然,在設計表和創建實體類的時候,還要注意book_name 和 bookName這種對應關系。
其實,開啟駝峰規則的本質還是給表定義了別名。不過這種別名是有規范的,book_name的別名就說bookName。