SSM框架专题-MyBatis框架从零入门老杜版笔记(上)

Posted 火柴哟

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了SSM框架专题-MyBatis框架从零入门老杜版笔记(上)相关的知识,希望对你有一定的参考价值。

MyBatis框架从零入门老杜版笔记(上)

一、MyBatis概述

1.1 框架 framework

1.2 MyBatis和JDBC的关系

MyBatis是增强版的jdbc,把一些功能通过反射封装好了

1.3 JDBC不足

  • sql语句写死,如果拓展功能,可能整个sql语句作废
  • set操作繁琐,如果sql语句有一百个?可能要写一百个set

1.4 了解MyBatis

  • MyBatis是对jdbc的封装
  • MyBatis之前叫做ibatis,后来才改名
  • MyBatis是持久层框架

1.5 了解ORM

  • O(Object):JVM中的java对象
  • R(Relational):关系型数据库
  • M(Mapping):映射
  • 什么是ORM?:JavaBean与数据表记录的互相映射

二、MyBatis入门程序

2.1 建数据库表


添加两条字段

2.2 加载mybatis的五个步骤

  1. 配置Maven环境,打包方式设置为jar,加载MyBatis,mysql
<packaging>jar</packaging>
<dependencies>
        <!--  MyBatis  -->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.5.11</version>
        </dependency>

        <!--  MySQL  -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.30</version>
        </dependency>

    </dependencies>
  1. 新建,编辑mybatis-config.xml文件(放入resources文件夹)
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.cj.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://localhost:3306/powernode"/>
                <property name="username" value="xxxx"/>
                <property name="password" value="xxxx"/>
            </dataSource>
        </environment>
    </environments>
    <mappers>
        <mapper resource="CarMapper.xml"/>
    </mappers>
</configuration>
  1. 新建,配置xxxMapper.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="org.mybatis.example.BlogMapper">
    <insert id="">
        insert into t_car(id,car_num,brand,guide_price,produce_time,car_type)
        values (null,1003,"面包车",13.00,"2020-10-13","飞行汽车")
    </insert>
</mapper>
  1. 在xxxMapper中编写sql代码(在3中已完成)

  2. 把xxxMapper.txt文件路径放入mybatis-config.txt中(在2中已完成)

<mappers>
        <mapper resource="CarMapper.xml"/>
</mappers>

2.3 MyBatis中的事务

在mybatis-config.xml中有一行为

<transactionManager type="JDBC"/>

type类型可以写成两种,一种是JDBC另一种是MANAGED(不区分大小写)

  • JDBC:交给JDBC处理事务(默认false,表示开启事务,需要手动提交)
  • MANAGED:有用到spring框架时设置为此,表交给框架处理事务,如果没有用到框架设置为此类型,则没有人处理事务,会自动提交

注意事项:

  • SqlSessionFactory.openSession()默认开启事务

2.4 编写MyBatis代码

   SqlSession sqlSession = null;
   try 
       SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
       SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(Resources.getResourceAsReader("mybatis-config.xml"));
       sqlSession = sqlSessionFactory.openSession();
       int count = sqlSession.insert("insertCar");
       System.out.println("新增了记录"+count);
       //提交事务
       sqlSession.commit();

    catch (Exception e) 
       if (sqlSession != null) 
           sqlSession.rollback();
       
       e.printStackTrace();
   finally 
       if (sqlSession != null) 
           sqlSession.close();
       
   

2.5 在MyBatis中引入JUnit

在maven中添加junit依赖

        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.13.2</version>
            <scope>test</scope>
        </dependency>

新建test包,以及创建CarMapperTest类

在新建的类中编写MyBatis代码


public class CarMapperTest 
    @Test
    public void insertCar()
        SqlSession sqlSession = null;
        try 
            SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
            SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(Resources.getResourceAsReader("mybatis-config.xml"));
            sqlSession = sqlSessionFactory.openSession();
            int count = sqlSession.insert("insertCar");
            System.out.println("新增了记录"+count);
            //提交事务
            sqlSession.commit();

         catch (Exception e) 
            if (sqlSession != null) 
                sqlSession.rollback();
            
            e.printStackTrace();
        finally 
            if (sqlSession != null) 
                sqlSession.close();
            
        
    

运行,测试一下,绿色就是没问题

junit小知识点:

  • 断言测试方法:Assert.assertEquals(期望值,实际值);

2.6 MyBatis集成日志组件

  • SLF4J沙拉疯):logback就是继承沙拉疯实现的
  • LOG4J
  • LOG4J2
  • STDOUT_LOGGING:MyBatis内部实现的日志组件,

logback、log4j、log4j2是同一个作者编写的

若使用STDOUT_LOGGING,需要在mybatis-config.xml里添加配置文件
注意:settings标签必须添加在configuration下面

<configuration>
    <settings>
        <setting name="logImpl" value="STDOUT_LOGGING"/>
    </settings>
</configuration>

这边不使用STDOUT_LOGGING日志组件,我们使用最常用的logback组件
配置步骤:

  1. 在maven中添加logback的依赖
        <dependency>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-classic</artifactId>
            <version>1.2.11</version>
            <scope>test</scope>
        </dependency>
  1. 在mybatis-config.xml中删除日志设置(除了STDOUT_LOGGING自带日志组件外,其他组件不需要写日志设置)
<!-- 删除这些 -->
    <settings>
        <setting name="logImpl" value="STDOUT_LOGGING"/>
    </settings>
  1. 写配置文件(名字必须为logback.xml或logback-test.xml)
    必须放在resources目录下
<?xml version="1.0" encoding="UTF-8"?>

<!-- 配置文件修改时重新加载,默认true -->
<configuration debug="false">

    <!-- 控制台输出 -->
    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder" charset="UTF-8">
            <!-- 输出日志记录格式 -->
            <pattern>[%thread] %-5level %logger50 - %msg%n</pattern>
        </encoder>
    </appender>
    
<!--    mybatis log configure-->
    <logger name="com.apache.ibatis" level="TRACE"/>
    <logger name="java.sql.Connection" level="DEBUG"/>
    <logger name="java.sql.Statement" level="DEBUG"/>
    <logger name="java.sql.PreparedStatement" level="DEBUG"/>
    

    <!-- 日志输出级别,LOGBACK日志级别包括五个:TRACE < DEBUG < INFO < WARN < ERROR-->
    <root level="DEBUG">
        <appender-ref ref="STDOUT"/>
        <appender-ref ref="FILE"/>
    </root>
</configuration>

  1. 运行测试

2.7 MyBatis工具类的编写

在编写代码中,每次都通过SqlSessionFactoryBuilder三步骤获取session太麻烦,我们编写一个工具类get会比较方便点

  1. 新建类utils.SqlSessionUtil
  2. 编写代码
public class SqlSessionUtilTest 

    /**
     * 测试工具类
     */
    @Test
    public void openSessionTest()
        SqlSession session = SqlSessionUtil.openSession();
        int count = session.insert("insertCar");
        System.out.println(count);
        session.commit();
        
        session.close();
    

  1. 运行测试(数据库正常添加,完成)

三、使用MyBatis完成CRUD

3.1 实现Insert新增

1.1 MyBatis中完成Map集合传参

第一个入门程序已完成,现在我们来做MyBatis的CRUD操作
入门程序有个问题:实战的时候新增数据表行数据不可能是固定值
回顾:

<mapper namespace="org.mybatis.example.BlogMapper">
    <insert id="insertCar">
        insert into t_car(id,car_num,brand,guide_price,produce_time,car_type)
        values (null,1003,"面包车",13.00,"2020-10-13","飞行汽车")
    </insert>
</mapper>
  1. 继续完善这个程序,新建一个模块叫CRUD,如图,把模块1的一些文件拷贝过来,maven依赖引用
  2. 修改CarMapper.xml文件,加上占位符
    在MyBatis中占位符为#,对应JDBC的?
    <insert id="insertCar">
        insert into t_car(id,car_num,brand,guide_price,produce_time,car_type)
        values (null,#,#,#,#,#)
    </insert>
  1. 编写测试代码
public class CarMapperTest 
    @Test
    public void insertCar()
        SqlSession session = SqlSessionUtil.openSession();
        Map<String,Object> map = new HashMap<>();
        map.put("carNum","1004");
        map.put("brand","比亚迪汉");
        map.put("guidePrice",160.00);
        map.put("produceTime","2022-06-08");
        map.put("carType","新能源汽车");

        int count= session.insert("insertCar", map);
        System.out.println("新增的条目:"+count);
        session.commit();

        session.close();
    

  1. 修改mapper文件中的占位符#(大括号中间填入map.get(key)里面的key)
<mapper namespace="org.mybatis.example.BlogMapper">
    <insert id="insertCar">
        insert into t_car(id,car_num,brand,guide_price,produce_time,car_type)
        values (null,#carNum,#brand,#guidePrice,#produceTime,#carType)
    </insert>
</mapper>
  1. 测试,完成

1.2 MyBatis中通过POJO类完成传参

  1. 新建POJO包、类(pojo.Car)

public class Car 
    private Long id;
    private String carNum;
    private String brand;
    private Double guidePrice;
    private String produceTime;
    private String carType;
    //此处忽略构造方法、getting setting方法
    .....

  1. 编写测试代码
    @Test
    public void insertCar()
        SqlSession session = SqlSessionUtil.openSession();
        
        Car car = new Car(null,"1005","比亚迪秦",30.0,"2020-10-20","新能源");
        
        int count= session.insert("insertCar", car);
        System.out.println("新增的条目:"+count);
        session.commit();

        session.close();
    
  1. 编辑mapper文件
<mapper namespace="org.mybatis.example.BlogMapper">
    <insert id="insertCar">
        insert into t_car(id,car_num,brand,guide_price,produce_time,car_type)
        values (null,#carNum,#brand,#guidePrice,#produceTime,#carType)
    </insert>
</mapper>
  1. 运行测试方法,总结:
    mapper文件中填写的#carType),MyBatis会通过反射机制查找getCarType()方法得到值

3.3 实现Delete删除

  1. 新增Mapper删除
    <delete id="deleteById">
        delete from t_car where id = #id
    </delete>
  1. 编写测试方法
    @Test
    public void deleteById()
        SqlSession session = SqlSessionUtil.openSession();
        session.delete("deleteById",17);
        session

跟老杜从零入门MyBatis到架构思维使用MyBatis完成CRUD- insert(Create)

使用MyBatis完成CRUD

配合视频教程观看,更易学习理解,课程讲解从Mybatis的一些核心要点与实战中的运用,一直过渡到MyBaits源码,由表及里的代入架构思维。一步一案例,一码一实操。从简单到深入,从实战到源码,MyBatis重点、难点、考点一网打尽。


●准备工作

○创建module(Maven的普通Java模块):mybatis-002-crud

○pom.xml

■打包方式jar

■依赖:

●mybatis依赖

●mysql驱动依赖

●junit依赖

●logback依赖

○mybatis-config.xml放在类的根路径下

○CarMapper.xml放在类的根路径下

○logback.xml放在类的根路径下

○提供com.powernode.mybatis.utils.SqlSessionUtil工具类

○创建测试用例:com.powernode.mybatis.CarMapperTest

1. insert(Create)

分析以下SQL映射文件中SQL语句存在的问题

<?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先随便写-->
<mapper namespace="car">
<insert id="insertCar">
insert into t_car(car_num,brand,guide_price,produce_time,car_type) values(103, 奔驰E300L, 50.3, 2022-01-01, 燃油车)
</insert>
</mapper>

跟老杜从零入门MyBatis到架构思维(三)使用MyBatis完成CRUD-

存在的问题是:SQL语句中的值不应该写死,值应该是用户提供的。之前的JDBC代码是这样写的:

// JDBC中使用 ? 作为占位符。那么MyBatis中会使用什么作为占位符呢?
String sql = "insert into t_car(car_num,brand,guide_price,produce_time,car_type) values(?,?,?,?,?)";
// ......
// 给 ? 传值。那么MyBatis中应该怎么传值呢?
ps.setString(1,"103");
ps.setString(2,"奔驰E300L");
ps.setDouble(3,50.3);
ps.setString(4,"2022-01-01");
ps.setString(5,"燃油车");

跟老杜从零入门MyBatis到架构思维(三)使用MyBatis完成CRUD-

在MyBatis中可以这样做:

在Java程序中,将数据放到Map集合中

在sql语句中使用 #map集合的key 来完成传值,# 等同于JDBC中的 ? ,#就是占位符

Java程序这样写:

package com.powernode.mybatis;

import com.powernode.mybatis.utils.SqlSessionUtil;
import org.apache.ibatis.session.SqlSession;
import org.junit.Test;

import java.util.HashMap;
import java.util.Map;

/**
* 测试MyBatis的CRUD
* @author 老杜
* @version 1.0
* @since 1.0
*/
public class CarMapperTest
@Test
public void testInsertCar()
// 准备数据
Map<String, Object> map = new HashMap<>();
map.put("k1", "103");
map.put("k2", "奔驰E300L");
map.put("k3", 50.3);
map.put("k4", "2020-10-01");
map.put("k5", "燃油车");
// 获取SqlSession对象
SqlSession sqlSession = SqlSessionUtil.openSession();
// 执行SQL语句(使用map集合给sql语句传递数据)
int count = sqlSession.insert("insertCar", map);
System.out.println("插入了几条记录:" + count);

跟老杜从零入门MyBatis到架构思维(三)使用MyBatis完成CRUD-

SQL语句这样写:

<?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先随便写-->
<mapper namespace="car">
<insert id="insertCar">
insert into t_car(car_num,brand,guide_price,produce_time,car_type) values(#k1,#k2,#k3,#k4,#k5)
</insert>
</mapper>

跟老杜从零入门MyBatis到架构思维(三)使用MyBatis完成CRUD-

# 的里面必须填写map集合的key,不能随便写。运行测试程序,查看数据库:

跟老杜从零入门MyBatis到架构思维(三)使用MyBatis完成CRUD-

如果#里写的是map集合中不存在的key会有什么问题?

<?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="car">
<insert id="insertCar">
insert into t_car(car_num,brand,guide_price,produce_time,car_type) values(#kk,#k2,#k3,#k4,#k5)
</insert>
</mapper>

跟老杜从零入门MyBatis到架构思维(三)使用MyBatis完成CRUD-运行程序:

跟老杜从零入门MyBatis到架构思维(三)使用MyBatis完成CRUD-


 

跟老杜从零入门MyBatis到架构思维(三)使用MyBatis完成CRUD-


通过测试,看到程序并没有报错。正常执行。不过 #kk 的写法导致无法获取到map集合中的数据,最终导致数据库表car_num插入了NULL。

在以上sql语句中,可以看到#k1 #k2 #k3 #k4 #k5的可读性太差,为了增强可读性,我们可以将Java程序做如下修改:

Map<String, Object> map = new HashMap<>();
// 让key的可读性增强
map.put("carNum", "103");
map.put("brand", "奔驰E300L");
map.put("guidePrice", 50.3);
map.put("produceTime", "2020-10-01");
map.put("carType", "燃油车");

跟老杜从零入门MyBatis到架构思维(三)使用MyBatis完成CRUD-

SQL语句做如下修改,这样可以增强程序的可读性:

<?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="car">
<insert id="insertCar">
insert into t_car(car_num,brand,guide_price,produce_time,car_type) values(#carNum,#brand,#guidePrice,#produceTime,#carType)
</insert>
</mapper>

跟老杜从零入门MyBatis到架构思维(三)使用MyBatis完成CRUD-

运行程序,查看数据库表:

跟老杜从零入门MyBatis到架构思维(三)使用MyBatis完成CRUD-


使用Map集合可以传参,那使用pojo(简单普通的java对象)可以完成传参吗?测试一下:

●第一步:定义一个pojo类Car,提供相关属性。

package com.powernode.mybatis.pojo;

/**
* POJOs,简单普通的Java对象。封装数据用的。
* @author 老杜
* @version 1.0
* @since 1.0
*/
public class Car
private Long id;
private String carNum;
private String brand;
private Double guidePrice;
private String produceTime;
private String carType;

@Override
public String toString()
return "Car" +
"id=" + id +
", carNum=" + carNum + \\ +
", brand=" + brand + \\ +
", guidePrice=" + guidePrice +
", produceTime=" + produceTime + \\ +
", carType=" + carType + \\ +
;


public Car()


public Car(Long id, String carNum, String brand, Double guidePrice, String produceTime, String carType)
this.id = id;
this.carNum = carNum;
this.brand = brand;
this.guidePrice = guidePrice;
this.produceTime = produceTime;
this.carType = carType;


public Long getId()
return id;


public void setId(Long id)
this.id = id;


public String getCarNum()
return carNum;


public void setCarNum(String carNum)
this.carNum = carNum;


public String getBrand()
return brand;


public void setBrand(String brand)
this.brand = brand;


public Double getGuidePrice()
return guidePrice;


public void setGuidePrice(Double guidePrice)
this.guidePrice = guidePrice;


public String getProduceTime()
return produceTime;


public void setProduceTime(String produceTime)
this.produceTime = produceTime;


public String getCarType()
return carType;


public void setCarType(String carType)
this.carType = carType;

跟老杜从零入门MyBatis到架构思维(三)使用MyBatis完成CRUD-

●第二步:Java程序

@Test
public void testInsertCarByPOJO()
// 创建POJO,封装数据
Car car = new Car();
car.setCarNum("103");
car.setBrand("奔驰C200");
car.setGuidePrice(33.23);
car.setProduceTime("2020-10-11");
car.setCarType("燃油车");
// 获取SqlSession对象
SqlSession sqlSession = SqlSessionUtil.openSession();
// 执行SQL,传数据
int count = sqlSession.insert("insertCarByPOJO", car);
System.out.println("插入了几条记录" + count);

跟老杜从零入门MyBatis到架构思维(三)使用MyBatis完成CRUD-

●第三步:SQL语句

<insert id="insertCarByPOJO">
<!--# 里写的是POJO的属性名-->
insert into t_car(car_num,brand,guide_price,produce_time,car_type) values(#carNum,#brand,#guidePrice,#produceTime,#carType)
</insert>

跟老杜从零入门MyBatis到架构思维(三)使用MyBatis完成CRUD-

●运行程序,查看数据库表:

跟老杜从零入门MyBatis到架构思维(三)使用MyBatis完成CRUD-

# 里写的是POJO的属性名,如果写成其他的会有问题吗?

<insert id="insertCarByPOJO">
insert into t_car(car_num,brand,guide_price,produce_time,car_type) values(#a,#brand,#guidePrice,#produceTime,#carType)
</insert>

跟老杜从零入门MyBatis到架构思维(三)使用MyBatis完成CRUD-运行程序,出现了以下异常:

跟老杜从零入门MyBatis到架构思维(三)使用MyBatis完成CRUD-


错误信息中描述:在Car类中没有找到a属性的getter方法。

修改POJO类Car的代码,只将getCarNum()方法名修改为getA(),其他代码不变,如下:

跟老杜从零入门MyBatis到架构思维(三)使用MyBatis完成CRUD-

 再运行程序,查看数据库表中数据:

跟老杜从零入门MyBatis到架构思维(三)使用MyBatis完成CRUD-

经过测试得出结论:

如果采用map集合传参,# 里写的是map集合的key,如果key不存在不会报错,数据库表中会插入NULL。

如果采用POJO传参,# 里写的是get方法的方法名去掉get之后将剩下的单词首字母变小写(例如:getAge对应的是#age,getUserName对应的是#userName),如果这样的get方法不存在会报错。

注意:其实传参数的时候有一个属性parameterType,这个属性用来指定传参的数据类型,不过这个属性是可以省略的

<insert id="insertCar" parameterType="java.util.Map">
insert into t_car(car_num,brand,guide_price,produce_time,car_type) values(#carNum,#brand,#guidePrice,#produceTime,#carType)
</insert>

<insert id="insertCarByPOJO" parameterType="com.powernode.mybatis.pojo.Car">
insert into t_car(car_num,brand,guide_price,produce_time,car_type) values(#carNum,#brand,#guidePrice,#produceTime,#carType)
</insert>

跟老杜从零入门MyBatis到架构思维(三)使用MyBatis完成CRUD-

 

 

 


以上是关于SSM框架专题-MyBatis框架从零入门老杜版笔记(上)的主要内容,如果未能解决你的问题,请参考以下文章

跟着老杜学MyBatis+第1天+MyBatis概述

跟老杜从零入门MyBatis到架构思维使用MyBatis完成CRUD- insert(Create)

跟着老杜学MyBatis+第2天+MyBatis入门程序

跟着老杜学MyBatis+第2天+MyBatis入门程序

跟着老杜学MyBatis+第2天+MyBatis入门程序

SSM框架搭建教程(从零开始,图文结合)