zoukankan      html  css  js  c++  java
  • MyBatis(3)开发dao方法

    本次全部学习内容MyBatisLearning

     
     
     
    SqlSession
            SqlSession是一个面向用户(程序员)的接口。
            SqlSession中提供了很多操作数据库的方法:如:selectOne(返回单个对象)、selectList(返回单个或多个对象)、。
            SqlSession是线程不安全的,在SqlSesion实现类中除了有接口中的方法(操作数据库的方法)还有数据域属性
            SqlSession最佳应用场合在方法体内,定义成局部变量使用。
            SqlSession中封装了对数据库的操作,如:查询、插入、更新、删除等。
            通过SqlSessionFactory创建SqlSession,而SqlSessionFactory是通过SqlSessionFactoryBuilder进行创建。
     
            每个线程都应该有它自己的SqlSession实例。SqlSession的实例不能共享使用,它也是线程不安全的。
            因此最佳的范围是请求或方法范围。绝对不能将SqlSession实例的引用放在一个类的静态字段或实例字段中。
            打开一个 SqlSession;使用完毕就要关闭它。通常把这个关闭操作放到 finally 块中以确保每次都能执行关闭。
     
     
     
    SqlSessionFactoryBuilder
            通过SqlSessionFactoryBuilder创建会话工厂SqlSessionFactory
            将SqlSessionFactoryBuilder当成一个工具类使用即可,不需要使用单例管理SqlSessionFactoryBuilder。
            在需要创建SqlSessionFactory时候,只需要new一次SqlSessionFactoryBuilder即可。
     
            SqlSessionFactoryBuilder用于创建SqlSessionFacoty,SqlSessionFacoty一旦创建完成就不需要SqlSessionFactoryBuilder了,
            因为SqlSession是通过SqlSessionFactory生产,所以可以将SqlSessionFactoryBuilder当成一个工具类使用,最佳使用范围是方
            法范围即方法体内局部变量。
     
     
    SqlSessionFactory
            通过SqlSessionFactory创建SqlSession,使用单例模式管理sqlSessionFactory(工厂一旦创建,使用一个实例)。
            将来mybatis和spring整合后,使用单例模式管理sqlSessionFactory。
             SqlSessionFactory是一个接口,接口中定义了openSession的不同重载方法,SqlSessionFactory的最佳使用范围
            是整个应用运行期间,一旦创建后可以重复使用,通常以单例模式管理SqlSessionFactory。
     
     
    SqlSession:
    SqlSession是一个面向用户的接口, sqlSession中定义了数据库操作,默认使用DefaultSqlSession实现类。
     
     
    1.原始dao开发方法(程序员需要些dao接口和dao实现类)
    程序员需要写dao接口和dao实现类
    需要xiangdao实现类中注入SqlSessionFactory在方法体内通过SqlSessionFactory创建SQlSession
     
    开始实践:
    新建包和类
     

    在UserDao.java接口中:

    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;
    }
     UserDao.java的实现类,UserDaoImp.java中:
     
    //UserDao的实现类
    public class UserDaoImp implements UserDao {
         //需要向dao实现类里面注入SqlSessionFactory
         //通过构造器注入
         private SqlSessionFactory SqlSessionFactory;
         public UserDaoImp(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.addUser", 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();
         }
    }

     在testUserDaoImp.java中:

     
    public class testUserDaoImp {
         
         private SqlSessionFactory SqlSessionFactory;
         public SqlSessionFactory getSqlSessionFactory() throws IOException{
               //配置文件的
            String resource = "SqlMapConfig.xml";
            //得到配置文件流
            InputStream inputStream = Resources.getResourceAsStream(resource);
            //创建会话工程
           SqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
            return SqlSessionFactory;
         }
         
         //根据id查询用户信息
         @Test
         public void findUserById() throws Exception{
               SqlSessionFactory SqlSessionFactory = getSqlSessionFactory();
               UserDao userdao = new UserDaoImp(SqlSessionFactory); 
               User user = userdao.findUserById(1);
               System.out.println(user);
         }
         //添加用户信息
    }

     控制台:

    DEBUG [main] - Opening JDBC Connection
    DEBUG [main] - Created connection 2054574951.
    DEBUG [main] - Setting autocommit to false on JDBC Connection [com.mysql.jdbc.JDBC4Connection@7a765367]
    DEBUG [main] - ==>  Preparing: select * from user where id=?
    DEBUG [main] - ==> Parameters: 1(Integer)
    DEBUG [main] - <==      Total: 1
     测试添加用户信息:
     
    //添加用户信息
         @Test
         public void testAddUser() throws Exception{
               SqlSessionFactory SqlSessionFactory = getSqlSessionFactory();
               UserDao userdao = new UserDaoImp(SqlSessionFactory);
               User user = new User();
               user.setUsername("Ma");
               user.setSex(1);
               user.setAddress("安徽");
               userdao.insertUser(user);
         
         }

     控制台:

    DEBUG [main] - Opening JDBC Connection
    DEBUG [main] - Created connection 22429093.
    DEBUG [main] - Setting autocommit to false on JDBC Connection [com.mysql.jdbc.JDBC4Connection@1563da5]
    DEBUG [main] - ==>  Preparing: insert into user(id,username,birthday,sex,address) value(?,?,?,?,?)
    DEBUG [main] - ==> Parameters: 0(Integer), Ma(String), null, 1(Integer), 安徽(String)
    DEBUG [main] - <==    Updates: 1
    DEBUG [main] - ==>  Preparing: SELECT LAST_INSERT_ID()
    DEBUG [main] - ==> Parameters:
    DEBUG [main] - <==      Total: 1
     
     
     测试删除操作:
         //删除用户信息
               @Test
               public void testDelete() throws Exception{
                    SqlSessionFactory SqlSessionFactory = getSqlSessionFactory();
                    UserDao userdao = new UserDaoImp(SqlSessionFactory);
                    userdao.deleteUser(29);
               }
    DEBUG [main] - Opening JDBC Connection
    DEBUG [main] - Created connection 22429093.
    DEBUG [main] - Setting autocommit to false on JDBC Connection [com.mysql.jdbc.JDBC4Connection@1563da5]
    DEBUG [main] - ==>  Preparing: delete from user where id=?
    DEBUG [main] - ==> Parameters: 29(Integer)
    DEBUG [main] - <==    Updates: 1
    DEBUG [main] - Committing JDBC Connection [com.mysql.jdbc.JDBC4Connection@1563da5]
     
     
    总结原始dao开发的问题:
     
    1、dao接口实现类方法中存在大量模板方法,设想能否将这些代码提取出来,大大减轻程序员的工作量。
    2、调用sqlsession方法时将statement的id硬编码了
    3、调用sqlsession方法时传入的变量,由于sqlsession方法使用泛型,即使变量类型传入错误,在编译阶段也不报错,不利于程序员开发。
     
     
     
     
     
    2.mapper代理方法(程序员只需要mapper接口)
    程序员还需要编写mapper.xml映射文件
    程序员编写mapper接口需要遵循一些开发规范,mybatis可以自动生成mapper接口实现类代理对象。
     
    Mapper接口开发方法只需要程序员编写Mapper接口(相当于Dao接口),由Mybatis框架根据接口定义
    创建接口的动态代理对象,代理对象的方法体同上边Dao接口实现类方法。
     
    Mapper接口开发需要遵循以下规范:
    1. Mapper.xml文件中的namespace与mapper接口的类路径相同。
    2.  Mapper接口方法名和Mapper.xml中定义的每个statement的id相同
    3. Mapper接口方法的输入参数类型和mapper.xml中定义的每个sql 的parameterType的类型相同
    4. Mapper接口方法的输出参数类型和mapper.xml中定义的每个sql的resultType的类型相同
     
    接口定义有如下特点:
    1. Mapper接口方法名和Mapper.xml中定义的statement的id相同
    2. Mapper接口方法的输入参数类型和mapper.xml中定义的statement的parameterType的类型相同
    3. Mapper接口方法的输出参数类型和mapper.xml中定义的statement的resultType的类型相同
     
    以上开发规范主要是对下边的代码进行统一生成:
    User user = sqlSession.selectOne("test.findUserById", id);
    sqlSession.insert("test.insertUser", user);
    update/insert/.........
    ........
     
     
     
     
    代码的实现开始了:
     
     
    创建包,类,已经映射文件
    此时添加了新的映射文件一定要在全局配置文件中添加:
         <mappers>
               <mapper resource="sqlmap/User.xml"/>
               <mapper resource="mapper/UserMapper.xml"/>
         </mappers>

     在UserMapper.java接口中:

         //根据id查询用户信息
         public User findUserById(int id) throws Exception;
    在UserMapper.xml文件中;
    namespace:是接口类的全类名
    id:是接口类中的方法
    <mapper namespace="com.MrChengs.mapper.UserMapper">
         <!-- 根据id查询 -->
         <!-- public User findUserById(int id) throws Exception; -->
         <select id="findUserById" parameterType="int" resultType="com.MrChengs.po.User">
               select * from user where id=#{id}
         </select>
    </mapper>

     在测试类testUserMapper.java类中

    private SqlSessionFactory SqlSessionFactory;
         public SqlSessionFactory getSqlSessionFactory() throws IOException{
               //配置文件的
            String resource = "SqlMapConfig.xml";
            //得到配置文件流
            InputStream inputStream = Resources.getResourceAsStream(resource);
            //创建会话工程
           SqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
            return SqlSessionFactory;
         }
         @Test
         public void testfindUserById() throws Exception{
                //得到sqlsession
               SqlSession sqlSession = getSqlSessionFactory().openSession();
               //创建UserMapper的代理对象
               UserMapper mapper = sqlSession.getMapper(UserMapper.class);
               //调用userMapper的方法
               User user = mapper.findUserById(27);
               System.out.println(user);
                sqlSession.close();
         }

     实现成功:

    DEBUG [main] - Opening JDBC Connection
    DEBUG [main] - Created connection 352359770.
    DEBUG [main] - Setting autocommit to false on JDBC Connection [com.mysql.jdbc.JDBC4Connection@1500955a]
    DEBUG [main] - ==>  Preparing: select * from user where id=?
    DEBUG [main] - ==> Parameters: 27(Integer)
    DEBUG [main] - <==      Total: 1
    User [id=27, username=MrChegns, birthday=Fri Oct 05 00:00:00 CST 2018, sex=2, address=北京]
     
    模糊查询:
    在UserMapper.java接口中:
    这里我们是不是会有疑问为什么不这样写?public User findByName(String name)  throws Exception;
        //根据用户名查询(模糊查询)
         public List<User> findByName(String name)  throws Exception;
    UserMapper.xml文件
       <!-- 根据用户名查询 -->
         <select id="findByName" parameterType="java.lang.String" resultType="com.MrChengs.po.User" >
               select * from user where username Like '%${value}%'
         </select>

     测试类:

        @Test
         public void testfindByName() throws Exception{
               SqlSession sqlSession = getSqlSessionFactory().openSession();
               
               //创建UserMapper的代理对象
               UserMapper mapper = sqlSession.getMapper(UserMapper.class);
    
               //调用userMapper的方法
               List<User> users = mapper.findByName("小明");
               for(User user:users){
                    System.out.println(user);
               }
               sqlSession.close();
         }

     查询成功:

    DEBUG [main] - ==>  Preparing: select * from user where username Like '%小明%'
    DEBUG [main] - ==> Parameters:
    DEBUG [main] - <==      Total: 3
    User [id=16, username=张小明, birthday=null, sex=1, address=河南郑州]
    User [id=22, username=陈小明, birthday=null, sex=1, address=河南郑州]
    User [id=25, username=陈小明, birthday=null, sex=1, address=河南郑州]
    模糊查询,此时可能会查出多个数据
    public User findByName(String name)  throws Exception;
    使用这个进行查询,系统在查询的时候会报错
     
     
     
    代理对象内部调用selectOne或selectList:
    如果mapper方法返回单个pojo对象(非集合对象),代理对象内部通过selectOne查询数据库。
    如果mapper方法返回集合对象,代理对象内部通过selectList查询数据库。
     
     
     
     
    mapper接口方法参数只能有一个参数会不会影响开发:
    mapper接口方法防暑只能有一个参数,系统开发是不利于扩展和维护的
    系统框架中,dao层是被业务代码公用的
    即使mapper接口层只有一个参数,可以使用包装类型的pojo满足不同的方法需求
    注意:持久层方法的参数包装类型:map,service....不建议使用(不利于扩展)
     
     
     
     
     
     
     
  • 相关阅读:
    ref与out的区别(C#)
    用MS SQL Server 2008修改数据库表时提示“不允许保存更改”的解决方法
    测试的职责
    性能测试新手误区(三):用户数与压力
    JAVA + LR实现apache流媒体的性能测试(LR部分)
    性能测试新手误区(二):为什么我模拟的百万测试数据是无效的
    JAVA + LR实现apache流媒体的性能测试(JAVA部分)
    性能测试新手误区(六):性能监控
    性能测试新手误区(五):这是性能问题么
    性能测试新手误区(四):一切来自录制
  • 原文地址:https://www.cnblogs.com/Mrchengs/p/9750076.html
Copyright © 2011-2022 走看看