Mybatis开发dao

1      Mybatis开发dao

Mybatis在项目中主要使用的地方就是开发dao(数据访问层),所以下面讲解一下mybatis开发dao的方法。有两种方式:原始dao开发方式mapper代理开发方式(推荐)

1.1  需求

1、  根据用户ID来查询用户信息;

2、  根据用户名称来模糊查询用户信息列表;

3、  添加用户;

1.2  原始dao开发方式

1.2.1  思路

程序员需要写dao接口和dao实现类。

1.2.2  编程步骤

1、  根据需求创建po类

2、  编写全局配置文件

3、  根据需求编写映射文件

4、  加载映射文件

5、  编写dao接口

6、  编写dao实现类

7、  编写测试代码

1.2.3  程序编写

步骤中的1234都在入门程序中进行了编写,此处不需要重新编写。

1.2.3.1       开发dao接口

publicinterface UserDao {

 

    //根据用户ID来查询用户信息

    public User findUserById(int id);

    //根据用户名称来模糊查询用户信息列表

    public List<User> findUsersByName(String username);

    //添加用户

    public void insertUser(User user);

}

1.2.3.2       开发dao实现类

1.2.3.2.1      SqlSession使用范围

通过入门程序,大家可以看出,在测试代码中,有大量的重复代码。所以我们第一反应就是想给它抽取出共性的部分,但是SqlSession、SqlSessionFactory、SqlSessionFactoryBuilder有着各自的生命周期,因为这些生命周期的不同,抽取时要有针对性的处理。

所以在抽取之前,我们先来了解并总结下它们三个的生命周期。

1.2.3.2.1.1 SqlSessionFactoryBuilder

它的作用只是通过配置文件创建SqlSessionFactory,所以只要创建出SqlSessionFactory,它就可以销毁了。所以说,它的生命周期是在方法之内。

1.2.3.2.1.2 SqlSessionFactory

它的作用是创建SqlSession的工厂,工厂一旦创建,除非应用停掉,不要销毁。

所以说它的生命周期是在应用范围内。这里可以通过单例模式来管理它。

在mybatis整合spring之后,最好的处理方式是把SqlSessionFactory交由spring来做单例管理。

1.2.3.2.1.3 SqlSession

SqlSession是一个面向用户(程序员)的接口,它的默认实现是DefaultSqlSession。

Mybatis是通过SqlSession来操作数据库的。SqlSession中不仅包含要处理的SQL信息,还包括一些数据信息,所以说它是线程不安全的,因此它最佳的生命周期范围是在方法体之内。

 

1.2.3.2.2      Dao实现类代码

需要向dao实现类中注入SqlSessionFactory,在方法体内通过SqlSessionFactory创建SqlSession

要注意SqlSession和SqlSessionFactory的生命周期。

publicclass UserDaoImpl implements UserDao {

 

    //注入SqlSessionFactory

    private SqlSessionFactory sqlSessionFactory;

    //使用构造方法来初始化SqlSessionFactory

    public UserDaoImpl(SqlSessionFactory sqlSessionFactory){

       this.sqlSessionFactory = sqlSessionFactory;

    }

   

    @Override

    public User findUserById(int id) {

       //通过工厂,在方法内部获取SqlSession,这样就可以避免线程不安全

       SqlSession sqlSession = sqlSessionFactory.openSession();

       //返回结果集

       return sqlSession.selectOne("test.findUserById", id);

    }

 

    @Override

    public List<User> findUsersByName(String username) {

       //通过工厂,在方法内部获取SqlSession,这样就可以避免线程不安全

       SqlSession sqlSession = sqlSessionFactory.openSession();

       return sqlSession.selectList("test.findUsersByName", username);

    }

 

    @Override

    publicvoid insertUser(User user) {

       //通过工厂,在方法内部获取SqlSession,这样就可以避免线程不安全

       SqlSession sqlSession = sqlSessionFactory.openSession();

       sqlSession.insert("test.insertUser", user);

    }

 

}

1.2.3.3       编写测试代码

publicclass UserDaoTest {

 

    //声明全局的SqlSessionFactory

    private SqlSessionFactory sqlSessionFactory;

   

    @Before

    public void setUp() throws Exception {

       // 1、读取配置文件

       String resource = "SqlMapConfig.xml";

       InputStream inputStream = Resources.getResourceAsStream(resource);

       // 2、根据配置文件创建SqlSessionFactory

       sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);

    }

 

    @Test

    public void testFindUserById() {

       //构造UserDao对象

       UserDao userDao = new UserDaoImpl(sqlSessionFactory);

       //调用UserDao对象的方法

       User user = userDao.findUserById(1);

      

       System.out.println(user);

    }

 

    @Test

    public void testFindUsersByName() {

       //构造UserDao对象

       UserDao userDao = new UserDaoImpl(sqlSessionFactory);

       //调用UserDao对象的方法

       List<User> list = userDao.findUsersByName("小明");

      

       System.out.println(list);

    }

 

    @Test

    publicvoid testInsertUser(){

       //构造UserDao对象

       UserDao userDao = new UserDaoImpl(sqlSessionFactory);

       //构造User对象

       User user = new User();

       user.setUsername("东哥3");

       user.setAddress("清河宝盛西里3");

      

       //调用UserDao对象的方法

       userDao.insertUser(user);

      

       System.out.println(user.getId());

    }

 

}

1.2.4  问题总结

原始dao开发存在一些问题:

Ø  存在一定量的模板代码。比如:通过SqlSessionFactory创建SqlSession;调用SqlSession的方法操作数据库;关闭Sqlsession。

Ø  存在一些硬编码。调用SqlSession的方法操作数据库时,需要指定statement的id,这里存在了硬编码。

1.3  Mapper代理开发方式(推荐)

Mapper代理的开发方式,程序员只需要编写mapper接口(相当于dao接口)即可。Mybatis会自动的为mapper接口生成动态代理实现类。

不过要实现mapper代理的开发方式,需要遵循一些开发规范。

1.3.1  开发规范

1、  mapper接口的全限定名要和mapper映射文件的namespace的值相同。

2、  mapper接口的方法名称要和mapper映射文件中的statement的id相同;

3、  mapper接口的方法参数只能有一个,且类型要和mapper映射文件中statement的parameterType的值保持一致。

4、  mapper接口的返回值类型要和mapper映射文件中statement的resultType值或resultMap中的type值保持一致;

通过规范式的开发mapper接口,可以解决原始dao开发当中存在的问题:

1、  模板代码已经去掉;

2、  剩下去不掉的操作数据库的代码,其实就是一行代码。这行代码中硬编码的部分,通过第一和第二个规范就可以解决。

1.3.2  编程步骤

1、  根据需求创建po类

2、  编写全局配置文件

3、  根据需求编写映射文件

4、  加载映射文件

5、  编写mapper接口

6、  编写测试代码

1.3.3  程序编写

步骤中的12都在入门程序中进行了编写,此处不需要重新编写。

1.3.3.1       编写mapper映射文件

重新定义mapper映射文件UserMapper.xml(内容同Users.xml,除了namespace的值),放到新创建的目录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:此时用mapper代理方式,它的值必须等于对应mapper接口的全限定名  -->

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

 

    <!-- 根据用户ID,查询用户信息 -->

    <!--

       [id]statementid,要求在命名空间内唯一 

       [parameterType]:入参的java类型,可是是简单类型、POJOHashMap

       [resultType]:查询出的单条结果集对应的java类型

       [#{}]表示一个占位符?

       [#{id}]:表示该占位符待接收参数的名称为id。注意:如果参数为简单类型时,#{}里面的参数名称可以是任意定义

     -->

    <select id="findUserById" parameterType="int" resultType="cn.itcast.mybatis.po.User">

       SELECT * FROM USER WHERE id = #{id}

    </select>

   

   

    <!-- 根据用户名称模糊查询用户信息列表 -->

    <!--

       [${}]:表示拼接SQL字符串,即不加解释的原样输出

        [${value}]:表示要拼接的是简单类型参数。

        注意:

       1、如果参数为简单类型时,${}里面的参数名称必须为value

       2${}会引起SQL注入,一般情况下不推荐使用。但是有些场景必须使用${},比如order by ${colname}

    -->

    <select id="findUsersByName" parameterType="java.lang.String" resultType="cn.itcast.mybatis.po.User">

       SELECT * FROM USER WHERE username LIKE '%${value}%'

    </select>

   

    <!-- 添加用户之自增主键返回(selectKey方式) -->

    <!--

       [selectKey标签]:通过select查询来生成主键

       [keyProperty]:指定存放生成主键的属性

       [resultType]:生成主键所对应的Java类型

       [order]:指定该查询主键SQL语句的执行顺序,相对于insert语句,此时选用AFTER

       [last_insert_id]MySQL的函数,要配合insert语句一起使用

     -->

    <insert id="insertUser" parameterType="cn.itcast.mybatis.po.User">

       <selectKey keyProperty="id"resultType="int" order="AFTER">

           SELECT LAST_INSERT_ID()

       </selectKey>

       INSERT INTO USER(username,sex,birthday,address) VALUES(#{username},#{sex},#{birthday},#{address})

    </insert>

   

</mapper>

1.3.3.2       加载mapper映射文件

<!-- 加载mapper -->

<mappers>

    <mapper resource="sqlmap/User.xml"/>

    <mapper resource="mapper/UserMapper.xml"/>

</mappers>

1.3.3.3       编写mapper接口

内容同UserDao接口一样:

public interface UserMapper {

    //根据用户ID来查询用户信息

    public User findUserById(int id);

    //根据用户名称来模糊查询用户信息列表

    public List<User> findUsersByName(String username);

    //添加用户

    public void insertUser(User user);

}

1.3.3.4       编写测试代码

 

public class UserMapperTest {

 

    // 声明全局的SqlSessionFactory

    private SqlSessionFactory sqlSessionFactory;

 

    @Before

    public void setUp() throws Exception {

       // 1、读取配置文件

       String resource = "SqlMapConfig.xml";

       InputStream inputStream = Resources.getResourceAsStream(resource);

       // 2、根据配置文件创建SqlSessionFactory

       sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);

    }

 

    @Test

    public void testFindUserById() {

       // 创建SqlSession

       SqlSession sqlSession = sqlSessionFactory.openSession();

       // 通过SqlSession,获取mapper接口的动态代理对象

       UserMapper userMapper = sqlSession.getMapper(UserMapper.class);

       // 调用mapper对象的方法

       User user = userMapper.findUserById(1);

 

       System.out.println(user);

       // 关闭SqlSession

       sqlSession.close();

 

    }

 

    @Test

    publicvoid testFindUsersByName() {

       // 创建SqlSession

       SqlSession sqlSession = sqlSessionFactory.openSession();

       // 通过SqlSession,获取mapper接口的动态代理对象

       UserMapper userMapper = sqlSession.getMapper(UserMapper.class);

       // 调用mapper对象的方法

       List<User> list = userMapper.findUsersByName("小明");

 

       System.out.println(list);

       // 关闭SqlSession

       sqlSession.close();

    }

 

    @Test

    publicvoid testInsertUser(){

       // 创建SqlSession

       SqlSession sqlSession = sqlSessionFactory.openSession();

       // 通过SqlSession,获取mapper接口的动态代理对象

       UserMapper userMapper = sqlSession.getMapper(UserMapper.class);

      

       //构造User对象

       User user = new User();

       user.setUsername("东哥4");

       user.setAddress("清河宝盛西里4");

      

       // 调用mapper对象的方法

       userMapper.insertUser(user);

 

       System.out.println(user.getId());

      

       //执行SqlSessioncommit操作

       sqlSession.commit();

       // 关闭SqlSession

       sqlSession.close();

    }

 

}

猜你喜欢

转载自blog.csdn.net/cuterabbitbaby/article/details/80578780