• 02_mybatis开发dao的方法


    MyBatis开发dao的方法

    1. SqlSession使用范围

    1.1 SqlSessionFactoryBuilder

    ​ 通过SqlSessionFactoryBuilder创建会话工厂SqlSessionFactory,将SqlSessionFactoryBuilder当成一个工具类使用即可,不需要使用单例管理SqlSessionFactoryBuilder。在需要创建SqlSessionFactory时候,只需要new一次SqlSessionFactoryBuilder即可。

    1.2 SqlSessionFactory

    通过SqlSessionFactory创建SqlSession,使用单例模式管理sqlSessionFactory(工厂一旦创建,使用一个实例)。 将来mybatis和spring整合后,使用单例模式管理sqlSessionFactory。

    1.3 SqlSession

    SqlSession是一个面向用户(程序员)的接口。

    SqlSession中提供了很多操作数据库的方法:如:selectOne(返回单个对象)、selectList(返回单个或多个对象)。

    SqlSession是线程不安全的,在SqlSesion实现类中除了有接口中的方法(操作数据库的方法)还有数据域属性。

    **SqlSession*最佳应用场合在方法体内,定义成局部变量使用。

    2. 原始dao开发方法

    需要写dao接口和dao实现类

    2.1 思路

    ​ 程序员需要写dao接口和dao实现类,需要向dao实现类中注入SqlSessionFactory,在方法体内通过SqlSessionFactory创建SqlSession。

    2.2 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的隔离-->
    <mapper namespace="test">
            <!--sql语句-->
        <!--通过select查询数据库信息
        id:标识映射文件的sql,将SQL语句封装到prepareStatement.称为statementid
        -->
        <select id="findUserById" parameterType="int" resultType="User">
          SELECT * FROM user where id=#{id}
        </select>
    
        <!--根据用户名模糊查询用户信息-->
        <!--
       resultType:表示单条记录所映射的java类型
        使用${}表示拼接sql串,将接受到的参数不加任何修饰拼接到sql中
        使用${}拼接sql,会引起sql注入,
        ${value}:接受输入参数的内容,如果传入类型是简单类型,${}中只能是value
        -->
        <select id="findUserByName" parameterType="java.lang.String" resultType="com.mybatis.po.User">
             SELECT * FROM USER WHERE USERNAME LIKE '%${value}%'
        </select>
    
        <!--添加用户(非自增主键的返回)-->
        <insert id="insertUser" parameterType="com.mybatis.po.User">
            <!--
            将插入数据的主键返回,返回到user对象中
            keyProperty:将查询到的主键值,设置到parameterType(目标对象)的那个属性
            order:表示执行顺序
            resultType:表示类型
            -->
        <selectKey keyProperty="id" order="AFTER" resultType="java.lang.Integer">
            SELECT LAST_INSERT_ID()
        </selectKey>
            insert into user(id,username,birthday,sex,address) value(#{id},#{username},#{birthday},#{sex},#{address});
    </insert>
    
        <!--添加用户1自增主键值的返回-->
        <insert id="insertUser1" parameterType="com.mybatis.po.User" useGeneratedKeys="true" keyProperty="id">
            insert into user(id,username,birthday,sex,address) value(#{id},#{username},#{birthday},#{sex},#{address});
        </insert>
    
        <!--删除用户-->
        <!--根据用户id删除用户:输入id值-->
    <delete id="deleteUserById" parameterType="java.lang.Integer">
        DELETE FROM USER WHERE ID=#{ID}
    </delete>
    
        <!--更新用户-->
        <!--根据用户id,更新,
         用户的更新信息
         parameterType:指定user对象,包含用户的所有信息
         #{id}从user对象中获取user的值
        -->
        <update id="updateUserById" parameterType="User">
           update user set username=#{username},birthday=#{birthday},sex=#{sex},address=#{address} where id=#{id}
        </update>
    
    </mapper>
    
    
    

    2.3 dao

    /**
     * Description:演示原始开发方法dao
     * User: jiatp
     * Date:2019/9/2 0002 下午 10:39
    */
    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;
    
    }
    
    

    2.4 dao接口实现类

    /**
     * Description:dao实现类
     * User: jiatp
     * Date:2019/9/2 0002 下午 10:44
    */
    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);
            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.deleteUserById",id);
            sqlSession.commit();
            sqlSession.close();
        }
    }
    
    

    2.5 测试代码

    /**
     * Description:传统dao、dao实现类开发方法
     * User: jiatp
     * Date:2019/9/3 0003 下午 10:18
    */
    public class MyBatisSecond {
    
        private SqlSessionFactory sqlSessionFactory;
        @Before
        public void setUp() throws IOException{
            //mybatis配置文件
            String resource = "com/mybatis/config/sqlMapConfig.xml";
            //得到配置文件流
            InputStream resourceAsStream = Resources.getResourceAsStream(resource);
            sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);
        }
    
        //查询用户
        @Test
        public void findById() throws Exception {
            UserDao userDao = new UserDaoImpl(sqlSessionFactory);
            User user = userDao.findUserById(27);
            System.out.println(user);
        }
        //删除用户
        @Test
        public void deleteUserById() throws Exception {
            UserDao userDao = new UserDaoImpl(sqlSessionFactory);
            userDao.deleteUser(26);
        }
    
    
    
    
    }
    
    

    2.6 总结原始dao开发问题

    1、dao接口实现类方法中存在大量模板方法,设想能否将这些代码提取出来,大大减轻程序员的工作量。

    2、调用sqlsession方法时将statement的id硬编码了

    3、调用sqlsession方法时传入的变量,由于sqlsession方法使用泛型,即使变量类型传入错误,在编译阶段也不报错,不利于程序员开发

    3. mapper代理开发

    **mapper代理开发规范:**程序员还需要编写mapper.xml映射文件;程序员编写mapper接口要遵循一些开发规范,mybatis可以自动实现类代理对象。

    **开发规范:***1.mapper.xml中namespace等于mapper接口地址;

    <!--namespace-sql的隔离-->
    <mapper namespace="com.mybatis.mapper.UserMapper">
            <!--sql语句-->
        <!--通过select查询数据库信息
        id:标识映射文件1的sql,将SQL语句封装到prepareStatement.称为statementid
        -->
        <select id="findUserById" parameterType="int" resultType="com.mybatis.po.User">
          SELECT * FROM user where id=#{id}
        </select>
    
    1. mapper.java接口中的方法名和mapper.xml中statement的id一致;
    2. mapper.java接口中的方法输入参数类型和mapper.xml中statement的parameterType指定的类型一致;
    3. mapper.java接口中的方法返回值类型和mapper.xml中statement的resultType指定的类型一致;

    以上开发规范主要是对下边的代码进行统一生成。

    3.1 mapper.java

    
    /**
     * Description:mapper代理开发
     * User: jiatp
     * Date:2019/9/2 0002 下午 10:39
    */
    public interface UserMapper {
    
        //根据id查询用户信息
        public User findUserById(int id) throws Exception;
        //添加用户信息
        public void insertUser(User user) throws Exception;
        //删除用户信息
        public void deleteUserById(int id) throws Exception;
        //根据用户名查询用户列表
        public List<User> findUserByName(String name) throws Exception;
    
    }
    
    

    3.2 mapper.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 namespace="com.mybatis.mapper.UserMapper">
            <!--sql语句-->
        <!--通过select查询数据库信息
        id:标识映射文件1的sql,将SQL语句封装到prepareStatement.称为statementid
        -->
        <select id="findUserById" parameterType="int" resultType="com.mybatis.po.User">
          SELECT * FROM user where id=#{id}
        </select>
    
        <!--根据用户名模糊查询用户信息-->
        <!--
       resultType:表示单条记录所映射的java类型
        使用${}表示拼接sql串,将接受到的参数不加任何修饰拼接到sql中
        使用${}拼接sql,会引起sql注入,
        ${value}:接受输入参数的内容,如果传入类型是简单类型,${}中只能是value
        -->
        <select id="findUserByName" parameterType="java.lang.String" resultType="user">
             SELECT * FROM USER WHERE USERNAME LIKE '%${value}%'
        </select>
    
        <!--添加用户(非自增主键的返回)-->
        <insert id="insertUser" parameterType="com.mybatis.po.User">
            <!--
            将插入数据的主键返回,返回到user对象中
            keyProperty:将查询到的主键值,设置到parameterType(目标对象)的那个属性
            order:表示执行顺序
            resultType:表示类型
            -->
        <selectKey keyProperty="id" order="AFTER" resultType="java.lang.Integer">
            SELECT LAST_INSERT_ID()
        </selectKey>
            insert into user(id,username,birthday,sex,address) value(#{id},#{username},#{birthday},#{sex},#{address});
    </insert>
    
        <!--添加用户1自增主键值的返回-->
        <insert id="insertUser1" parameterType="com.mybatis.po.User" useGeneratedKeys="true" keyProperty="id">
            <!--
            将插入数据的主键返回,返回到user对象中
            keyProperty:将查询到的主键值,设置到parameterType(目标对象)的那个属性
            order:表示执行顺序
            resultType:表示类型
            -->
            insert into user(id,username,birthday,sex,address) value(#{id},#{username},#{birthday},#{sex},#{address});
        </insert>
    
        <!--删除用户-->
        <!--根据用户id删除用户:输入id值-->
    <delete id="deleteUserById" parameterType="java.lang.Integer">
        DELETE FROM USER WHERE ID=#{ID}
    </delete>
    
        <!--更新用户-->
        <!--根据用户id,更新,
         用户的更新信息
         parameterType:指定user对象,包含用户的所有信息
         #{id}从user对象中获取user的值
        -->
        <update id="updateUserById" parameterType="com.mybatis.po.User">
           update user set username=#{username},birthday=#{birthday},sex=#{sex},address=#{address} where id=#{id}
        </update>
    
    </mapper>
    
    
    

    3.3 测试

    
    /**
     * Description:测试mapper.java  mapper.xml
     * User: jiatp
     * Date:2019/9/3 0003 上午 9:08
    */
    public class UserMapperTest {
        private SqlSessionFactory sqlSessionFactory;
        @Before
        public void setUp() throws IOException {
            //mybatis配置文件
            String resource = "com/mybatis/config/sqlMapConfig.xml";
            //得到配置文件流
            InputStream resourceAsStream = Resources.getResourceAsStream(resource);
            sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);
        }
        //根据id查询用户
        @Test
        public void testFindById() throws Exception {
            SqlSession sqlSession = sqlSessionFactory.openSession();
            //        创建userMapper对象,mybatis自动代理生成mapper对象
            UserMapper mapper = sqlSession.getMapper(UserMapper.class);
            User user = mapper.findUserById(27);
            System.out.println(user);
            sqlSession.close();
    
        }
        //插入用户
        @Test
        public void testInsertUser() throws Exception {
            SqlSession sqlSession = sqlSessionFactory.openSession();
            // 创建userMapper对象,mybatis自动代理生成mapper对象
            UserMapper mapper = sqlSession.getMapper(UserMapper.class);
            User user = new User();
            user.setUsername("东方不败");
            user.setSex("2");
            user.setBirthday(new Date());
            user.setAddress("北京东城");
            mapper.insertUser(user);
            //不要忘记增删改,完了要提交和关闭资源
            sqlSession.commit();
            sqlSession.close();
    
        }
        // 删除用户
        @Test
        public void testDeleteUser() throws Exception {
            SqlSession sqlSession = sqlSessionFactory.openSession();
            // 创建userMapper对象,mybatis自动代理生成mapper对象
            UserMapper mapper = sqlSession.getMapper(UserMapper.class);
            mapper.deleteUserById(196);
            //不要忘记增删改,完了要提交和关闭资源
            sqlSession.commit();
            sqlSession.close();
        }
        //根据用户名称查询用户列表
        @Test
        public void findUserByName() throws Exception {
            SqlSession sqlSession = sqlSessionFactory.openSession();
            // 创建userMapper对象,mybatis自动代理生成mapper对象
            UserMapper mapper = sqlSession.getMapper(UserMapper.class);
            List<User> list = mapper.findUserByName("小明");
            for(User user:list) {
                System.out.println(user);
            }
           /* User user = mapper.findUserByName("小明");
            System.out.println(user);*/
            sqlSession.close();
        }
    }
    
    

    4. 问题总结

    4.1 代理对象内部调用selectOne或selectList

    1.如果mapper方法返回单个pojo对象(非集合对象),代理对象内部通过selectOne查询数据库。

    2.如果mapper方法返回集合对象,代理对象内部通过selectList查询数据库。

    4.2 mapper接口方法参数只能有一个是否影响系统 开发

    1.mapper接口方法参数只能有一个,系统是否不利于扩展维护。

    2.系统 框架中,dao层的代码是被业务层公用的。即使mapper接口只有一个参数,可以使用包装类型的pojo****满足不同的业务方法的需求。

    注意:持久层方法的参数可以包装类型、map。service方法中建议不要使用包装类型(不利于业务层的可扩展)。

  • 相关阅读:
    Error Code: 1414. OUT or INOUT argument 2 for routine company.new_procedure is not a variable or NEW
    Linux四个常用的指挥机关处理具体的解释
    JTextpane 加入的行号
    Oracle主键(Primary Key)使用详细的说明
    POJ 3904(容斥原理)
    [Angular] AuthService and AngularFire integration
    [React] Close the menu component when click outside the menu
    [D3] SVG Graphics Containers and Text Elements in D3 v4
    [D3] Start Visualizing Data Driven Documents with D3 v4
    [Angular] Setup automated deployment with Angular, Travis and Firebase
  • 原文地址:https://www.cnblogs.com/jatpeo/p/11767510.html
Copyright © 2020-2023  润新知