1. 背景
在上一篇博客中,介绍执行一个sql 语句,需要创建sqlsession 对象,调用对象相关方法,通过调用相关map.xml 中sql 语句,返回sql 语句中对应的返回类型。
mybatis 在进行Dao 开发时候,有两种方式,第一种原始开发,第二种即使Map 动态代理开发。
2.原始DAO开发
1. 原始DAO 开发:中需要编写Dao接口,和Dao实现类。
DAO 接口: 对数据库的相关操作,如按用户名查明用户。
DAO 实现类:定义sqlsessionFactory.通过生成sqlsession 对象实现接口中相关业务功能,并生成结果对象进行下一步操作。
2. 原始Dao开发中存在以下问题:
1.Dao方法体存在重复代码:通过SqlSessionFactory创建SqlSession,调用SqlSession的数据库操作方法
2.调用sqlSession的数据库操作方法需要指定statement的id,这里存在硬编码,不得于开发维护。
3. Map 动态代理开发
Mapper接口开发方法只需要程序员编写Mapper接口(相当于Dao接口),由Mybatis框架根据接口定义创建接口的动态代理对象,代理对象的方法体同上边Dao接口实现类方法,同时与map.xml sql语句的sqlID 保持一致。另一个优点不需要手动选择sqlsession 中的访问数据的方法。
1.开发规范
Mapper接口开发需要遵循以下规范:
1、Mapper.xml文件中的namespace与mapper接口的类路径相同。
2、Mapper接口方法名和Mapper.xml中定义的每个statement的id相同
3、Mapper接口方法的输入参数类型和mapper.xml中定义的每个sql 的parameterType的类型相同
4、Mapper接口方法的输出参数类型和mapper.xml中定义的每个sql的resultType的类型相同
2.开发实现
1.mapper映射文件UserMapper.xml,将UserMapper.xml放在config下mapper目录下
<?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:命名空间,用于隔离sql -->
<!-- 还有一个很重要的作用,使用动态代理开发DAO,1. namespace必须和Mapper接口类路径一致 -->
<mapper namespace="cn.itcast.mybatis.mapper.UserMapper">
<!-- resultMap最终还是要将结果映射到pojo上,type就是指定映射到哪一个pojo -->
<!-- id:设置ResultMap的id,类似别名,无太大意义 -->
<resultMap type="User" id="orderResultMap">
<!-- 定义主键 ,非常重要。如果是多个字段,则定义多个id -->
<!-- property:主键在pojo中的属性名 -->
<!-- column:主键在数据库中的列名 -->
<id property="id" column="id" />
<result property="userId" column="user_id" />
<result property="number" column="number" />
<result property="createtime" column="createtime" />
<result property="note" column="note" />
</resultMap>
<!-- 根据用户id查询用户 -->
<!-- 2. id必须和Mapper接口方法名一致 -->
<!-- 3. parameterType必须和接口方法参数类型一致 -->
<!-- 4. resultType必须和接口方法返回值类型一致 -->
<!-- 5. resultType可以使用relultmap 中id -->
<select id="queryUserById" parameterType="int"
resultType="orderResultMap">
select * from user where id = #{id}
</select>
<!-- 根据用户名查询用户 -->
<select id="queryUserByUsername" parameterType="string"
resultType="cn.itcast.mybatis.pojo.User">
select * from user where username like '%${value}%'
</select>
<!-- 保存用户 -->
<insert id="saveUser" parameterType="cn.itcast.mybatis.pojo.User">
<selectKey keyProperty="id" keyColumn="id" order="AFTER"
resultType="int">
select last_insert_id()
</selectKey>
insert into user(username,birthday,sex,address) values
(#{username},#{birthday},#{sex},#{address});
</insert>
</mapper>
2.创建UserMapper接口代码如下
public interface UserMapper {
User queryUserById(int id);
List<User> queryUserByUsername(String username);
void saveUser(User user);
}
3.加载UserMapper.xml文件
修改SqlMapConfig.xml文件,添加以下所示的内容
<mappers>
<!--<mapper resource="sqlmap/User.xml" /> -->
<mapper resource="mapper/UserMapper.xml" />
</mappers>
4.编写测试代码
public class UserMapperTest {
private SqlSessionFactory sqlSessionFactory;
@Before
public void init() throws Exception {
// 创建SqlSessionFactoryBuilder
SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
// 加载SqlMapConfig.xml配置文件
InputStream inputStream = Resources.getResourceAsStream("SqlMapConfig.xml");
// 创建SqlsessionFactory 具体实现类为defaultSqlSessionFacotry
this.sqlSessionFactory = sqlSessionFactoryBuilder.build(inputStream);
}
@Test
public void testQueryUserById() {
// 获取sqlSession (defaultSqlSession),和spring整合后由spring管理
SqlSession sqlSession = this.sqlSessionFactory.openSession();
//在bulild时 初始化knownMappers,由addMapper(Class<T> Type) 方法添加到MAP中
//根据传进来的接口Type 得到对应的mapperProxyFactory
//通过mapperProxyFactory.newInstance(sqlSession)获取Mapper接口的代理对象
//newInstance(sqlSession)方法中调用MapperProxy<T>( sqlSession,mapperInterface[即接口class对象],methodCache) 获取代理实例的处理程序
//最后执行动态代理 Proxy.newProxyInstance(mapperInterface.getClassLoader(),new Class[]{mapperInterface},mapperProxy)
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
// 执行查询方法
// 通过执行invoke中cacheMapperMethod(method)方法得到mapperMethod对象,随后mapperMethod调用excute()方法。
User user = userMapper.queryUserById(1);
System.out.println(user);
// 和spring整合后由spring管理
sqlSession.close();
}
@Test
public void testQueryUserByUsername() {
// 获取sqlSession,和spring整合后由spring管理
SqlSession sqlSession = this.sqlSessionFactory.openSession();
// 从sqlSession中获取Mapper接口的代理对象
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
// 执行查询方法
List<User> list = userMapper.queryUserByUsername("张");
for (User user : list) {
System.out.println(user);
}
// 和spring整合后由spring管理
sqlSession.close();
}
@Test
public void testSaveUser() {
// 获取sqlSession,和spring整合后由spring管理
SqlSession sqlSession = this.sqlSessionFactory.openSession();
// 从sqlSession中获取Mapper接口的代理对象
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
// 创建保存对象
User user = new User();
user.setUsername("刘备");
user.setBirthday(new Date());
user.setSex("1");
user.setAddress("蜀国");
// 执行查询方法
userMapper.saveUser(user);
System.out.println(user);
// 和spring整合后由spring管理
sqlSession.commit();
sqlSession.close();
}
}