下面来讨论mybatis开发Dao的方法
先来说一下基本架构流程中使用到的几个类
1.SqlSession使用范围
1.1SqlSessionFactoryBuilder
通过SqlSessionFactoryBuilder创建会话工厂SqlSessionFactory
将SqlSessionFactoryBuilder当成一个工具类使用即可,不需要使用单例管理SqlSessionFactoryBuilder。
在需要创建SqlSessionFactory时候,只需要new一次SqlSessionFactoryBuilder即可。
1.2
SqlSessionFactory
通过SqlSessionFactory创建SqlSession,使用单例模式管理sqlSessionFactory(工厂一旦创建,使用一个实例)。
将来mybatis和spring整合后,使用单例模式管理sqlSessionFactory。
1.3SqlSession
SqlSession是一个面向用户(程序员)的接口。
SqlSession中提供了很多操作数据库的方法:如:selectOne(返回单个对象)、selectList(返回单个或多个对象)。
SqlSession是线程不安全的,在SqlSesion实现类中除了有接口中的方法(操作数据库的方法)还有数据域属性。
SqlSession最佳应用场合在方法体内,定义成局部变量使用。
接下来就来说说MyBatis的Dao的写法,分为两种,一种是原始Dao开发方法,一种是mapper代理方法,我们下面一一讨论:
2.原始dao开发方法(程序员需要写dao接口和dao实现类)
2.1思路:程序员需要写dao接口和dao实现类。
需要向dao实现类中注入SqlSessionFactory,在方法体内通过SqlSessionFactory创建SqlSession。
下面实现Dao的场景是基于之前对用户数据进行增删改查的需求。
先建立一个config源包,包里创建一个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命名空间,为了对sql语句进行隔离,方便管理 ,mapper开发dao方式,使用namespace有特殊作用 -->
<mapper namespace="test">
<!-- 在mapper.xml文件中配置很多的sql语句,执行每个sql语句时,封装为MappedStatement对象
mapper.xml以statement为单位管理sql语句
-->
<!-- 根据id查询用户信息 -->
<!--
id:唯一标识 一个statement
#{}:表示 一个占位符,如果#{}中传入简单类型的参数,#{}中的名称随意
parameterType:输入 参数的类型,通过#{}接收parameterType输入 的参数
resultType:输出结果 类型,不管返回是多条还是单条,指定单条记录映射的pojo类型
-->
<select id="findById" parameterType="int" resultType="cn.edu.hpu.mybatis.po.User">
select * from user where id = #{id}
</select>
<!-- 根据用户名称查询用户信息,可能返回多条
${}:表示sql的拼接,通过${}接收参数,将参数的内容不加任何修饰拼接在sql中。
-->
<select id="findByName" parameterType="java.lang.String" resultType="cn.edu.hpu.mybatis.po.User">
select * from user where username like '%${value}%'
</select>
<!-- 添加用户
parameterType:输入 参数的类型,User对象 包括 username,birthday,sex,address
#{}接收pojo数据,可以使用OGNL解析出pojo的属性值
#{username}表示从parameterType中获取pojo的属性值
selectKey:用于进行主键返回,定义了获取主键值的sql
order:设置selectKey中sql执行的顺序,相对于insert语句来说
keyProperty:将主键值设置到哪个属性
resultType:select LAST_INSERT_ID()的结果 类型
-->
<insert id="insertUser" parameterType="cn.edu.hpu.mybatis.po.User">
<selectKey keyProperty="id" order="AFTER" resultType="int">
select LAST_INSERT_ID()
</selectKey>
insert into user(username,sex,birthday,address) values(#{username},#{sex},#{birthday},#{address})
</insert>
<!-- mysql的uuid生成主键 -->
<!-- <insert id="insertUser" parameterType="cn.edu.hpu.mybatis.po.User">
<selectKey keyProperty="id" order="BEFORE" resultType="string">
select uuid()
</selectKey>
INSERT INTO USER(id,username,birthday,sex,address) VALUES(#{id},#{username},#{birthday},#{sex},#{address})
</insert>
-->
<!-- oracle
在执行insert之前执行select 序列.nextval() from dual取出序列最大值,将值设置到user对象 的id属性
-->
<!-- <insert id="insertUser" parameterType="cn.edu.hpu.mybatis.po.User">
<selectKey keyProperty="id" order="BEFORE" resultType="int">
select 序列.nextval() from dual
</selectKey>
INSERT INTO USER(id,username,birthday,sex,address) VALUES(#{id},#{username},#{birthday},#{sex},#{address})
</insert> -->
<!-- 删除 -->
<delete id="deleteUser" parameterType="int">
delete from user where id = #{id}
</delete>
<!-- 更新 -->
<update id="updateUser" parameterType="cn.edu.hpu.mybatis.po.User">
update user set username=#{username},birthday=#{birthday},sex=#{sex},address=#{address} where id = #{id}
</update>
</mapper>
2.2写Dao接口
- package cn.edu.hpu.mybatis.dao;
-
- import cn.edu.hpu.mybatis.PO.User;
-
-
- public interface UserDao {
-
-
- public User findUserById(int id) throws Exception;
-
-
- public void insertUser(User user) throws Exception;
-
-
- public void deleteUser(int id) throws Exception;
-
-
- public void updateUser(User user) throws Exception;
- }
2.3写Dao的实现
- package cn.edu.hpu.mybatis.dao;
-
- import org.apache.ibatis.session.SqlSession;
- import org.apache.ibatis.session.SqlSessionFactory;
-
- import cn.edu.hpu.mybatis.PO.User;
-
- public class UserDaoImpl implements UserDao{
-
-
-
- private SqlSessionFactory sqlSessionFactory;
- public UserDaoImpl(SqlSessionFactory sqlSessionFactory){
- this.sqlSessionFactory=sqlSessionFactory;
- }
-
- @Override
- public void deleteUser(int id) throws Exception {
-
- SqlSession sqlSession=sqlSessionFactory.openSession();
-
-
- sqlSession.delete("test.deleteUser",id);
-
-
- sqlSession.commit();
-
- sqlSession.close();
- }
-
-
- @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 updateUser(User user) throws Exception {
-
- SqlSession sqlSession=sqlSessionFactory.openSession();
-
- sqlSession.update("test.updateUser",user);
-
-
- sqlSession.commit();
-
- sqlSession.close();
-
- }
-
-
- }
测试方法(这里只测试findUserBiId方法):
- package cn.edu.hpu.mybatis.test;
-
- import java.io.InputStream;
-
- 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 cn.edu.hpu.mybatis.PO.User;
- import cn.edu.hpu.mybatis.dao.UserDao;
- import cn.edu.hpu.mybatis.dao.UserDaoImpl;
-
-
- public class UserDaoImplTest {
-
-
- private SqlSessionFactory sqlSessionFactory;
-
-
- @Before
- public void setup() throws Exception{
-
- String resource="SqlMapConfig.xml";
-
-
- InputStream inputStream = Resources.getResourceAsStream(resource);
-
- sqlSessionFactory=new SqlSessionFactoryBuilder().build(inputStream);
- }
-
- @Test
- public void testFindUserById() throws Exception{
-
-
- UserDao userDao=new UserDaoImpl(sqlSessionFactory);
-
-
- User user=userDao.findUserById(1);
-
- System.out.println(user.getUsername());
-
- }
-
- }
测试结果:
张三
输出的日志:
- DEBUG [main] - Logging initialized using 'class org.apache.ibatis.logging.slf4j.Slf4jImpl' adapter.
- DEBUG [main] - PooledDataSource forcefully closed/removed all connections.
- DEBUG [main] - PooledDataSource forcefully closed/removed all connections.
- DEBUG [main] - PooledDataSource forcefully closed/removed all connections.
- DEBUG [main] - PooledDataSource forcefully closed/removed all connections.
- DEBUG [main] - Opening JDBC Connection
- DEBUG [main] - Created connection 28970806.
- DEBUG [main] - Setting autocommit to false on JDBC Connection [com.mysql.jdbc.Connection@1ba0f36]
- DEBUG [main] - ==> Preparing: SELECT * FROM USER WHERE id=?
- DEBUG [main] - ==> Parameters: 1(Integer)
- DEBUG [main] - <== Total: 1
- DEBUG [main] - Resetting autocommit to true on JDBC Connection [com.mysql.jdbc.Connection@1ba0f36]
- DEBUG [main] - Closing JDBC Connection [com.mysql.jdbc.Connection@1ba0f36]
- DEBUG [main] - Returned connection 28970806 to pool.
2.4总结原始 dao开发问题
1、dao接口实现类方法中存在大量模板方法,设想能否将这些代码提取出来,大大减轻程序员的工作量。
2、调用sqlsession方法时将statement的id硬编码了
3、调用sqlsession方法时传入的变量,由于sqlsession方法使用泛型,即使变量类型传入错误,在编译阶段也不报错,不利于程序员开发。
下一篇总结我们来使用mapper代理方法来写Dao,来解决上面我们发现的问题。
源:http://blog.csdn.net/acmman/article/details/46455507