mybatis入门基础(二)----原始dao的开发和mapper代理开发
承接上一篇 mybatis 入门基础 (一)
看过上一篇的朋友,肯定可以看出,里面的 MybatisService 中存在大量的重复代码,看起来不是很清楚,但第一次那样写,是为了解 mybatis 的执行步骤,先苦后甜嘛!
一: 原始 dao 开发方法
概要:1. 在上篇中搭建好的框价中编写 dao 接口和 dao 实现类
2. 向 dao 接口实现类中注入 SqlSessionFactory, 在方法体内通过 SqlSessionFactory 创建 sqlSession.
- DAO 接口类 UserDAO.java
package com.mybatis.dao;
import java.util.List;
import com.mybatis.entity.User;
/**
*
* @ClassName: UserDAO
* @Description: TODO(用户管理 DAO 接口)
* @author warcaft
* @date 2015-6-27 下午 10:23:42
*
*/
public interface UserDAO {
/** 根据 ID 查询用户信息*/
public User findUserById(Integer id);
</span><span style="color: rgba(0, 128, 0, 1)">/**</span><span style="color: rgba(0, 128, 0, 1)">根据用户名称模糊查询用户信息</span><span style="color: rgba(0, 128, 0, 1)">*/</span>
<span style="color: rgba(0, 0, 255, 1)">public</span> List<User><span style="color: rgba(0, 0, 0, 1)"> findUserByName(String username);
</span><span style="color: rgba(0, 128, 0, 1)">/**</span><span style="color: rgba(0, 128, 0, 1)"> 添加用户</span><span style="color: rgba(0, 128, 0, 1)">*/</span>
<span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> insertUser(User user);
</span><span style="color: rgba(0, 128, 0, 1)">/**</span><span style="color: rgba(0, 128, 0, 1)"> 根据ID删除用户</span><span style="color: rgba(0, 128, 0, 1)">*/</span>
<span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> deleteUser(Integer id);
</span><span style="color: rgba(0, 128, 0, 1)">/**</span><span style="color: rgba(0, 128, 0, 1)"> 根据ID更新用户</span><span style="color: rgba(0, 128, 0, 1)">*/</span>
<span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> updateUser(User user);
}
- dao 实现类 UserDaoImpl.java
package com.mybatis.dao;
import java.util.List;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import com.mybatis.entity.User;
/**
*
* @ClassName: UserDaoImpl
* @Description: TODO(用户管理接口的实现类)
* @author warcaft
* @date 2015-6-27 下午 10:29:35
*
*/
public class UserDaoImpl implements UserDAO {
private SqlSessionFactory sqlSessionFactory;
// 需要向 dao 实现类中注入 SqlSessionFactory
// 通过构造方法注入
public UserDaoImpl(SqlSessionFactory sqlSessionFactory) {
this.sqlSessionFactory = sqlSessionFactory;
}
@Override
</span><span style="color: rgba(0, 0, 255, 1)">public</span><span style="color: rgba(0, 0, 0, 1)"> User findUserById(Integer id) {
SqlSession sqlSession </span>=<span style="color: rgba(0, 0, 0, 1)"> sqlSessionFactory.openSession();
User user </span>= sqlSession.selectOne("test.findUserById"<span style="color: rgba(0, 0, 0, 1)">, id);
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 释放资源</span>
sqlSession.close();
return user;
}
@Override
</span><span style="color: rgba(0, 0, 255, 1)">public</span> List<User><span style="color: rgba(0, 0, 0, 1)"> findUserByName(String username) {
SqlSession sqlSession </span>=<span style="color: rgba(0, 0, 0, 1)"> sqlSessionFactory.openSession();
List</span><User> list =<span style="color: rgba(0, 0, 0, 1)"> sqlSession
.selectList(</span>"test.findUserByName"<span style="color: rgba(0, 0, 0, 1)">, username);
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 提交事务</span>
sqlSession.commit();
// 释放资源
sqlSession.close();
return list;
}
@Override
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> insertUser(User user) {
SqlSession sqlSession </span>=<span style="color: rgba(0, 0, 0, 1)"> sqlSessionFactory.openSession();
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 执行插入操作</span>
sqlSession.insert("test.insertUser"<span style="color: rgba(0, 0, 0, 1)">, user);
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 提交事务</span>
sqlSession.commit();
// 释放资源
sqlSession.close();
}
@Override
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> deleteUser(Integer id) {
SqlSession sqlSession </span>=<span style="color: rgba(0, 0, 0, 1)"> sqlSessionFactory.openSession();
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 执行插入操作</span>
sqlSession.delete("test.deleteUser"<span style="color: rgba(0, 0, 0, 1)">, id);
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 提交事务</span>
sqlSession.commit();
// 释放资源
sqlSession.close();
}
@Override
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> updateUser(User user) {
SqlSession sqlSession </span>=<span style="color: rgba(0, 0, 0, 1)"> sqlSessionFactory.openSession();
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 执行插入操作</span>
sqlSession.update("test.updateUser"<span style="color: rgba(0, 0, 0, 1)">, user);
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 提交事务</span>
sqlSession.commit();
// 释放资源
sqlSession.close();
}
}
- JunitTest 测试 UserDaoImplTest.java
package com.mybatis.dao.test;
import java.io.InputStream;
import java.util.Date;
import java.util.List;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.Before;
import org.junit.Test;
import com.mybatis.dao.UserDaoImpl;
import com.mybatis.entity.User;
public class UserDaoImplTest {
</span><span style="color: rgba(0, 0, 255, 1)">private</span><span style="color: rgba(0, 0, 0, 1)"> SqlSessionFactory sqlSessionFactory;
@Before
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span> setUp() <span style="color: rgba(0, 0, 255, 1)">throws</span><span style="color: rgba(0, 0, 0, 1)"> Exception {
String resource </span>= "SqlMapConfig.xml"<span style="color: rgba(0, 0, 0, 1)">;
InputStream inputStream </span>=<span style="color: rgba(0, 0, 0, 1)"> Resources.getResourceAsStream(resource);
sqlSessionFactory </span>= <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> SqlSessionFactoryBuilder().build(inputStream);
}
@Test
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> findUserByIdTest() {
UserDaoImpl userDao </span>= <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> UserDaoImpl(sqlSessionFactory);
User user </span>= userDao.findUserById(1<span style="color: rgba(0, 0, 0, 1)">);
System.out.println(user);
}
@Test
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> findUserByNameTest() {
UserDaoImpl userDao </span>= <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> UserDaoImpl(sqlSessionFactory);
List</span><User> list = userDao.findUserByName("小"<span style="color: rgba(0, 0, 0, 1)">);
System.out.println(list);
}
@Test
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> insertUserTest() {
UserDaoImpl userDao </span>= <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> UserDaoImpl(sqlSessionFactory);
User user </span>= <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> User();
user.setUsername(</span>"张三丰"<span style="color: rgba(0, 0, 0, 1)">);
user.setSex(</span>"1"<span style="color: rgba(0, 0, 0, 1)">);
user.setBirthday(</span><span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> Date());
user.setAddress(</span>"武当山"<span style="color: rgba(0, 0, 0, 1)">);
userDao.insertUser(user);
}
@Test
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> deleteUserTest() {
UserDaoImpl userDao </span>= <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> UserDaoImpl(sqlSessionFactory);
userDao.deleteUser(</span>8<span style="color: rgba(0, 0, 0, 1)">);
}
@Test
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> updateUserTest() {
UserDaoImpl userDao </span>= <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> UserDaoImpl(sqlSessionFactory);
User user </span>= <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> User();
user.setId(</span>1<span style="color: rgba(0, 0, 0, 1)">);
user.setUsername(</span>"王六"<span style="color: rgba(0, 0, 0, 1)">);
user.setSex(</span>"2"<span style="color: rgba(0, 0, 0, 1)">);
user.setAddress(</span>"天津"<span style="color: rgba(0, 0, 0, 1)">);
user.setBirthday(</span><span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> Date());
userDao.updateUser(user);
}
}
才上面的代码可以看出,比起之前那个 MybatisService.java 类里面的内容稍微清晰了点吧。但依然存在以下几个问题:
1.dao 接口中存在大量模版方法,能否把这些代码提出来,减少我们的工作量
2. 调用 sqlSession 方法时将 statement 的 id 硬编码了
3. 调用 sqlSession 传入的变量,由于 sqlSession 方法使用泛型,即使变量类型传入错误,在编译阶段也不报错,不利于程序开发。
所以我们带着这几个问题看看 mapper 代理开发的方法,是否能解决这些问题呢?
二:mapper 代理方法 (只需要 mapper 接口,相当于 dao 接口)
1. 概要:(1). 编写 XXXmapper.xml 的映射文件
(2). 编写 mapper 接口需要遵循一些开发规范,mybatis 可以自动生成 mapper 接口实现类代理对象。
2. 开发规范:
(1). 在 XXXmapper.xml 中 namespace 等于 mapper 接口地址;
(2).XXXmapper.java 接口中的方法和 mapper.xml 中的 statement 的 Id 一致。
(3).mapper.java 接口中的方法输入参数和 mapper.xml 中 statement 的 parameterType 指定的类型一致。
(4).mapper.java 接口中的方法的返回值类型和 mapper.xml 中 statement 的 resultType 指定的类型一致。
小结:以上的开发规范主要是对下面的代码进行统一生成
SqlSession sqlSession = sqlSessionFactory.openSession(); User user = sqlSession.selectOne("test.findUserById", id);
......
3.UserMapper.java 类代码
package com.mybatis.mapper;
import java.util.List;
import com.mybatis.entity.User;
/**
*
- @ClassName: UserDAO
- @Description: TODO(用户管理 mapper 接口)
- @author warcaft
- @date 2015-6-27 下午 10:23:42
/
public interface UserMapper {
/** 根据 ID 查询用户信息 /
public User findUserById(int id);
</span><span style="color: rgba(0, 128, 0, 1)">/**</span><span style="color: rgba(0, 128, 0, 1)"> 根据用户名称模糊查询用户信息 </span><span style="color: rgba(0, 128, 0, 1)">*/</span>
<span style="color: rgba(0, 0, 255, 1)">public</span> List<User><span style="color: rgba(0, 0, 0, 1)"> findUserByName(String username);
</span><span style="color: rgba(0, 128, 0, 1)">/**</span><span style="color: rgba(0, 128, 0, 1)"> 添加用户 </span><span style="color: rgba(0, 128, 0, 1)">*/</span>
<span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> insertUser(User user);
</span><span style="color: rgba(0, 128, 0, 1)">/**</span><span style="color: rgba(0, 128, 0, 1)"> 根据ID删除用户 </span><span style="color: rgba(0, 128, 0, 1)">*/</span>
<span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> deleteUser(Integer id);
</span><span style="color: rgba(0, 128, 0, 1)">/**</span><span style="color: rgba(0, 128, 0, 1)"> 根据ID更新用户 </span><span style="color: rgba(0, 128, 0, 1)">*/</span>
<span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> updateUser(User user);
}
4. 将原来的 User.xml 拷贝修改名称为 UserMapper.xml, 只需修改此行代码即可
<!-- namespace 命名空间, 作用就是对 sql 进行分类化的管理, 理解为 sql 隔离
注意: 使用 mapper 代理开发时,namespace 有特殊作用,namespace 等于 mapper 接口地址
-->
<mapper namespace="com.mybatis.mapper.UserMapper">
5. 在 SqlMapConfig.xml 中加载 UserMapper.xml
<!-- 加载映射文件 -->
<mappers>
<mapper resource="sqlmap/User.xml"/>
<mapper resource="mapper/UserMapper.xml"/>
</mappers>
6.Junit 测试 UserMapperTest.java
package com.mybatis.dao.test;
import java.io.InputStream;
import java.util.Date;
import java.util.List;
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.Before;
import org.junit.Test;
import com.mybatis.entity.User;
import com.mybatis.mapper.UserMapper;
public class UserMapperTest {
</span><span style="color: rgba(0, 0, 255, 1)">private</span><span style="color: rgba(0, 0, 0, 1)"> SqlSessionFactory sqlSessionFactory;
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 此方法是在执行findUserByIdTest之前执行</span>
@Before
public void setUp() throws Exception {
String resource = "SqlMapConfig.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
// 创建 SqlSessionFcatory
sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
}
@Test
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> testFindUserById() {
SqlSession sqlSession </span>=<span style="color: rgba(0, 0, 0, 1)"> sqlSessionFactory.openSession();
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 创建Usermapper对象,mybatis自动生成mapper代理对象</span>
UserMapper mapper = sqlSession.getMapper(UserMapper.<span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)">);
User user </span>= mapper.findUserById(1<span style="color: rgba(0, 0, 0, 1)">);
System.out.println(user);
sqlSession.close();
}
@Test
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> testFindUserByName() {
SqlSession sqlSession </span>=<span style="color: rgba(0, 0, 0, 1)"> sqlSessionFactory.openSession();
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 创建Usermapper对象,mybatis自动生成mapper代理对象</span>
UserMapper mapper = sqlSession.getMapper(UserMapper.<span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)">);
List</span><User> list = mapper.findUserByName("小"<span style="color: rgba(0, 0, 0, 1)">);
System.out.println(list);
sqlSession.close();
}
@Test
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> testDeleteUser() {
SqlSession sqlSession </span>=<span style="color: rgba(0, 0, 0, 1)"> sqlSessionFactory.openSession();
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 创建Usermapper对象,mybatis自动生成mapper代理对象</span>
UserMapper mapper = sqlSession.getMapper(UserMapper.<span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)">);
mapper.deleteUser(</span>6<span style="color: rgba(0, 0, 0, 1)">);
sqlSession.commit();
sqlSession.close();
}
@Test
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> testInsertUser() {
SqlSession sqlSession </span>=<span style="color: rgba(0, 0, 0, 1)"> sqlSessionFactory.openSession();
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 创建Usermapper对象,mybatis自动生成mapper代理对象</span>
User user = <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> User();
user.setUsername(</span>"者别"<span style="color: rgba(0, 0, 0, 1)">);
user.setSex(</span>"1"<span style="color: rgba(0, 0, 0, 1)">);
user.setAddress(</span>"蒙古乞颜部落"<span style="color: rgba(0, 0, 0, 1)">);
user.setBirthday(</span><span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> Date());
UserMapper mapper </span>= sqlSession.getMapper(UserMapper.<span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)">);
mapper.insertUser(user);
sqlSession.commit();
sqlSession.close();
}
@Test
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> testUpdateUser() {
SqlSession sqlSession </span>=<span style="color: rgba(0, 0, 0, 1)"> sqlSessionFactory.openSession();
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 创建Usermapper对象,mybatis自动生成mapper代理对象</span>
User user = <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> User();
user.setId(</span>11);<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">必须设置Id</span>
user.setUsername("神箭手者别"<span style="color: rgba(0, 0, 0, 1)">);
user.setSex(</span>"1"<span style="color: rgba(0, 0, 0, 1)">);
user.setAddress(</span>"蒙古乞颜部落"<span style="color: rgba(0, 0, 0, 1)">);
user.setBirthday(</span><span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> Date());
UserMapper mapper </span>= sqlSession.getMapper(UserMapper.<span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)">);
mapper.updateUser(user);
sqlSession.commit();
sqlSession.close();
}
}
7. 小结
(1). 代理对象内部调用 selectOne()和 selectList(): 如果 mapper 对象返回单个 pojo 对象 (非集合对象) 代理对象内部通过 selectOne 查询数据库,如果 mapper 方法返回集合对象,代理对象内部通过 selectList 查询数据库。
(2).mapper 接口中的方法参数只能有一个是否影响系统开发:
mapper 接口方法参数只能有一个,系统是否不利于维护?
回答:系统框架中,dao 层的代码是被业务层公用的。机试 mapper 接口只有一个参数,可以使用包装类型的 pojo 满足不同的业务方法的需求。