您的位置:首页 > 移动开发

mybatis--原始dao和代理Mapper

2016-03-06 09:25 351 查看
上一篇博客我们讲了对于mybatis的增删改,但是我们看上篇的博客,几乎每一个方法都会出现创建工厂,创建会话,关闭绘画,关闭事务等操作。那么今天我们就来封装一下,用接口实现一下mybatis的增删改查。

原始dao

原始的dao,我们需要dao接口和dao的实现类,代码如下:

dao接口

/**
* 用户管理
* @author mengh
*
*/
public interface UserDao {

//根据id查询

public User findUserById(int id) throws Exception;

public void insertUser(User user) throws Exception;

public void deleteUser(int id) throws Exception;
}


dao实现类

public class UserDaoImpl implements UserDao {

//需要向dao实现类注入SqlSessionFactory
//这里通过构造函数注入
private SqlSessionFactory sqlSessionFactory;
public UserDaoImpl(SqlSessionFactory sqlSessionFactory){

this.sqlSessionFactory = sqlSessionFactory;
}

@Override
public User findUserById(int id) throws Exception {
SqlSession sqlSession = sqlSessionFactory.openSession();
User user = sqlSession.selectOne("test.findUserById", id);
sqlSession.close();
return user;

}

@Override
public void insertUser(User user) throws Exception {
SqlSession sqlSession = sqlSessionFactory.openSession();
sqlSession.insert("test.insertUser", user);
sqlSession.commit();
sqlSession.close();
}

@Override
public void deleteUser(int id) throws Exception {
SqlSession sqlSession = sqlSessionFactory.openSession();
sqlSession.delete("test.deleteUser", id);
sqlSession.commit();
sqlSession.close();

}


User.xml

<mapper namespace="test">
<!-- 在映射文件中配置很多的sql -->
<!-- 需求: 通过id,查询数据库的记录 -->
<!-- 通过select执行数据库查询
id:表示映射文件的sql,称为statement的id
将来sql语句会封装到mappedstate的对象中

#{}表示一个占位符
parameterType="" 指定输入的类型,这里指定int
#{id}:其中的id标志输入的参数,参数的名称就是id,如果输入的参数是简单类型,#{}中的参数名称可以是任意类型
resultType="" 置顶输出查询的结果的所映射的java对象,这里select置顶resultType表示将单条记录所映射的java对象

-->
<select id="findUserById" parameterType="int" resultType="cn.itcast.mybatis.po.User">
SELECT * FROM USER WHERE ID=#{id}
</select>

<!-- 根据用户名模糊查询用户信息,可能返回多条记录
resultType:指定的就是单挑记录锁映射的java对象类型
${}表示拼接字符串,将接收的内容,不加任何修饰的凭借到sql中
使用${}凭借sql,会引起sql注入
${}:接受输入的内容,如果传入的是简单类型,${}只能使用value
-->
<select id="findUserByName" parameterType="String" resultType="cn.itcast.mybatis.po.User">
SELECT * FROM USER WHERE USERNAME LIKE '%${value}%'
</select>

<!-- 添加用户
parameterType:指定输入的参数类型(包括用户信息)
#{}中指定pojo的属性名,接受到pojo对象的属性值
mybatis也是通过OGNL来获取属性的值
-->
<insert id="insertUser" parameterType="cn.itcast.mybatis.po.User" >

<!--        select LAST_INSERT_ID() :得到刚刚在insert进去记录的主键值,值适用于自增列 -->
<!--        keyProperty:将查询到的主键值设置到parameterType置顶的对象的哪个属性 -->
<!--        order="AFTER":select LAST_INSERT_ID()执行顺序,相对于insert语句来说它的执行顺序 -->
<!--        resultType:指定结果的类型 -->
<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>

<!-- 删除用户
根据id删除信息
-->
<delete id="deleteUser" parameterType="java.lang.Integer">
delete from user where id=#{id}

</delete>

<!-- 更新用户
需要用户的id和用户信息
#{id}:从传入的user实体中获取对应属性的值
-->
<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>


客户端

@Override
public void deleteUser(int id) throws Exception {
SqlSession sqlSession = sqlSessionFactory.openSession();
sqlSession.delete("test.deleteUser", id);
sqlSession.commit();
sqlSession.close();

}


原声dao缺点

这样我们的做法就写好了,当然这只是传统的做法,虽然比上一篇博客每次都要去实现一下工厂好多了,但是还是有很多的缺点,如下:

1.存在大量的重复代码,可以提取出来,也就是用模板方法。

2.调用sqlSession方法时,将statement硬编码了

3.调用sqlSession方法的时候,由于Session方法使用泛型,即变量类型传入错误,在编译阶段也不报错,不利于发现错误。

Mapper代理

针对上边的不足,mybatis做了一些相应的政策,就是我们说的mapper代理,而且针对mybatis的代理,我们还需要在mapper.xml和接口上加一些规范。

1.在mapper.xml中namespace中编写Mapper接口的地址

<mapper namespace="cn.itcast.mybatis.mapper.UserMapper">


2.mapper.java接口中的方法名称和mapper.xml总的statement的id一直

3.接口中的方法的输入参数类型和mapper.xml中的statement的parameterType的类型一直

4.mapper.java中的返回值的类型和映射文件中的resultType的类型一致

以上开发规范总要对下边的代码统一的

<!-- 改进前 -->
<mapper namespace="cn.itcast.mybatis.mapper.UserMapper">
<!-- 改进后 -->
<mapper namespace="cn.itcast.mybatis.mapper.UserMapper">


改进以后就是我们的mapper.xml,代码如下:

UserMapper.xml

<!-- 命名空间,作用:对sql进行分类话的管理,sql的隔离
注意,如果使用mapper代理开发,他代表mapper接口的地址
-->
<mapper namespace="cn.itcast.mybatis.mapper.UserMapper">

<!-- 在映射文件中配置很多的sql -->
<!-- 需求: 通过id,查询数据库的记录 -->
<!-- 通过select执行数据库查询
id:表示映射文件的sql,称为statement的id
将来sql语句会封装到mappedstate的对象中 -->
<select id="findUserById" parameterType="int" resultType="cn.itcast.mybatis.po.User">
SELECT * FROM USER WHERE ID=#{id}
</select>

<select id="findUserByName" parameterType="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>

<!-- 删除用户
根据id删除信息
-->
<delete id="deleteUser" parameterType="java.lang.Integer">
delete from user where id=#{id}

</delete>

<!-- 更新用户
需要用户的id和用户信息
#{id}:从传入的user实体中获取对应属性的值
-->
<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接口

//根据id查询用户
public User findUserById(int id) throws Exception;

//根据用户名查询用户信息
public List<User> findUserByName(String name) throws Exception;
//
public void insertUser(User user) throws Exception;
//
public void deleteUser(int id) throws Exception;


你以为这样写就完了吗,确实完了,哈哈。而且这样写的好处就是我们不用写实现类,mapper代理会根据我们的statement来选择到底调用什么方法,例如我们的是Insert,那么他就会调用insert。

客户端

@Test
public void test() throws Exception {
SqlSession sqlSession = sqlSessionFactory.openSession();
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
User user = userMapper.findUserById(1);
System.out.println(user);
}


SqlSession

Sqlsession对应着一次数据库会话。由于数据库回话不是永久的,因此Sqlsession的生命周期也不应该是永久的,相反,在你每次访问数据库时都需要创建它(当然并不是说在Sqlsession里只能执行一次sql,你可以执行多次,当一旦关闭了Sqlsession就需要重新创建它)。创建Sqlsession的地方只有一个,那就是SqlsessionFactory的openSession方法。

注意:

这里我们有的方法是查询一个用户,当然也有可能查询出来的是多个用户,没关系,如果我们这个方法查询出来的是多个实体,那么mybaits会自动让让我们的代理类实现selectList()方法,且返回值是List,如果是返回单个实体,则返回User。

小结

针对原始的jdbc和传统的dao的实现,mybaits还是做了非常大的优化的,他让我们真正的面向接口来编程,让我们的代码量减少,让我们的工作能更好的运用在业务上,还真是做到了全心全意为人民服务。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  mybatis