MyBatis基础

MyBatis

MyBatis是java平台下一款优秀的持久层框架,它支持定制化 SQL、存储过程以及高级映射。MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集。MyBatis 可以使用简单的 XML 或注解来配置和映射原生信息,将接口和 Java 的 POJOs(Plain Ordinary Java Object,简单普通的 Java对象)映射成数据库中的记录。

其前身为apache的ibatis后来迁移到Gihub并更名为MyBatis

特点:

​ 1.轻量级自身不依赖其他任何JAR,但需要提供JDBC实现

​ 2.灵活,更加适用于需求变化频繁的互联网应用

​ 3.学习成本低,相比ORM框架而言,掌握MyBatis的使用是很轻松的

在结构中的位置

MyBatis基础_第1张图片

可以看出MyBatis处在DAO(数据访问对象)的位置,回顾一下DAO的工作职责:

​ 连接数据库

​ 接收输入数据

​ 拼接并执行SQL

​ 解析并返回结果

为什么需要MyBatis

使用JDBC完成DAO层存在以下问题

  • 每次操作都需要手动的创建连接,最后关闭连接

    对于重复代码通常开发者都会进行封装,但是由于每个人的编码风格不同导致封装的代码也没有固定的套路

    MyBatis将数据库连接相关的参数放到配置XML中并封装了创建连接的代码
  • 频繁的创建和销毁连接

    由于数据库连接使用的是TCP长连接,并发量大的系统中,这样的方式会导致数据库连接资源耗尽

    MyBatis本身实现了连接池,可以解决这一问题,当然后续会更换其他更好的连接池
  • 接受参数拼接SQL语句并执行

    每一条SQL语句都是直接写在代码中(硬编码),如果后期需求发生变化,则需要修改源码中的SQL,然后重新编译,测试.....

    MyBatis将SQL语句从代码中剥离到Mapper.xml映射文件中
  • 解析结果

    JDBC返回的是ResultSet,必须手动将其映射到一个个的对象中,同样是重复度很高的代码;并且存在硬编码问题

    MyBatis实现了入参映射到SQL参数,以及结果集映射到POJO对象

更多功能

MyBatis在解决上述问题的同时提供了更多实用的功能

  • 动态SQL,即在SQL语句中可以包含逻辑处理(判断,循环等....)

  • 高级映射,支持一对一,一对多映射

  • 动态代理Mapper,使得可以用面向对象的方式来完成数据库操作

  • 逆向工程,根据表结构自动生成,POJO,Mapper映射和Mapper接口,包含简单的CRUD

MyBatis构架

MyBatis基础_第2张图片

  • SqlMapConfig.xml作为全局配置,指定MyBatis的基本参数,如运行环境(开发,发布),事务管理器,数据来源等; 以及需要加载的mapper映射文件(从源码中剥离出来的SQL语句)

  • SqlSessionFactory,负责读取SqlMapConfig中的参数创建会话

  • SqlSession,通过SqlSessionFactory获取一个Session(会话)
  • Executor 真正负责执行sql语句的对象
  • MappedStatement用于将输入参数映射到sql语句,以及结果集映射到POJO

上述构架中,SqlSession以下的部分是MyBatis封装好的,SqlSession负责调用它们完成操作; 开发过程中不需要涉及(特殊需求除外);

另外SqlSessionFactory和SqlSession也可以通过简单的代码获取到,后续Spring框架能够自动创建它们

所以使用MyBatis的重点就落在了SqlMapConfig.xml以及Mapper.xml

CRUD入门

环境搭建

官方文档:https://mybatis.org/mybatis-3/getting-started.html

  1. 创建项目

    这里采用Maven来引入MyBatis,项目采用普通的Java项目,不使用Maven骨架

  2. 添加依赖

     1.8 1.8
    
    
     org.mybatis mybatis 3.5.3
        
        
    mysql mysql-connector-java 8.0.17
        
        
    log4j log4j 1.2.17
        
        
    junit junit 4.12
        
    
  3. 提供配置文件

    1. MyBatis全局配置

      mybatis-config.xml

      
      
      
          
      
              
      
                  
      
                  
                      
      
                      
                      
                      
                  
              
          
      
          
              
          
      
      
      
      
    2. log4日志模块,定义输出格式的配置

      log4j.properties

      # Global logging configuration
      log4j.rootLogger=DEBUG, stdout  
      # Console output... 
      log4j.appender.stdout=org.apache.log4j.ConsoleAppender 
      log4j.appender.stdout.layout=org.apache.log4j.PatternLayout 
      log4j.appender.stdout.layout.ConversionPattern=%5p [%t] - %m%n

查询数据

查询单个

  1. 创建并编写Mapper

ProductsMapper.xml






        
    
  

​ 不要忘记将这个mapper配置到mybatis-config.xml中

    
        
    
  1. 执行测试
 @Test
    public void TestSelect() throws IOException {
        //获取的工厂构造器
        SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
        //加载配置文件
        InputStream stream = Resources.getResourceAsStream("mybatis-config.xml");
        //获得会话工厂
        SqlSessionFactory factory = builder.build(stream);
        //获得会话
        SqlSession sqlSession = factory.openSession();

        //执行sql
        Products product = sqlSession.selectOne("selectProductBtId", 1);
        System.out.println(product);
    }

查询多个

需求:使用模糊查询名字中带有新疆的数据

  1. 修改mapper增加标签

  2. 执行测试

    @Test
    public void selectTest2() throws IOException {
        //获得会话
        SqlSession sqlSession = factory.openSession();
        //执行sql
        List products = sqlSession.selectList("selectProductLikeName", "新疆");
        System.out.println(products);
        sqlSession.close();
    }

    由于多个测试方法都需要工厂所以讲工厂作为属性并在,@Before中进行初始化

    public class MyBatisTest {
        private SqlSessionFactory factory;
        @Before
        public  void init() throws IOException {
            //获取的工厂构造器
            SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
            //加载配置文件
            InputStream stream = Resources.getResourceAsStream("mybatis-config.xml");
            //获得会话工厂
            factory = builder.build(stream);
        }
    ........}

    需要注意的是:在mapper中当需要做将参数进行字符串拼接时则不能在使用#{} 需更换为${}表示将参数结果提取并拼接到字符串中

    注意了:若MyBatis版本低于3.5.2 则在字符串中使用#{xxx}的方式将导致找不到属性异常,在低版本中MyBatis将#{xxx}中的xxx当做参数的属性去参数中查找get方法(很明显找不到),不知道为啥这么设计,在字符串内和字符串串为获取属性的行为竟然不同,,,,,好在3.5.2解决了这个问题,真TM坑......

插入数据

  1. 修改mapper增加标签

    
    
      insert into products values(null,#{pname},#{price},#{pdate},#{cid})
    
  2. 执行测试

    @Test
    public void insertTest() {
        //设置自动提交为true 默认为false  
        SqlSession session = factory.openSession(true);
        //实例化一个商品
        Products p = new Products();
        p.setPname("虎邦辣酱");
        p.setPrice(5.5f);
        p.setPdate(new Date());
        p.setCid("s001");
        session.insert("insertProduct",p);
        //session.commit();//手动commit
        session.close();
    }
    强调:

    当sql为update insert delete时需要commit才会生效,SqlSession默认不自动提交的,可以在获取SqlSession时指定自动提交,也可以在执行完后手动调用commit;

    sql为update insert delete时返回值为受影响行数

  3. 获取插入记录的id

    很多情况下需要获取刚刚添加的记录的id用来做表关联,要获得id有两种方式

    3.1对于支持自增的数据库MySQL

    
      insert into products values(null,#{pname},#{price},#{pdate},#{cid})
    
    MyBatis会把id存储到传入对象的pid属性中

    3.2兼容不支持自增的数据库

    
        
            insert into products values(null,#{pname},#{price},#{pdate},#{cid})
            
            
                select last_insert_id();
            
        

    注意:select last_insert_id();是mysql的函数,oracle没有,那就需要将其替换为oracle中生产id的函数,selectKey的原理是执行这个sql函数,然后将结果放入对象的属性中,order指定id放入对象属性是在执行sql前或者后

    关于before和after的选择,要根据id的来源是自增的还是自己编写语句获取的,如下:

    MyBatis基础_第3张图片

更新数据

  1. 修改mapper增加标签

    
        
            update products set
                pname = #{pname},
                price = #{price},
                pdate = #{pdate},
                cid = #{cid}
            where pid = #{pid}
        
  2. 执行测试

    @Test
    public void updateTest() {
        SqlSession session = factory.openSession();
        //先获取一条记录
        Products p = session.selectOne("selectProductBtId", 1);
        //更新属性
        p.setPrice(99.99f);
        //执行更新
        int count = session.update("updateProduct", p);
        System.out.println("update count :"+count);
        //提交事务
        session.commit();
        session.close();
    }

删除数据

  1. 修改mapper增加标签

    
    
      delete from products where
      pid = #{pid}
    
  2. 执行测试

    @Test
    public void deleteTest() {
        SqlSession session = factory.openSession();
        int count = session.delete("deleteProductById", 1);
        System.out.println("delete count :"+count);
        session.commit();
        session.close();
    }

你可能感兴趣的:(MyBatis基础)