MyBatis 实体映射
Mybatis 配置数据映射主要有 2 种方式,通过 XML 配置文件进行,通过注解进行;
Mybatis 对于实体映射是通过接口调用的方式,在底层上使用 Java 的动态代理实现,不需要提供接口的实现类;
基于 XML 的映射
以下示例完整示例代码地址:
https://gitee.com/assad/mybatis-test-CRUD
代码模块:
site.assad.domain.User (POJO 类)
site.assad.dao.UserDao (Dao 接口)
site.assad.UserDaoTest(UserDao 测试)
mapper/UserMapper.xml (User 实体映射配置文件)
mybatis-config.xml (mybatis 配置文件)
实体类,dao接口 和 映射XML文件的编写
假如要数据表映射的实体类为 site.assad.model.User
public class User implements Serializable{
private int id;
private String name;
private String password;
private Date createDate;
//省略 getter,setter
}
那么编写一个对应的映射配置文件 mapper/UserMapper.xml
<!--设置映射的命名空间-->
<mapper namespace="site.assad.dao.UserDao">
<!--结果映射规则-->
<resultMap id="userMap" type="site.assad.domain.User">
<id property="id" column="user_id" />
<result property="name" column="user_name" />
<result property="password" column="user_password" />
<result property="createDate" column="create_date" jdbcType="DATE" javaType="java.util.Date"/>
</resultMap>
<!--定义接口方法-->
<select id="selectAll" resultMap="userMap">
SELECT user_id,user_name,user_password,create_date FROM users
</select>
</mapper>
<resultMap> 包含以下常用属性:
id:必填,而且唯一,指定该结果集映射规则的标识符;
- type:必填,用于配置该查询列所映射的 Java 实体类类型;
- extends:配置当前 resultMap 继承于其他的 resultMap;
- autoMapping:配置是否启用非映射字段的自动映射功能(即没有在 resultMap 中设置的字段),可选值为 True/ False,该配置可以覆盖全局的 autoMappingBehavior 配置;
<resultMap>包含以下常用标签:
- <constructor>:使用构造方法注入结果,参数如下:
- idArg:id参数;
- arg:注入到构造方法的一个普通结果;
- <id>:注入到 Java 实体类属性的 id 行结果;
- <result>:注入到 Java 实体类属性的普通行结果;
- property:Java 实体类的属性名;
- column:数据库字段名;
- javaType:该 Java 实体类属性的 Java 类型;
- jdbcType:该数据库字段的类型;
- <association>:类型的关联类型,将多个结果包装为该类型;
- <collection>:复杂类型的集合;
- <discrimnator>:根据结果至决定使用哪个结果映射;
- <case>:基于某些值的结果映射;
以上配置文件中定义了一个接口方法 "selectAll",该接口方法的 SQL 执行产生的结果由 “userMap” 结果映射规则进行处理,在 <resultMap> 中可详细地规定数据表字段和Java实体类属性的映射规则;
对于数据库 Date,Timestamp 日期时间 类型的可以在 <result> 节点的 jdbcType,javaType 属性强制指定该结果在数据库和 Java 的实际类型,如上示例;
相关的 dao 接口:site.assad.dao.UserDao 如下:
public interface UserDao {
List<User> getAllUser();
}
在 Mybatis 配置文件中引入实体配置文件
在 mybatis 配置文件中引用
UserMapper.xml 实体映射配置文件:
<configuration>
.....
<mappers>
<mapper resource="mapper/UserMapper.xml" />
</mappers>
</configuration>
如果由多个实体配置文件,可以如下:
<mappers>
<mapper resource="mapper/UserMapper.xml" />
<mapper resource="mapper/gameMapper.xml" />
<mapper resource="mapper/commentMapper.xml" />
</mappers>
或者直接配置包命名空间,即可引入包下所有的映射配置文件:
<mappers>
<package name="mapper" />
</mappers>
调用映射文件中定义的接口方法
以下示例调用 UserMapper 中的 “getAllUser” 方法:
SqlSessionFactory sqlSessionFactory =
new SqlSessionFactoryBuilder().build(Resources.getResourceAsReader("mybatis-config.xml"));
SqlSession sqlSession = sqlSessionFactory.openSession();
//创建 Dao 对象
UserDao userDao = sqlSession.getMapper(UserDao.class);
//调用 Dao 方法
List<User> userList = userDao.getAllUser();
userList.forEach(System.out::println);
sqlSession.close();
CRUD 的 XML 配置
- 对于数据库常用的 CRUD 操作,MyBatis 提供了<select>、<insert>、<update>、<delete> 这些标签分别用于支持 Read,Create,Update,Delete 的数据库基本操作;
- 现在要对 Java 实体类添加一个 CRUD 操作,只需要在该类的 XML 映射文件中增加一个相应的节点,之后在DAO 接口定义该节点的方法 id 即可;
- 对于接口方法入参到映射配置文件的传递,可以在配置文件中使用 EL 表达式作为接口方法入参的占位符;
Java 实体类 User 的映射文件
UserMapper.xml 中添加以下:
.....
<!--演示 select 方法接口定义-->
<select id="getUserById" resultMap="userMap">
SELECT user_id,user_name,user_password,create_date FROM users
WHERE user_id = #{id}
</select>
<!--演示 insert 方法接口定义-->
<insert id="addUser">
INSERT INTO users(user_name,user_password,create_date)
VALUES(#{name},#{password},#{createDate, jdbcType=DATE})
</insert>
<!--演示 update 方法接口定义-->
<update id="updateUserById">
UPDATE users
SET user_name = #{name}, user_password = #{password}
WHERE user_id = #{id}
</update>
<!--演示 delete 方法接口定义-->
<delete id="removeUserById">
DELETE FROM users
WHERE user_id = #{id}
</delete>
....
之后在
site.assad.dao.UserDao 中要添加以下接口方法:
public interface UserDao {
//select 类型方法接口
User getUserById(int id);
//insert 类型方法接口:返回的 int 为 SQL 影响的行数
int addUser(User user);
//update 类型方法接口
int updateUserById(User user);
//delete 类型方法接口
int removeUserById(int id);
}
以下是对于 UserDao 各个接口方法的调用测试代码:
ublic class UserDaoTest {
private UserDao userDao;
public void init() throws IOException {
Reader reader = Resources.getResourceAsReader("mybatis-config.xml");
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);
SqlSession sqlSession = sqlSessionFactory.openSession();
userDao = sqlSession.getMapper(UserDao.class);
reader.close();
}
public void testGetUserById(){
User user = userDao.getUserById(1);
System.out.println(user);
}
public void testAddUser(){
User user = new User();
user.setName("Aaron");
user.setPassword("1234567");
user.setCreateDate(new Date());
int result = userDao.addUser(user);
assertTrue(result > 0 );
}
public void testUpdateUserById(){
User user = userDao.getUserById(48);
user.setName("Linton");
user.setPassword("1111111");
int result = userDao.updateUserById(user);
assertTrue(result > 0);
}
public void testRemoveUserById(){
int result = userDao.removeUserById(48);
assertTrue(result > 0);
}
}
基于 注解的映射
MyBatis 同样支持注解方式进行实体映射的配置,直接将SQL语句写在接口方法上,这种方式优点是简化了映射配置,比较适合对需求比较简单的系统,但是当SQL变化时,需要重新编译代码,一般在大型工程中会更加常用基于XML的配置方式;
以下示例完整示例代码地址:
https://gitee.com/assad/mybatis-test-CRUD
代码模块:
site.assad.domain.User (POJO 类)
site.assad.dao.UserDaoAnno (Dao 接口)
site.assad.UserDaoAnnoTest(UserDao 测试)
mybatis-config.xml (mybatis 配置文件)
使用注解的配置方式不需要编写映射的XML配置文件,在 mybatis 配置文件中需要添加向接口类的定位,如下:
.......
<mappers>
<!--通过注解配置的映射接口-->
<mapper class="site.assad.dao.UserDaoAnno" />
</mappers>
.......
以下是示例代码中的 UserDaoAnno ,即 DAO 接口:
public interface UserDaoAnno {
//相当于 <select> 标签
"SELECT user_id,user_name,user_password,create_date FROM users"}) ({
//相当于 <resultMap> 标签
id = "userAnnoMap", value = { (
property = "id", column = "user_id", id = true), (
property = "name", column = "user_name"), (
property = "password", column = "user_password"), (
property = "createDate", column = "create_date", jdbcType = JdbcType.DATE, javaType = java.util.Date.class), (
})
List<User> getAllUser();
"SELECT user_id,user_name,user_password,create_date FROM users " + ({
"WHERE user_id = #{id}"})
"userAnnoMap") (
User getUserById(int id);
//相当于 <insert> 标签
"INSERT INTO users(user_name,user_password,create_date) " + (
"VALUES(#{name},#{password},#{createDate, jdbcType=DATE})")
"userAnnoMap") (
int addUser(User user);
//相当于 <update> 标签
"UPDATE users " + (
"SET user_name = #{name}, user_password = #{password} " +
"WHERE user_id = #{id}")
"userAnnoMap") (
int updateUserById(User user);
//相当于 <delete> 标签
"DELETE FROM users " + (
"WHERE user_id = #{id}")
"userAnnoMap") (
int removeUserById(int id);
}
调用方式和基于 XML 的配置相同,具体代码见:
site.assad.UserDaoAnnoTest