MyBatis-01-⼊⻔

MyBatis入门

⼀、MyBatis概述

1.1 框架

在⽂献中看到的framework被翻译为框架Java常⽤框架:
SSM三⼤框架:Spring + SpringMVC + MyBatis
SpringBoot
SpringCloud
框架其实就是对通⽤代码的封装,提前写好了⼀堆接⼝和类,我们可以在做项⽬的时候直接引⼊这些接⼝和类(引⼊框架),基于这些现有的接⼝和类进⾏开发,可以⼤⼤提⾼开发效率。框架⼀般都以jar包的形式存在。(jar包中有class⽂件以及各种配置⽂件等。)

1.2 三层架构

在这里插入图片描述
表现层(UI):直接跟前端打交互(⼀是接收前端ajax请求,⼆是返回json数据给前端)
业务逻辑层(BLL):⼀是处理表现层转发过来的前端请求(也就是具体业务),⼆是将从持久层获取的数据返回到表现层。
数据访问层(DAL):直接操作数据库完成CRUD,并将获得的数据返回到上⼀层(也就是业务逻辑层)。
Java持久层框架:
MyBatis
Hibernate(实现了JPA规范)
Spring Data(实现了JPA规范)

1.3 JDBC不⾜

示例代码1:

// ......
// sql语句写死在java程序中
String sql = "insert into t_user(id,idCard,username,password,birth,gender,
email,city,street,zipcode,phone,grade) values(?,?,?,?,?,?,?,?,?,?,?,?)";
PreparedStatement ps = conn.prepareStatement(sql);
// 繁琐的赋值:思考⼀下,这种有规律的代码能不能通过反射机制来做⾃动化。
ps.setString(1, "1");
ps.setString(2, "123456789");
ps.setString(3, "zhangsan");
ps.setString(4, "123456");
ps.setString(5, "1980-10-11");
ps.setString(6, "男");
ps.setString(7, "zhangsan@126.com");
ps.setString(8, "北京");
ps.setString(9, "⼤兴区凉⽔河⼆街");
ps.setString(10, "1000000");
ps.setString(11, "16398574152");
ps.setString(12, "A");
// 执⾏SQL
int count = ps.executeUpdate();
// ......

// ......
// sql语句写死在java程序中
String sql = "select id,idCard,username,password,birth,gender,email,city,s
treet,zipcode,phone,grade from t_user";
PreparedStatement ps = conn.prepareStatement(sql);
ResultSet rs = ps.executeQuery();
List<User> userList = new ArrayList<>();
// 思考以下循环中的所有代码是否可以使⽤反射进⾏⾃动化封装。
while(rs.next()){
 // 获取数据
 String id = rs.getString("id");
 String idCard = rs.getString("idCard");
 String username = rs.getString("username");
 String password = rs.getString("password");
 String birth = rs.getString("birth");
 String gender = rs.getString("gender");
 String email = rs.getString("email");
 String city = rs.getString("city");
 String street = rs.getString("street");
 String zipcode = rs.getString("zipcode");
 String phone = rs.getString("phone");
 String grade = rs.getString("grade");
 // 创建对象
 User user = new User();
 // 给对象属性赋值
 user.setId(id);
 user.setIdCard(idCard);
 user.setUsername(username);
 user.setPassword(password);
 user.setBirth(birth);
 user.setGender(gender);
 user.setEmail(email);
 user.setCity(city);
 user.setStreet(street);
 user.setZipcode(zipcode);
 user.setPhone(phone);
 user.setGrade(grade);
 // 添加到集合
 userList.add(user);
}
// .....
JDBC不⾜:

SQL语句写死在Java程序中,不灵活。改SQL的话就要改Java代码。违背开闭原则OCP。

1.4 了解MyBatis

MyBatis本质上就是对JDBC的封装,通过MyBatis完成CRUD。MyBatis在三层架构中负责持久层的,属于持久层框架。
MyBatis本是apache的⼀个开源项⽬iBatis,2010年这个项⽬由apache software foundation迁移到了google code,并且改名为MyBatis。2013年11⽉迁移到Github。iBATIS⼀词来源于“internet”和“abatis”的组合,是⼀个基于Java的持久层框架。iBATIS提供的持久层框架包括SQL Maps和Data Access Objects(DAOs)。打开mybatis代码可以看到它的包结构中包含:ibatis

ORM:对象关系映射

O(Object):Java虚拟机中的Java对象
R(Relational):关系型数据库
M(Mapping):将Java虚拟机中的Java对象映射到数据库表中⼀⾏记录,或是将数据库表中⼀⾏记录映射成Java虚拟机中的⼀个Java对象。
ORM图示


在这里插入图片描述
MyBatis属于半⾃动化ORM框架。
Hibernate属于全⾃动化的ORM框架。

MyBatis框架特点:

⽀持定制化 SQL、存储过程、基本映射以及⾼级映射
避免了⼏乎所有的 JDBC 代码中⼿动设置参数以及获取结果集
⽀持XML开发,也⽀持注解式开发。【为了保证sql语句的灵活,所以mybatis⼤部分是采⽤XML⽅式开发。】
将接⼝和 Java 的 POJOs(Plain Ordinary Java Object,简单普通的Java对象)映射成数据库中的记录
体积⼩好学:两个jar包,两个XML配置⽂件。
完全做到sql解耦合。
提供了基本映射标签。
提供了⾼级映射标签。
提供了XML标签,⽀持动态SQL的编写。

2.3 MyBatis⼊⻔程序开发步骤

创建数据库表

CREATE TABLE `my_batis_car` (
  `id` bigint(20) DEFAULT NULL,
  `brand` varchar(100) DEFAULT NULL comment '品牌',
  `car_num` varchar(64) DEFAULT NULL  comment '汽⻋编号',
  `guide_price` decimal(12,2) DEFAULT NULL COMMENT '⼚家指导价【decimal类型,专⻔为财务数据准备的类型】',
  `produce_time` datetime DEFAULT NULL  comment '生产日期',
  `car_type` varchar(64) DEFAULT NULL  comment '汽⻋类型(燃油⻋、电⻋、氢能源)【varchar】'

) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3;

创建Project:建议创建Empty Project,设置Java版本以及编译版本等。

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

创建Module:普通的Maven Java模块
在这里插入图片描述
步骤1:打包⽅式:jar(不需要war,因为mybatis封装的是jdbc。)

 <groupId>com.mybaties.demo</groupId>
    <artifactId>mybaties-demo-01</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>jar</packaging>

步骤2:引⼊依赖(mybatis依赖 + mysql驱动依赖)

 <!--mybatis核⼼依赖-->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.5.10</version>
        </dependency>
        <!--mysql驱动依赖-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.30</version>
        </dependency>

步骤3:在resources根⽬录下新建mybatis-config.xml配置⽂件(可以参考mybatis⼿册拷⻉)

<?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/xuexi"/>
                <property name="username" value="root"/>
                <property name="password" value="root"/>
            </dataSource>
        </environment>
    </environments>
    <mappers>
        <!--sql映射⽂件创建好之后,需要将该⽂件路径配置到这⾥-->
        <mapper resource=""/>
    </mappers>
</configuration>

注意1:mybatis核⼼配置⽂件的⽂件名不⼀定是mybatis-config.xml,可以是其它名字。
注意2:mybatis核⼼配置⽂件存放的位置也可以随意。这⾥选择放在resources根下,相当于放到了类的根路径下。
● 步骤4:在resources根⽬录下新建CarMapper.xml配置⽂件(可以参考mybatis⼿册拷⻉)

<?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 sql:保存⼀个汽⻋信息-->
    <insert id="insertCar">
        insert into my_batis_car
            (id,car_num,brand,guide_price,produce_time,car_type)
        values
            (null,'123','联想L7',40.30,'2023-10-05','氢能源')
    </insert>
</mapper>

注意1:sql语句最后结尾可以不写“;”
注意2:CarMapper.xml⽂件的名字不是固定的。可以使⽤其它名字。
注意3:CarMapper.xml⽂件的位置也是随意的。这⾥选择放在resources根下,相当于放到了类的根路径下。
注意4:将CarMapper.xml⽂件路径配置到mybatis-config.xml:

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

步骤5:编写MyBatisIntroductionTest代码

    public static Integer insertData() {
//          1.创建SqlSessionFactoryBuilder对象
        SqlSessionFactoryBuilder sessionFactoryBuilder = new SqlSessionFactoryBuilder();

//          2.创建SqlSessionFactor对象
        InputStream resourceAsStream = Thread.currentThread().getContextClassLoader().getResourceAsStream("mybatis-config.xml");

        SqlSessionFactory sqlSessionFactory = sessionFactoryBuilder.build(resourceAsStream);

//        3.获取SqlSession对象
        SqlSession sqlSession = sqlSessionFactory.openSession();

//        4.执行Sql
        int insertCarOne = sqlSession.insert("insertCarOne");
               /*
                * insertCarOne 为sql ID
                *
                * */

        // 5. 提交(mybatis默认采⽤的事务管理器是JDBC,默认是不提交的,需要⼿动提交

         sqlSession.commit();

         // 6. 关闭资源
        sqlSession.close();

        return insertCarOne;
    }

2.4 关于MyBatis核⼼配置⽂件的名字和路径详解

核⼼配置⽂件的名字是随意的,因为以下的代码:

// ⽂件名是出现在程序中的,⽂件名如果修改了,对应这⾥的java程序也改⼀下就⾏了。
InputStream is = Thread.currentThread().getContextClassLoader().getResource
AsStream("mybatis-config.xml");

核⼼配置⽂件必须放到resources下吗?放到D盘根⽬录下,可以吗?测试⼀下:
将mybatis-config.xml⽂件拷⻉⼀份放到D盘根下,然后编写以下程序:

public class MyBatisConfigFilePath {
 public static void main(String[] args) throws Exception{
 // 1. 创建SqlSessionFactoryBuilder对象
 SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSession
FactoryBuilder();
 // 2. 创建SqlSessionFactory对象
 // 这只是⼀个输⼊流,可以⾃⼰new。
 InputStream is = new FileInputStream("D:/mybatis-config.xml");
 SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.bui
ld(is);
 // 3. 创建SqlSession对象
 SqlSession sqlSession = sqlSessionFactory.openSession();
 // 4. 执⾏sql
 int count = sqlSession.insert("insertCar");
 System.out.println("插⼊⼏条数据:" + count);
 // 5. 提交(mybatis默认采⽤的事务管理器是JDBC,默认是不提交的,需要⼿动提
交。)
 sqlSession.commit();
 // 6. 关闭资源(只关闭是不会提交的)
 sqlSession.close();
 }
}

以上程序运⾏后,看到数据库表t_car中⼜新增⼀条数据,如下(成功了):

经过测试说明mybatis核⼼配置⽂件的名字是随意的,存放路径也是随意的。
虽然mybatis核⼼配置⽂件的名字不是固定的,但通常该⽂件的名字叫做:mybatis-config.xml
虽然mybatis核⼼配置⽂件的路径不是固定的,但通常该⽂件会存放到类路径当中,这样让项⽬的移植更
加健壮。

在mybatis中提供了⼀个类:Resources【org.apache.ibatis.io.Resources】,该类可以从类路径当
中获取资源,我们通常使⽤它来获取输⼊流InputStream,代码如下

// 这种⽅式只能从类路径当中获取资源,也就是说mybatis-config.xml⽂件需要在类路径下。
InputStream is = Resources.getResourceAsStream("mybatis-config.xml");

优化代码

 public static Integer insertData() {

    SqlSession sqlSession = null;

    try {

      //          1.创建SqlSessionFactoryBuilder对象
      SqlSessionFactoryBuilder sessionFactoryBuilder = new SqlSessionFactoryBuilder();

      //          2.创建SqlSessionFactor对象
      InputStream resourceAsStream =
          Thread.currentThread().getContextClassLoader().getResourceAsStream("mybatis-config.xml");

      SqlSessionFactory sqlSessionFactory = sessionFactoryBuilder.build(resourceAsStream);

      //        3.获取SqlSession对象
      sqlSession = sqlSessionFactory.openSession();

      //        4.执行Sql
      int insertCarOne = sqlSession.insert("insertCarOne");
      /*
       * insertCarOne 为sql ID
       *
       * */

      // 5. 提交(mybatis默认采⽤的事务管理器是JDBC,默认是不提交的,需要⼿动提交

      sqlSession.commit();

      return insertCarOne;

    } catch (Exception e) {
      e.printStackTrace();
      return 0;

    } finally {
      // 6. 关闭资源
      sqlSession.close();
    }
  }
2.6 引⼊JUnit

Unit是专⻔做单元测试的组件。
在实际开发中,单元测试⼀般是由我们Java程序员来完成的。
我们要对我们⾃⼰写的每⼀个业务⽅法负责任,要保证每个业务⽅法在进⾏测试的时候都能通过。
测试的过程中涉及到两个概念:
期望值
实际值
期望值和实际值相同表示测试通过,期望值和实际值不同则单元测试执⾏时会报错。
这⾥引⼊JUnit是为了代替main⽅法。
使⽤JUnit步骤:
第⼀步:引⼊依赖

<!-- junit依赖 -->
<dependency>
 <groupId>junit</groupId>
 <artifactId>junit</artifactId>
 <version>4.13.2</version>
 <scope>test</scope>
</dependency>

第⼆步:编写单元测试类【测试⽤例】,测试⽤例中每⼀个测试⽅法上使⽤@Test注解进⾏标

测试⽤例的名字以及每个测试⽅法的定义都是有规范的:
测试⽤例的名字:XxxTest
测试⽅法声明格式:public void test业务⽅法名(){}

// 测试⽤例
public class CarMapperTest{

 // 测试⽅法
 @Test
 public void testInsert(){}

 @Test
 public void testUpdate(){}

}

第三步:可以在类上执⾏,也可以在⽅法上执⾏
在类上执⾏时,该类中所有的测试⽅法都会执⾏。
在⽅法上执⾏时,只执⾏当前的测试⽅法。
编写⼀个测试⽤例,来测试insertCar业务

2.7 引⼊⽇志框架logback

引⼊⽇志框架的⽬的是为了看清楚mybatis执⾏的具体sql。
启⽤标准⽇志组件,只需要在mybatis-config.xml⽂件中添加以下配置:【可参考mybatis⼿册】

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

标准⽇志也可以⽤,但是配置不够灵活,可以集成其他的⽇志组件,例如:log4j,logback等。
logback是⽬前⽇志框架中性能较好的,较流⾏的,所以我们选它。
引⼊logback的步骤:
第⼀步:引⼊logback相关依赖

<!--引入logback的依赖,这个日志框架实现了slf4j规范-->
        <dependency>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-classic</artifactId>
            <version>1.2.11</version>
        </dependency>

第⼆步:引⼊logback相关配置⽂件(⽂件名叫做logback.xml或logback-test.xml,放到类路径当中)

<?xml version="1.0" encoding="UTF-8"?>
<configuration debug="false">
    <!--定义⽇志⽂件的存储地址-->
    <property name="LOG_HOME" value="/home"/>
    <!-- 控制台输出 -->
    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
            <!--格式化输出:%d表示⽇期,%thread表示线程名,%-5level:级别从左显示5
           个字符宽度%msg:⽇志消息,%n是换⾏符-->
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logge
                r{50} - %msg%n</pattern>
        </encoder>
    </appender>
    <!-- 按照每天⽣成⽇志⽂件 -->
    <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <!--⽇志⽂件输出的⽂件名-->
            <FileNamePattern>${LOG_HOME}/TestWeb.log.%d{yyyy-MM-dd}.log</FileNamePattern>
            <!--⽇志⽂件保留天数-->
            <MaxHistory>30</MaxHistory>
        </rollingPolicy>
        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncode
r">
            <!--格式化输出:%d表示⽇期,%thread表示线程名,%-5level:级别从左显示5
           个字符宽度%msg:⽇志消息,%n是换⾏符-->
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logge
                r{50} - %msg%n</pattern>
        </encoder>
        <!--⽇志⽂件最⼤的⼤⼩-->
        <triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
            <MaxFileSize>100MB</MaxFileSize>
        </triggeringPolicy>
    </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>

再次执⾏单元测试⽅法testInsertCar,查看控制台是否有sql语句输出

2.8 MyBatis⼯具类SqlSessionUtil的封装

每⼀次获取SqlSession对象代码太繁琐,封装⼀个⼯具类

package com.mybaties.demo.util;

import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

public class SqlSessionUtil {

    private static SqlSessionFactory sqlSessionFactory;
    /**
     * 类加载时初始化sqlSessionFactory对象
     */
    static {
        try {
            SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
            sqlSessionFactory = sqlSessionFactoryBuilder.build(Resources.getResourceAsStream("mybatis-config.xml"));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    /**
     * 每调⽤⼀次openSession()可获取⼀个新的会话,该会话⽀持⾃动提交。
     *
     * @return 新的会话对象
     */
    public static SqlSession openSession() {
        return sqlSessionFactory.openSession(true);
    }

}

使用:

@Test
public void testInsertCar(){
 SqlSession sqlSession = SqlSessionUtil.openSession();
 // 执⾏SQL
 int count = sqlSession.insert("insertCar");
 System.out.println("插⼊了⼏条记录:" + count);
 sqlSession.close();
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值