前言 |
mybatis官方推荐使用mapper代理方法开发mapper接口,程序员不用编写mapper接口实现类,使用mapper代理方法时,输入参数可以使用pojo包装对象或map对象,保证dao的通用性;传统的dao层开发容易出现硬编码的问题。下面我们了解一下这两种编码方式:
- 传统DAO层开发: |
User.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">
<!-- 此处namespace无特殊的意义 -->
<mapper namespace="test">
<select id="findUserById" parameterType="int" resultType="cn.itcast.mybatis.po.User">
SELECT * FROM user WHERE id=#{id}
</select>
<select id="findUserByName" parameterType="java.lang.String" resultType="cn.itcast.mybatis.po.User">
select * from user where username like '%${value}%'
</select>
<!-- 添加数据 -->
<insert id="insertUser" parameterType="cn.itcast.mybatis.po.User">
<selectKey keyProperty="id" order="AFTER" resultType="java.lang.Integer">
select LAST_INSERT_ID()
</selectKey>
insert into user(username,birthday,sex,address)value(#{username},#{birthday},#{sex},#{address})
</insert>
<!-- 删除数据 -->
<delete id="deleteUser" parameterType="java.lang.Integer">
delete from user where id=#{id}
</delete>
<!-- 更新数据 -->
<update id="updateUser" parameterType="cn.itcast.mybatis.po.User">
update user set username=#{username},birthday=#{birthday},sex=#{sex},address=#{address} where id=#{id}
</update>
</mapper>
- Dao的接口类:UserDao:
package cn.itcast.mybatis.dao;
import java.security.PublicKey;
import cn.itcast.mybatis.po.User;
/**
*
* @InterfaceName: UserDao
* @Description: TODO(用户管理接口)
* @author 常银玲
* @date 2017年9月26日17:09:36
*
*/
public interface UserDao {
/**
*根据id进行查询
* @param id
* @return
* @throws Exception
*/
public User findUserById(int id)throws Exception;
/**
* 添加用户
* @param user
* @throws Exception
*/
public void insertUser(User user)throws Exception;
/**
* 根据id进行删除
* @param id
* @throws Exception
*/
public void deleteUser(int id) throws Exception;
}
Dao实现类:UserDaoImp1
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 常银玲
* @date 2017年9月26日17:09:36
*
*/
public class UserDaoImpl implements UserDAO {
private SqlSessionFactory sqlSessionFactory;
// 需要向dao实现类中注入SqlSessionFactory
// 通过构造方法注入
public UserDaoImpl(SqlSessionFactory sqlSessionFactory) {
this.sqlSessionFactory = sqlSessionFactory;
}
@Override
public User findUserById(Integer id) {
SqlSession sqlSession = sqlSessionFactory.openSession();
User user = sqlSession.selectOne("test.findUserById", id);
// 释放资源
sqlSession.close();
return user;
}
@Override
public List<User> findUserByName(String username) {
SqlSession sqlSession = sqlSessionFactory.openSession();
List<User> list = sqlSession
.selectList("test.findUserByName", username);
// 提交事务
sqlSession.commit();
// 释放资源
sqlSession.close();
return list;
}
@Override
public void insertUser(User user) {
SqlSession sqlSession = sqlSessionFactory.openSession();
// 执行插入操作
sqlSession.insert("test.insertUser", user);
// 提交事务
sqlSession.commit();
// 释放资源
sqlSession.close();
}
@Override
public void deleteUser(Integer id) {
SqlSession sqlSession = sqlSessionFactory.openSession();
// 执行插入操作
sqlSession.delete("test.deleteUser", id);
// 提交事务
sqlSession.commit();
// 释放资源
sqlSession.close();
}
@Override
public void updateUser(User user) {
SqlSession sqlSession = sqlSessionFactory.openSession();
// 执行插入操作
sqlSession.update("test.updateUser", user);
// 提交事务
sqlSession.commit();
// 释放资源
sqlSession.close();
}
}
- Junit测试:
package cn.itcast.mybatis.dao;
import static org.junit.Assert.*;
import java.io.InputStream;
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 cn.itcast.mybatis.po.User;
/**
*
* @ClassName: UserDaoImp1Test
* @Description: 用户管理接口的测试类
* @author 常银玲
* @date 2017年9月26日17:09:36
*
*/
public class UserDaoImp1Test {
private SqlSessionFactory sqlsessionfactory;
@Before
public void setUp()throws Exception{
String resource="SqlMapConfig.xml";
InputStream inputStream=Resources.getResourceAsStream(resource);
//创建会话工厂
sqlsessionfactory=new SqlSessionFactoryBuilder().build(inputStream);
//SqlSession sqlSession=sqlSessionFactory.openSession();
}
/**
*测试根据id查询的方法;这里只举例一个
*/
@Test
public void testFindUserById() throws Exception {
//创建一个userDao的对象
UserDao userDao=new UserDaoImp1(sqlsessionfactory);
User user=userDao.findUserById(1);
System.out.println(user);
}
}
mybatis传统DAO层开发存在的问题:
1.dao接口中存在大量模版方法,增加工作量。
2.调用sqlSession方法时将statement的id硬编码了
3.调用sqlSession传入的变量,由于sqlSession方法使用泛型,即使变量类型传入错误,在编译阶段也不报错,不利于程序开发。
二:mapper代理开发Mapper接口: |
mapper代理开发和传统开发主要的区别在于
1. 接口不用实现
2. mapper文件的namespace有意义,必须与mapper接口类路径一致。
3. Mapper接口方法名和Mapper.xml中定义的每个statement的id相同
4. mapper接口方法名的输入和输出参数必须和mapper.xml中定义的类型一致。
代码如下:
- 新建UserMapper.xml:关注namespace
<?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有特殊的意义 -->
<mapper namespace="cn.itcast.mybatis.mapper.UserMapper">
<select id="findUserById" parameterType="int" resultType="cn.itcast.mybatis.po.User">
SELECT * FROM user WHERE id=#{id}
</select>
</mapper>
- 配置SqlMapConfig.xml
<mapper resource="mapper/UserMapper.xml"/>
- mapper代理接口:UserMapper.java(关注mapper.xml中方法名,输出和输入参数类型)
```
package cn.itcast.mybatis.dao;
import cn.itcast.mybatis.po.User;
/**
*
* @InterfaceName: UserMapper
* @Description: TODO(用户管理接口)
* @author 常银玲
* @date 2017年9月26日17:09:36
*
*/
public interface UserMapper{
/**
*根据id进行查询
* @param id
* @return
* @throws Exception
*/
public User findUserById(int id)throws Exception;
}
junit测试类:
package cn.itcast.mybatis.mapper;
import static org.junit.Assert.*;
import java.io.IOException;
import java.io.InputStream;
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 cn.itcast.mybatis.po.User;
public class UserMapperTest {
private SqlSessionFactory sqlsessionfactory;
@Before
public void setUp() throws IOException{
String resource="SqlMapConfig.xml";
InputStream inputStream=Resources.getResourceAsStream(resource);
/**
* 创建SqlSessionFcatory
*/
sqlsessionfactory=new SqlSessionFactoryBuilder().build(inputStream);
}
@Test
public void test() {
SqlSession sqlSession=sqlsessionfactory.openSession();
// 创建Usermapper对象,mybatis自动生成mapper代理对象
UserMapper userMapper=sqlSession.getMapper(UserMapper.class);
User user=userMapper.findUserById(1);
System.out.println(user);
}
}
其实学习完mapper代理开发之后,可能你还存在一个疑问,就是返回的结果如果是list,代理内部会怎么判断?
- 代理内部会自动判断,如果返回list那么就调用sqlsession的selectlist方法,如果是对象,就调用sqlsession的selectone方法。
结语: |
mapper代理开发接口不用写实现类,节省了我们的代码量;mapper代理对象减少了我们的硬编码,使编码更加灵活。