MyBatis学习

一、mybatis是什么

  • MyBatis是一个ORM的数据库持久化框架
    框架(Framework)是一个框子——指其约束性,也是一个架子——指其支撑性,框架本身不解决问题。
  • 什么叫数据库持久化:
    数据库持久化是数据持久化的其中一种,就是把内存中的数据保存到数据库中。
  • Java中最简单的就是使用jdbc来完成数据库持久化:但是代码重复,拼接复杂。。
    MyBatis学习_第1张图片
  • ORM框架映射方式?
    1、Sql操作方式(对jdbc进行封装):
    把SQL配置到配置文件中,通过不同SQL中完成对象实体和数据库关系相互转换的操作。(mybatis的实现方式)
    2、完整操作:
    直接映射的是对象实体和数据库关系映射。操作数据库关系,不用写SQL有框架自己生成。(JPA、Hibenate实现方式)
    mybatis的取别在于是通过映射sql(不完全映射)来操作数据库

二、准备jar包,实体类

  • 新建普通Java项目
  • 数据库准备一张表product
    创建实体类
public class Product {
	private	Long id;
	//商品名称
	private String productName;
	//品牌
	private String brand;
	//供应商
	private String supplier;
	//零售价
	private BigDecimal salePrice;
	//进价
	private BigDecimal costPrice;
	//折扣价
	private Double cutoff;
	//商品分类编号
	private Long dir_id;
	 
   //提供getter与setter...
}
  • 准备 dao层
public interface IProductDao {

    void save(Product product);

    void remove(Long id);

    void update(Product product);

    Product loadOne(Long id);

    List loadAll();
}

三、搭建环境

MyBatis学习_第2张图片

  • 新建lib文件夹
  • recourses文件夹
  • 导入相应的jar包
    MyBatis学习_第3张图片
  • recourses中新建MyBatis-Config.xml



    
    
    
    
       
        
        
    
    
        
            
            
                
                
                
                
            
        
    
    
    
   
       
        
       
        
       
       
    


  • recourses中新建db.properties
db.driver=com.mysql.jdbc.Driver
db.url=jdbc:mysql:///mybatistest
db.username=xxx
db.password=xxxxx
  • 在实体类中新建xx类Mapper.xml
    在这里插入图片描述





    
    
    
    
    
    
    

        INSERT INTO product (productName,brand,supplier,salePrice,costPrice,cutoff,dir_id) VALUES (
        #{productName},
        #{brand},
        #{supplier},
        #{salePrice},
        #{costPrice},
        #{cutoff},
        #{dir_id})

    
    
    

        DELETE FROM product WHERE id = #{id}

    
    
    
    

        update product set
         productName = #{productName},
         brand = #{brand},
         supplier = #{supplier},
         salePrice = #{salePrice},
         costPrice = #{costPrice},
         cutoff = #{cutoff},
         dir_id = #{dir_id}
        where id = #{id}

    
    

  • 在MyBatis-Config.xml中引入关系映射xml

小结:
配置MyBatis-Config.xml
引入关系映射xml,关系映射文件中的sql决定了功能
映射文件要取命名空间,方便区分使用
映射文件中的sql方法取id,实现的时候调用这个id就可以
注意 sql中的配置
注意配置文件中的文件路径和实体路径,如果是文件的地址,是斜杠划分
实体类是.划分
实现方法的时候,是使用的命名空间的命名加上方法id
MyBatis-Config.xml引入的是xml映射关系文件

四、impl层实现

  • 读取配置文件
  • SqlSessionFactory获取
  • 获取SqlSession对象

问题:
每次实现方法都需要创建,获取,关闭。。

 @Override
    public void save(Product product) {
        SqlSession sqlSession = null;
        try {
            //加载mybatis.xml文件
            Reader reader = Resources.getResourceAsReader("MyBatis-Config.xml");
            //获取session工厂对象
            SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(reader);
            //测试工厂对象是否加载成功
            System.out.println(sessionFactory);
            //拿到session
            sqlSession = sessionFactory.openSession();
            //返回集合selectList
            sqlSession.insert("com.lr.mybatis._01_hello.domain.ProductMapper.save",product);
            sqlSession.commit();
        }catch (Exception e){
            sqlSession.rollback();
            e.printStackTrace();
        }finally {
            //关闭session
            if (sqlSession!=null){
                sqlSession.close();
            }
        }
    }

入门小结

  1. 准备配置文件-Mybatis-Config.xml
    1)环境配置-配置怎么访问数据
    2)导入映射配置-先不配置
  2. 基于配置文件创建SqlSessionFactory
    1)通过配置文件获取Reader
    2)SqlSessionFactoryBuilder.build(reader)
  3. 通过SqlSessionFactory获取SqlSession,并调用对应的api完成对应操作
    1)配置映射文件并且在Mybatis-Config.xml导入
    2)获取SqlSession
    3)调用api-selectOne,selectList,insert,delete,update
    4)如果是增删改要做事务控制 commit rollback
    5)关闭sqlsession

五、工具类抽取

为了减少重复代码,抽取一个工具类,可以方便的获取session对象和关闭对象

public enum  MybatisUtil {
    INSTANCE;
    //获取session的工厂
    private static SqlSessionFactory sessionFactory;
    //静态代码块,运行就创建
    //在其他地方可以随时调用获取session
    static {
        //加载工厂对象
        //加载mybatis.xml文件
        try {
            //注意try catch中如果先没有处理异常,会报错
            Reader reader = Resources.getResourceAsReader("MyBatis-Config.xml");
            //获取session工厂对象
            sessionFactory = new SqlSessionFactoryBuilder().build(reader);
        }catch (Exception e){
            e.printStackTrace();
        }
    }
    //得到sqlsession的方法
    public SqlSession openSqlSession (){
        //System.out.println("================");
        SqlSession sqlSession = sessionFactory.openSession();
        //System.out.println("+++++++++++++++++++++++");
        return sqlSession;
    }
    //关闭 SqlSession 的方法  需要传入sqlSession   确定要关闭的对象是哪一个
    public void endSqlSession(SqlSession sqlSession){
        if (sqlSession!=null){
            sqlSession.close();
        }
    }
}

  • 注意枚举的单例模式
  • 静态代码块
  • 异常处理
  • 将方法中的重复代码全部替换掉

六、mybatis使用一些细节

  1. 保存时返回id
  • 如果没有在关系映射xml中配置时如果马上打印使用这个被添加的对象时,id是空的
  • Product{id=null, productName=‘测试’, brand=‘null’, supplier=‘null’, salePrice=null, costPrice=null, cutoff=null, dir_id=null}只添加了一个名字,但是id是空的
  • mybatis不像jpa,没有自动维护关联表关系的功能所以需要得到返回的id,自动将id设置到刚才添加的对象中,并且我们能使用设置到中间表,手动维护关系
  • 解决方法:
    在映射关系xml中的sql方法配置时,加上这些设置

    
  1. 别名
    在MyBatis.xml中配置别名,实体关系映射xml中就可以直接使用别名
    比如

配置的方法


    
    
    
    
       
        
        
    

  1. 日志支持
    log4j-1.2.17.jar
    slf4j-api-1.7.2.jar
    slf4j-log4j12-1.7.2.jar
    在资源文件中配置log4j.properties
    在这里插入图片描述
log4j.rootLogger=DEBUG, stdout
#log4j.rootLogger=NONE
log4j.logger.com.lr=TRACE

log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d %p [%c] - %m%n

一定要根据自己的包名情况进行修改
如果配置成功,那么在MyBatis运行操作数据时就可以看到相应的日志了。
如果要打印到debug,需要改成
log4j.rootLogger=DEBUG, stdout

  1. #与$区别
  • #{OGNL表达式}
MyBatis会把这个表达式使用?(占位符)替换,作为一个sql参数使用:推荐使用
     比如name的值为:  
     定义SQL: select * from t_user where name = #{name}
     最终SQL: select * from t_user where name = ? 
  • ${OGNL表达式} 的区别

MyBatis会把这个表达式的值替换到sql中,作为sql的组成部分;
该方式主要用于程序拼接SQL;
如果sql中使用${OGNL},并且参数的类型是(integer,string…)那么OGNL表达式可以写成任意东西;

  • ${OGNL}表达式的应用场景
    1)不能用在登录,会出现sql注入
    比如登录功能,在输入name的时候可以人为的制造成功:
User user=new User();
user.setName("\"admin\" or \"1=1\" ");
user.setPassword("\"admin\"  ");
     定义SQL: select id,name,password from t_user where name = ${name} and password=${password}
     最终SQL: select id,name,password from t_user where name="test" or "1=1" and password="test"  出现sql注入

2)用在order by + limit的场景

七、常用的动态SQL

  1. 传入id批量删除


        DELETE FROM product WHERE id IN 
          #{id}
    
    

实现方法

@Override
    public void removeMany(List ids) {
        System.out.println("=======================");
        SqlSession sqlSession =null;
        try {
            sqlSession = MybatisUtil.INSTANCE.openSqlSession();
            sqlSession.delete("com.lr.mybatis._04_batch_many.domain.ProductMapper.removeMany", ids);
            //提交事务
            sqlSession.commit();
        }catch (Exception e){
            //事务回滚
            sqlSession.rollback();
            e.printStackTrace();
        }finally {
            MybatisUtil.INSTANCE.endSqlSession(sqlSession);
        }
    }
  1. 批量添加

		

        INSERT  INTO product (productName,brand,supplier,salePrice,costPrice,cutoff,dir_id)VALUES
        
        (#{product.productName},#{product.brand},#{product.supplier},#{product.salePrice},
        #{product.costPrice},#{product.cutoff},#{product.dir_id})

        
    

实现方法

@Override
    public void addMany(List list) {
        SqlSession sqlSession =null;
        try {
            sqlSession = MybatisUtil.INSTANCE.openSqlSession();
            sqlSession.delete("com.lr.mybatis._04_batch_many.domain.ProductMapper.addMany", list);
            //提交事务
            sqlSession.commit();
        }catch (Exception e){
            //事务回滚
            sqlSession.rollback();
            e.printStackTrace();
        }finally {
            MybatisUtil.INSTANCE.endSqlSession(sqlSession);
        }
    }

你可能感兴趣的:(MyBatis学习)