Mybatis(四)

版权声明:转载请注明出处! https://blog.csdn.net/CC1014524900/article/details/82559647

Dao开发方法

使用Mybatis开发Dao,通常有两个方法,即原始Dao开发方法和Mapper接口开发方法。

先介绍几个概念

a、SqlSession的使用范围

   SqlSession中封装了对数据库的操作,如:查询、插入、更新、删除等。
   通过SqlSessionFactory创建SqlSession,而SqlSessionFactory是通过SqlSessionFactoryBuilder进行创建

b、SqlSessionFactoryBuilder

   SqlSessionFactoryBuilder用于创建SqlSessionFacoty,SqlSessionFacoty一旦创建完成就不  
   需要SqlSessionFactoryBuilder了,因为SqlSession是通过SqlSessionFactory生产,所以可  
   以将SqlSessionFactoryBuilder当成一个工具类使用,最佳使用范围是方法范围即方法体内局部变量。

c、SqlSessionFactory

   SqlSessionFactory是一个接口,接口中定义了openSession的不同重载方法,SqlSessionFactory  
   的最佳使用范围是整个应用运行期间,一旦创建后可以重复使用,通常以单例模式管理SqlSessionFactory。

d、SqlSession

    SqlSession是一个面向用户的接口, sqlSession中定义了数据库操作方法。每个线程都应该有它自己的  
    SqlSession实例。SqlSession的实例不能共享使用,它也是线程不安全的。因此最佳的范围是请求或方法  
    范围。绝对不能将SqlSession实例的引用放在一个类的静态字段或实例字段中。打开一个 SqlSession,  
    使用完毕就要关闭它。通常把这个关闭操作放到 finally 块中以确保每次都能执行关闭

1、原始Dao开发方式:原始Dao开发方法需要程序员编写Dao接口和Dao实现类。

 需求:根据用户id查询一个用户信息
      根据用户名称模糊查询用户信息列表
      添加用户信息

Dao接口和实现

    接口
        public interface UserDao {

            User getUserById(int id);
            List<User> getUserByUsername(String username);
            void insertUser(User user);
        }

    实现
        public class UserDaoImpl implements UserDao {

            //注入SqlSessionFactory
            private SqlSessionFactory sqlSessionFactory;

            public UserDaoImpl(SqlSessionFactory sqlSessionFactory) {
                this.sqlSessionFactory = sqlSessionFactory;
            }

            @Override
            public User getUserById(int id) {
                SqlSession sqlSession = sqlSessionFactory.openSession();
                // 根据id查询用户信息
                User user = sqlSession.selectOne("getUserById", id);
                // 关闭SQLSession
                sqlSession.close();
                return user;
            }

            @Override
            public List<User> getUserByUsername(String username) {
                // 创建一个SQLSession对象
                SqlSession sqlSession = sqlSessionFactory.openSession();
                // 执行查询
                List<User> list = sqlSession.selectList("getUserByUsername", username);
                // 释放资源
                sqlSession.close();
                return list;
            }

            @Override
            public void insertUser(User user) {
                // 创建一个SQLSession对象
                SqlSession sqlSession = sqlSessionFactory.openSession();
                // 插入用户
                sqlSession.insert("insertUser", user);
                // 提交事务
                sqlSession.commit();
                // 释放资源
                sqlSession.close();
            }

    测试
        public class UserDaoImplTest {

            //创建会话工厂
            private SqlSessionFactory sqlSessionFactory = null;

            @Before
            public void createSqlSessionFactory() throws Exception {
                //第一步:创建一个SQLSessionFactoryBuilder对象。
                SqlSessionFactoryBuilder sessionFactoryBuilder=new SqlSessionFactoryBuilder();
                //第二步:加载配置文件。
                InputStream inputStream = Resources.getResourceAsStream("SqlMapConfig.xml");
                //第三步:创建SQLSessionFactory对象
                sqlSessionFactory = sessionFactoryBuilder.build(inputStream);
            }


            @Test   //根据用户id获取用户
            public void getUserByIdTest() {
                UserDao userDao = new UserDaoImpl(sqlSessionFactory);
                User user = userDao.getUserById(10);
                System.out.println(user);
            }

            @Test   //通过用户名查询用户
            public void findUserByUsernameTest() {
                UserDao userDao = new UserDaoImpl(sqlSessionFactory);
                List<User> list = userDao.getUserByUsername("张");
                for (User user : list) {
                    System.out.println(user);
                }
            }

            @Test
            public void insertUserTest() {
                UserDao userDao = new UserDaoImpl(sqlSessionFactory);
                User user = new User();
                user.setUsername("赵云");
                user.setAddress("正定");
                user.setBirthday(new Date());
                user.setSex("1");
                userDao.insertUser(user);
            }
      }

原始Dao开发中存在以下问题:

Dao方法体存在重复代码:通过SqlSessionFactory创建SqlSession,调用SqlSession的数据库操作  
方法调用sqlSession的数据库操作方法需要指定statement的id,这里存在硬编码,不得于开发维护。

2、Mapper动态代理方式

Mapper接口开发方法只需要程序员编写Mapper接口(相当于Dao接口),由Mybatis框架根据接口定义  
创建接口的动态代理对象,代理对象的方法体同上边Dao接口实现类方法。
    Mapper接口开发需要遵循以下规范:
    a、Mapper.xml文件中的namespace与mapper接口的类路径相同。
    b、Mapper接口方法名和Mapper.xml中定义的每个statement的id相同 
    c、Mapper接口方法的输入参数类型和mapper.xml中定义的每个sql 的parameterType的类型相同
    d、Mapper接口方法的输出参数类型和mapper.xml中定义的每个sql的resultType的类型相同

创建包 com.kid.mybatis.mapper

        a、接口:UserMapper
            public interface UserMapper {
                User getUserById(int id);
                List<User> getUserByUsername(String username);
                void insertUser(User user);
            }

        b、映射文件:UserMapper.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语句的隔离,
                 #{}作用就是占位符,相当于jdbc的“?”
                 parameterType:查询的参数类型
                    定义输入到sql中的映射类型,#{id}表示使用preparedstatement设置占位符号并将输入变量id传到sql。
                 resultType:查询结果的数据类型,如果是pojo应该给全路径。
            -->
            <!-- mapper代理的开发规则:
                    1、namespace必须时候接口的全限定名
                    2、Statementid必须和接口的方法名称一致
                    3、接口方法的参数类型要和parameterType要一致
                    4、接口方法的返回值类型要和resultType一致
             --> 
            <mapper namespace="com.kid.mybatis.mapper.UserMapper">
                <!-- 通过用户id获取用户 -->
                <select id="getUserById" parameterType="int" resultType="user">
                    select * from user where id = #{id}
                </select>

                <!-- 如果查询结果返回list, resultType设置为list中一个元素的数据类型
                    ${}字符串拼接指令
                -->
                <select id="getUserByUsername" parameterType="string" resultType="user">
                    <!-- ${value}表示使用参数将${value}替换,做字符串的拼接。
                          注意:如果是取简单数量类型的参数,括号中的值必须为value
                     -->
                    select * from user where username like '%${value}%'
                </select>

                <!-- 参数时候pojo时,#{}中的名称就是pojo的属性 -->
                <insert id="insertUser" parameterType="user">
                    <!-- keyProperty:对于pojo的主键属性 
                        resultType:对应主键的数据类型
                        order:是在insert语句执行之前或者之后。
                        如果使用uuid做主键,应该先生成主键然后插入数据,此时应该使用Before
                     -->
                    <selectKey keyProperty="id" order="AFTER" resultType="int">
                        select LAST_INSERT_ID()
                    </selectKey>

                        insert into user(username,birthday,sex,address) 
                        value(#{username},#{birthday},#{sex},#{address})
                </insert>
            </mapper>

        c、改造SqlMapperConfig.xml
            <?xml version="1.0" encoding="UTF-8"?>
            <!DOCTYPE configuration
            PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
            "http://mybatis.org/dtd/mybatis-3-config.dtd">

            <configuration>
                <!-- 配置属性 先加载内部属性,再加载外部属性,如果有同名属性会覆盖-->
                <properties resource="db.properties"/>

                <!-- 配置pojo别名 -->
                <typeAliases>
                    <!-- 扫描包的形式创建别名,别名就是类名,不区分大小写 -->
                    <package name="com.kid.mybatis.pojo"/>
                </typeAliases>

                <!-- 和spring整合后 environments配置将废除-->
                <environments default="development">
                    <environment id="development">
                    <!-- 使用jdbc事务管理-->
                        <transactionManager type="JDBC" />
                    <!-- 数据库连接池-->
                        <dataSource type="POOLED">
                            <property name="driver" value="${jdbc.driver}" />
                            <property name="url" value="${jdbc.url}" />
                            <property name="username" value="${jdbc.username}" />
                            <property name="password" value="${jdbc.password}" />
                        </dataSource>
                    </environment>
                </environments>

                <!-- 加载mapper文件 -->
                <mappers>
                    <!-- resource基于classpath查找 -->
                    <mapper resource="sqlmap/user.xml"/>
                    <!-- 根据接口名称加载mapper文件
                        要求:1、mapper映射文件和接口在同一个目录下
                            2、mapper映射文件的名称和接口名称一致。
                            3、class就是接口的权限定名
                     -->
                    <!-- 使用扫描包的形式加载mapper文件 -->
                    <package name="com.kid.mybatis.mapper"/>
                </mappers>
            </configuration>

测试

public class UserMapperTest {

            private SqlSessionFactory sqlSessionFactory = null;

            @Before
            public void init() throws Exception {
                // 第一步:创建一个SQLSessionFactoryBuilder对象。
                SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
                // 第二步:加载配置文件。
                InputStream inputStream = Resources.getResourceAsStream("SqlMapConfig.xml");
                // 第三步:创建SQLSessionFactory对象
                sqlSessionFactory = sqlSessionFactoryBuilder.build(inputStream);
            }


            @Test   //根据用户id获取用户
            public void getUserByIdTest() {
                //和spring整合后省略
                SqlSession sqlSession = sqlSessionFactory.openSession();
                //获取代理对象
                UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
                User user = userMapper.getUserById(10);
                System.out.println(user);

                //和spring整合后省略
                sqlSession.close();
            }

            @Test   //通过用户名查询用户
            public void findUserByUsernameTest() {
                SqlSession sqlSession = sqlSessionFactory.openSession();
                UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
                List<User> list = userMapper.getUserByUsername("张");
                for (User user : list) {
                    System.out.println(user);
                }
                sqlSession.close();
            }

            @Test
            public void insertUserTest() {
                SqlSession sqlSession = sqlSessionFactory.openSession();
                UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
                User user = new User();
                user.setUsername("关羽");
                user.setAddress("硅谷");
                user.setBirthday(new Date());
                user.setSex("2");
                userMapper.insertUser(user);
                sqlSession.commit();
                sqlSession.close();
            }
    }

猜你喜欢

转载自blog.csdn.net/CC1014524900/article/details/82559647