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 [[email protected]]
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 [[email protected]]
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 [[email protected]]
DEBUG [main] - ==>  Preparing: delete from user where id=?
DEBUG [main] - ==> Parameters: 29(Integer)
DEBUG [main] - <==    Updates: 1
DEBUG [main] - Committing JDBC Connection [[email protected]]

总结原始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 [[email protected]]
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....不建议使用(不利于扩展)

原文地址:https://www.cnblogs.com/Mrchengs/p/9750076.html

时间: 2024-10-04 00:36:57

MyBatis(3)开发dao方法的相关文章

09_Mybatis开发Dao方法——mapper代理开发规范

一.开发规范 需要编写mapper.xml映射文件(本项目为userMapper.xml,类似于前面的user.xml). 编写mapper接口需要遵循一些开发规范,这样MyBatis可以自动生成mapper接口实现代理对象. 1.在userMapper中namespace等于mapper接口地址 [UserMapper.xml]中的namespace: 2.UserMapper接口中方法名和UserMapper.xml中的statement的id一致 [UserMapper.java] [Us

10_Mybatis开发Dao方法——mapper代理实现

[工程截图(几个关键的标红框)] [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"> <mapper namespace=&

Mybatis学习记录(五)--整合spring开发Dao

mybatis和spring整合,也就是通过spring管理SqlSessionFactory.mapper接口. 一.导入架包 除了spring的包和mybatis的包,还需要导入两者的整合包,目前这个包由mybatis提供 mybatis-spring-1.2.0.jar 二.一些必要的配置文件 1.log4j配置 需要先导入log4j的架包,然后建立log4j.properties # Global logging configuration #在开发环境中要设置为DEBUG,不然不会打印

mybatis开发dao的方法

mybatis开发dao的方法 1.1     SqlSession使用范围 1.1.1     SqlSessionFactoryBuilder 1 //以流的方式读取总的配置文件 2 Reader reader = Resources.getResourceAsReader("mybatis-config.xml"); 3 4 //生成SqlSessionFactory 5 SqlSessionFactory sqlSessionFactory = new SqlSessionFa

【MyBatis学习04】mapper代理方法开发dao

上一篇博文总结了mybatis使用 原始dao的方法存在的一些弊端,我们肯定不会去用它,那么mybatis中该如何开发dao呢?如题所述,这篇博文主要来总结一下使用mapper代理的方法来开发dao的步骤. 使用mapper代理的方法来开发dao时,程序员只需要干两件事即可: 需要编写mapper.xml映射文件 需要编写mapper接口(相当于dao接口) 从做的工作来看,使用mybatis中使用mapper代理来开发dao会很方便,完全不需要我们去写具体的实现类,只需要写出接口即可,但是接口

MyBatis学习--mybatis开发dao的方法

简介 使用Mybatis开发Dao,通常有两个方法,即原始Dao开发方法和Mapper接口开发方法. 主要概念介绍: MyBatis中进行Dao开发时候有几个重要的类,它们是SqlSessionFactoryBuilder.SqlSessionFactory.SqlSession. SqlSession中封装了对数据库的操作,如:查询.插入.更新.删除等.通过SqlSessionFactory创建SqlSession,而SqlSessionFactory是通过SqlSessionFactoryB

MyBatis开发Dao

MyBatis开发Dao有两种方法: 1.原始Dao开发方法,就是程序需要编写Dao的接口和Dao的实现类. 2.MyBatis的mapper接口(相当于Dao接口)代理开发方法.(更重要)

11Mybatis_mybatis开发Dao的方法

在介绍开发Dao的方法之前先介绍下SqlSession. 1.先介绍一下SqlSessionFactoryBuilder:通过SqlSessionFactoryBuilder创建会话工厂SqlSessionFactory 将SqlSessionFactoryBuilder当成一个工具类使用即可,不需要使用单例管理SqlSessionFactoryBuilder. 在需要创建SqlSessionFactory时候,只需要new一次SqlSessionFactoryBuilder即可. 2.再介绍一

Mybatis学习记录(二)--Mybatis开发DAO方式

mybatis开发dao的方法通常用两种,一种是传统DAO的方法,一种是基于mapper代理的方法,下面学习这两种开发模式. 写dao之前应该要对SqlSession有一个更加细致的了解 一.mybatis的SqlSession使用范围 SqlSessionFactoryBuilder用于创建SqlSessionFacoty,SqlSessionFacoty一旦创建完成就不需要SqlSessionFactoryBuilder了,因为SqlSession是通过SqlSessionFactory生产