用过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。