[Java]Mybatis学习笔记(动力节点老杜)(二)

本文涉及的产品
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS MySQL,高可用系列 2核4GB
简介: [Java]Mybatis学习笔记(动力节点老杜)(二)

引入 Junit

  • Junit 是专⻔做单元测试的组件。
  • 在实际开发中,单元测试⼀般是由我们 Java 程序员来完成的。我们要对我们⾃⼰写的每⼀个业务⽅法负责任,要保证每个业务⽅法在进⾏测试的时候都能通过。
  • 测试的过程中涉及到两个概念:
  • 期望值:执行了这个业务方法之后,你期望的执行结果是什么
  • 实际值:被测试的业务方法的真正执行结果
  • 期望值和实际值相同表示测试通过,期望值和实际值不同则单元测试执⾏时会报错。
  • 这里引⼊ Junit 是为了代替 main ⽅法

第一步:引入依赖

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

第二步:使用 Junit 进行测试

  • 编写单元测试类,对我们的代码进行测试,测试类中的每⼀个测试⽅法上使用@Test注解进⾏标注
  • 关于测试类的一写规范:
  • 测试类的类名:要进行测试的类 + Test
  • 测试类中的测试方法:一般是一个业务方法对应一个测试方式,测试方法的命名为test + 要测试方法的方法名public void testXxxx() {},每个测试方法需要使用@Test注解进行标注,表示该方法是一个单元测试方法
package com.powernode.junit.service;
import org.junit.Assert;
import org.junit.Test;
// 测试类的类名:要进行测试的类 + Test
public class MathServiceTest {
    @Test
    public void testSum(){
        // 单元测试中有两个重要的概念:
        // 一个是:实际值(被测试的业务方法的真正执行结果)
        // 一个是:期望值(执行了这个业务方法之后,你期望的执行结果是多少)
        MathService mathService = new MathService();
        // 获取实际值
        int actual = mathService.sum(1, 2);
        // 期望值
        //int expected = 3;
        int expected = 30;
        // 加断言进行测试,期望值与实际值不一致会报错
        Assert.assertEquals(expected, actual);
    }
    @Test
    public void testSub(){
        MathService mathService = new MathService();
        // 实际值
        int actual = mathService.sub(10, 5);
        // 期望值
        int expected = 5;
        // 添加断言机制,期望值与实际值一致则不会报错
        Assert.assertEquals(expected, actual);
    }
}

关于 MyBatis 集成日志组件

日志组件简述

  • mybatis 常见的集成的日志组件有哪些呢?
  • SLF4J(沙拉风):沙拉风是一个日志标准,其中有一个日志框架叫做logback,它实现了沙拉风规范。
  • LOG4J
  • LOG4J2
  • STDOUT_LOGGING
  • log4j、log4j2、logback都是同一个作者开发的。
  • STDOUT_LOGGING 是标准日志,mybatis 已经实现了这种标准日志,mybatis 框架本身已经实现了这种标准,只要开启即可。

开启 MyBatis 本身的日志功能

  • 在 mybatis-config.xml 文件中使用settings标签进行配置开启。
<settings>
  <setting name="logImpl" value="STDOUT_LOGGING"/>
</settings>
  • 这个标签在编写的时候要注意,它应该出现在 environments 标签之前,注意顺序。
  • 当然,不需要记忆这个顺序,因为有dtd文件进行约束,我们只要参考dtd约束即可,标签的顺序不正确会报错
  • MyBatis 本身自己实现的日志框架也是可以的,可以看到一些信息,比如:连接对象什么时候创建,什么时候关闭,sql语句是怎样的。但是没有详细的日期,线程名字等。
  • 如果想可以看到更加丰富的日志信息,可以集成第三方的log组件。

集成 logback 日志框架。

  • logback日志框架实现了slf4j标准。(沙拉风:日志门面、日志标准)
  • 在MyBatis使用标准日志 STDOUT_LOGGING 之外的其他日志框架,可以不在mybatis的配置文件中指定 MyBatis 所用日志的具体实现,未指定时将会自动查找,只需要引入相应日志框架的依赖以及日志框架的配置文件即可。
  • 第一步:引入logback的依赖。
<!-- 引入logback依赖,logback日志框架实现了slf4j规范 -->
<dependency>
    <groupId>ch.qos.logback</groupId>
    <artifactId>logback-classic</artifactId>
    <version>1.2.11</version>
</dependency>
  • 第二步:引入logback所必须的xml配置文件。
  • 这个配置文件的名字必须叫做:logback.xml或者logback-test.xml,不能是其它的名字。
  • 这个配置文件必须放到类的根路径下,不能是其他位置。
<?xml version="1.0" encoding="UTF-8"?>
<configuration debug="false">
    <!-- 控制台输出 -->
    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
            <!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度%msg:日志消息,%n是换行符-->
            <pattern>[%thread] %-5level %logger{50} - %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>

MyBatis 工具类 SqlSessionUtil 的封装

package cw.mybatis.utils;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import java.io.IOException;
/**
 * Mybatis工具类
 */
public class SqlSessionUtils {
    // 工具类的构造方法一般为私有,防止实例化对象
    // 工具类中的方法都是静态的,可以直接采用类名进行调用,不需要new对象,方便调用
    private SqlSessionUtils() {}
    private static SqlSessionFactory sqlSessionFactory;
    // 类加载时执行
    // SqlSessionUtil工具类在进行第一次加载的时候,解析mybatis-config.xml文件。创建SqlSessionFactory对象。
    // SqlSessionFactory对象:一个SqlSessionFactory对应一个environment,一个environment通常是一个数据库。
    static {
        SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
        try {
            sqlSessionFactory = sqlSessionFactoryBuilder.build(Resources.getResourceAsStream("mybatis-config.xml"));
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
    /**
     * 获取数据库会话对象
     * @return 数据库会话对象
     */
    public static SqlSession openSession() {
        // SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
        // SqlSessionFactory对象:一个SqlSessionFactory对应一个environment,一个environment通常是一个数据库。
        // SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(Resources.getResourceAsStream("mybatis-config.xml"));
        SqlSession sqlSession = sqlSessionFactory.openSession();
        return sqlSession;
    }
}
  • 测试:
package cw.mybatis.test;
import cw.mybatis.utils.SqlSessionUtils;
import org.apache.ibatis.session.SqlSession;
import org.junit.Test;
public class SqlSessionUtilsTest {
    @Test
    public void testOpenSession() {
        SqlSession sqlSession = SqlSessionUtils.openSession();
        int count = sqlSession.insert("insertCar");
        System.out.println(count);
        sqlSession.commit();
        sqlSession.close();
    }
}

使用 MyBatis 完成 CRUD

  • CRUD
  • C: Create 增
  • R: Retrieve 查(检索)
  • U: Update 改
  • D: Delete 删

insert

MyBatis 中 SQL 的编写

<!--namespace先随便写-->
<mapper namespace="car">
    <!-- 在insert标签中写向数据库中插入数据的SQL -->
    <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>
  • 这样写的问题是:插入数据库的值写死到配置文件中的。这个在实际开发中是不存在的。一定是前端的form表单提交过来数据。然后将值传给sql语句。
  • JDBC 的代码的写法
String sql = "insert into t_car(id,car_num,brand,guide_price,produce_time,car_type) values(null,?,?,?,?,?)";
ps.setString(1, xxx);
ps.setString(2, yyy);
....
  • 在JDBC当中占位符采用的是?,在mybatis当中是什么呢?
  • 和?等效的写法是:#{}
  • 在mybatis当中不能使用?占位符,必须使用 #{} 来代替JDBC当中的 ?
  • #{} 和 JDBC当中的 ? 是等效的。
<!--namespace先随便写-->
<mapper namespace="car">
    <insert id="insertCar">
        insert into t_car(car_num,brand,guide_price,produce_time,car_type) 
        values(#{}, #{}, #{}, #{}, #{})
    </insert>
</mapper>

使用Map集合传参

  • java程序中使用Map可以给SQL语句的占位符传值,占位符中写map集合的key,如果key不存在,获取的是null,一般map集合的key起名的时候要见名知意。
<mapper namespace="car">
    <!--insert sql:保存⼀个汽⻋信息-->
    <insert id="insertCar">
        insert into t_car
            (id,car_num,brand,guide_price,produce_time,car_type)
        values
            (null, #{k1}, #{k2}, #{k3}, #{k4}, #{k5})
    </insert>
</mapper>
package cw.mybatis;
import cw.mybatis.utils.SqlSessionUtils;
import org.apache.ibatis.session.SqlSession;
import java.util.HashMap;
import java.util.Map;
public class CarMapperTest {
  @Test
    public void testInsertCar() {
        // 使用map集合进行数据的封装。
        Map<String, Object> map = new HashMap<>();
        map.put("k1", "1111");
        map.put("k2", "比亚迪汉");
        map.put("k3", 10.0);
        map.put("k4", "2020-11-11");
        map.put("k5", "电车");
        // 获取与数据库的会话对象
        SqlSession sqlSession = SqlSessionUtils.openSession();
        // 执行SQL语句
        // insert SQL 使用 insert方法
        // insert方法的参数:
        // 第一个参数:sqlId,从CarMapper.xml文件中复制。
        // 第二个参数:封装数据的对象。
        sqlSession.insert("insertCar", map);
        sqlSession.commit();
        sqlSession.close();
    }
}

使用POJO(简单普通的java对象)传参

  • 第一步:定义一个pojo类Car,提供相关属性
package cw.mybatis.pojo;
/**
 * 封装汽车相关信息的pojo类。普通的java类。
 */
public class Car {
    // 数据库表当中的字段应该和pojo类的属性一一对应。
    // 建议使用包装类,这样可以防止null的问题。
    private Long id;
    private String carNum;
    private String brand;
    private Double guidePrice;
    private String produceTime;
    private String 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;
    }
    @Override
    public String toString() {
        return "Car{" + "id=" + id + ", carNum='" + carNum + '\'' + ", brand='" + brand + '\'' + ", guidePrice=" + guidePrice + ", produceTime='" + produceTime + '\'' + ", carType='" + carType + '\'' + '}';
    }
}
  • 第二步:Java程序
@Test
public void testInsertCarPOJO() {
    // 封装数据
    Car car = new Car(null, "3333", "比亚迪", 30.0, "2020-11-11", "新能源");
    SqlSession sqlSession = SqlSessionUtils.openSession();
    // 执行sql
    sqlSession.insert("insertCar", car);
    sqlSession.commit();
    sqlSession.close();
}
  • 第三步:SQL语句
<mapper namespace="car">
    <!--insert sql:保存⼀个汽⻋信息-->
    <!-- 占位符 #{} 中写POJO的属性名 -->
    <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>

MyBatis 如何获取 POJO 属性值分析
  • 如果把SQL语句写成如下这个德行:
insert into t_car(id,car_num,brand,guide_price,produce_time,car_type)
values(null,#{xyz},#{brand},#{guidePrice},#{produceTime},#{carType})
  • 出现了什么问题呢?
  • There is no getter for property named 'xyz' in 'class com.powernode.mybatis.pojo.Car'
  • mybatis去找:Car类中的getXyz()方法去了。没找到。报错了。
  • 怎么解决的?
  • 可以在Car类中提供一个getXyz()方法。这样问题就解决了。
  • 通过这个测试,得出一个结论:
  • 严格意义上来说:如果使用POJO对象传递值的话,#{}这个大括号中到底写什么?
  • 写的是get方法的方法名去掉get,然后将剩下的单词首字母小写,然后放进去。
  • 例如:getUsername() --> #{username}
  • 例如:getEmail() --> #{email}
  • 也就是说mybatis在底层给?传值的时候,先要获取值,怎么获取的?
  • 调用了pojo对象的get方法。例如:car.getCarNum(),car.getCarType(),car.getBrand()

SQL 语句标签的 parameterType 属性

  • 其实传参数的时候有一个属性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>

delete

  • 需求:根据id删除数据
  • SQL语句
<!-- 当sql语句中的占位符只有一个时,占位符中的内容可以任意写,但是不能不写,一般采用见名知意的命名 -->
<!-- 只有一个占位符时,mybatis可以知道数据填放的位置 -->
<delete id="deleteById">
    delete from t_car where id = #{id}
</delete>
  • java程序
@Test
public void testDeleteById() {
    SqlSession sqlSession = SqlSessionUtils.openSession();
  // 第二个参数会被自动装箱成相应的类型
    sqlSession.delete("deleteById", 10);
    sqlSession.commit();
    sqlSession.close();
}

  • 注意:如果占位符只有一个,那么#{}的大括号里可以随意。但是最好见名知意。

update

  • 需求:根据id修改某条记录。
<update id="updateById">
    update t_car set
        car_num = #{carNum}, brand = #{brand},
        guide_price = #{guidePrice}, produce_time = #{produceTime},
        car_type = #{carType}
    where id = #{id}
</update>
@Test
public void testUpdateById() {
    SqlSession sqlSession = SqlSessionUtils.openSession();
    // 封装数据
    Car car = new Car(4L, "9999", "凯美瑞", 30.3, "1999-11-10", "燃油车");
    int count = sqlSession.update("updateById", car);
    System.out.println(count);
    sqlSession.commit();
    sqlSession.close();
}

select

  • select语句查询会有一个结果集

查一条数据

  • 需求:根据id查询。
  • 查询时需要告诉mybatis查询结果集封装成的java对象类型,select标签中resultType属性,这个属性用来告诉mybatis,查询结果集封装成什么类型的java对象。
  • select标签中resultType通常写的是:全限定类名。
  • 如果表的字段名与相应的java类的属性名不一致可以使用别名为查询语句的字段指定别名,来解决不能为java对象属性赋值的问题
<!-- 
  sql语句中如果表的字段名与相应的java类的属性名不一致需要使用别名为查询语句的字段指定别名,
  否则对应字段的查询为null 
-->
<select id="selectById" resultType="cw.mybatis.pojo.Car">
    select
        id,car_num as carNum,brand,guide_price as guidePrice,
        produce_time as produceTime,
        car_type as carType
    from
        t_car
    where
        id = #{id}
</select>
@Test
public void testSelectById() {
    SqlSession sqlSession = SqlSessionUtils.openSession();
    // 执行DQL语句。查询。根据id查询。返回结果一定是一条。
    // mybatis底层执行了select语句之后,一定会返回一个结果集对象:ResultSet
    // JDBC中叫做ResultSet,接下来就是mybatis应该从ResultSet中取出数据,封装java对象。
    Object car = sqlSession.selectOne("selectById", 1);
    System.out.println(car);
    sqlSession.close();
}

查多条数据

<!-- 
resultType还是指定要封装的结果集的类型。
不是指定List类型,是指定List集合中元素的类型。 
-->
<select id="selectAll" resultType="cw.mybatis.pojo.Car">
    select
        id,car_num as carNum,brand,guide_price as guidePrice,
        produce_time as produceTime,
        car_type as carType
    from
        t_car
</select>
@Test
public void testSelectAll() {
    SqlSession sqlSession = SqlSessionUtils.openSession();
    // selectList方法:mybatis通过这个方法就可以得知你需要一个List集合。
    // 它会自动给你返回一个List集合。
    List<Car> cars = sqlSession.selectList("selectAll");
    cars.forEach(System.out::println);
    sqlSession.close();
}

SQL Mapper 的 namespace

  • 在sql mapper.xml文件当中有一个namespace,这个属性是用来指定命名空间的。用来防止id重复。
  • 当不同的 SQLMapper 映射文件中,存在 sqlId 相同的两个SQL语句,若使用SQL语句时不使用命名空间,则会报错
  • 命名空间的使用 namespace.sqlId (MyBatis中sqlId的完整写法)
  • 实际上,本质上,mybatis中的sqlId的完整写法:namespace.id
  • 创建CarMapper2.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="car2">
    <select id="selectCarAll" resultType="com.powernode.mybatis.pojo.Car">
        select
            id, car_num as carNum, brand, guide_price as guidePrice, produce_time as produceTime, car_type as carType
        from
            t_car
    </select>
</mapper>
  • CarMapper.xml和CarMapper2.xml文件中都有 id=“selectCarAll”
  • 将CarMapper2.xml配置到mybatis-config.xml文件中。
<mappers>
  <mapper resource="CarMapper.xml"/>
  <mapper resource="CarMapper2.xml"/>
</mappers>
  • Java代码
@Test
public void testSelectAll() {
    SqlSession sqlSession = SqlSessionUtils.openSession();
    List<Car> cars = sqlSession.selectList("selectAll");
    cars.forEach(System.out::println);
    sqlSession.close();
}

org.apache.ibatis.exceptions.PersistenceException: 
### Error querying database.  Cause: java.lang.IllegalArgumentException: 
  selectCarAll is ambiguous in Mapped Statements collection (try using the full name including the namespace, or rename one of the entries) 
【翻译】selectCarAll在Mapped Statements集合中不明确(请尝试使用包含名称空间的全名,或重命名其中一个条目)
【大致意思是】selectCarAll重名了,你要么在selectCarAll前添加一个名称空间,要有你改个其它名字。
  • Java代码修改如下:
@Test
public void testSelectAll() {
    SqlSession sqlSession = SqlSessionUtils.openSession();
    // SQL id:namespace.id
    List<Car> cars = sqlSession.selectList("car.selectAll");
    cars.forEach(System.out::println);
    sqlSession.close();
}

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/powernode"/>
                <property name="username" value="root"/>
                <property name="password" value="root"/>
            </dataSource>
        </environment>
    </environments>
    <mappers>
        <mapper resource="CarMapper.xml"/>
        <mapper resource="CarMapper2.xml"/>
    </mappers>
</configuration>
  • configuration:根标签,表示配置信息。
  • environments:环境(多个),以“s”结尾表示复数,也就是说mybatis的环境可以配置多个数据源。
  • default属性:表示默认使用的是哪个环境,default后面填写的是environment的id。default的值只需要和environment的id值一致即可
  • environment:具体的环境配置(主要包括:事务管理器的配置 + 数据源的配置
  • id:给当前环境一个唯一标识,该标识用在environments的default后面,用来指定默认环境的选择。
  • transactionManager:配置事务管理器
  • type属性:指定事务管理器具体使用什么方式,可选值包括两个
  • JDBC:使用JDBC原生的事务管理机制。底层原理:事务开启conn.setAutoCommit(false); …处理业务…事务提交conn.commit();
  • MANAGED:交给其它容器来管理事务,比如WebLogic、JBOSS等。如果没有管理事务的容器,则没有事务。没有事务的含义:只要执行一条DML语句,则提交一次
  • dataSource:指定数据源
  • type属性:用来指定具体使用的数据库连接池的策略,可选值包括三个
  • UNPOOLED:采用传统的获取连接的方式,虽然也实现Javax.sql.DataSource接口,但是并没有使用池的思想。
  • property可以是:
  • driver 这是 JDBC 驱动的 Java 类全限定名。
  • url 这是数据库的 JDBC URL 地址。
  • username 登录数据库的用户名。
  • password 登录数据库的密码。
  • defaultTransactionIsolationLevel 默认的连接事务隔离级别。
  • defaultNetworkTimeout 等待数据库操作完成的默认网络超时时间(单位:毫秒)
  • POOLED:采用传统的javax.sql.DataSource规范中的连接池,mybatis中有针对规范的实现。
  • property可以是(除了包含UNPOOLED中之外):
  • poolMaximumActiveConnections 在任意时间可存在的活动(正在使用)连接数量,默认值:10
  • poolMaximumIdleConnections 任意时间可能存在的空闲连接数。
  • 其它…
  • JNDI:采用服务器提供的JNDI技术实现,来获取DataSource对象,不同的服务器所能拿到DataSource是不一样。如果不是web或者maven的war工程,JNDI是不能使用的。
  • property可以是(最多只包含以下两个属性):
  • initial_context 这个属性用来在 InitialContext 中寻找上下文(即,initialContext.lookup(initial_context))这是个可选属性,如果忽略,那么将会直接从 InitialContext 中寻找 data_source 属性。
  • data_source 这是引用数据源实例位置的上下文路径。提供了 initial_context 配置时会在其返回的上下文中进行查找,没有提供时则直接在 InitialContext 中查找。
  • mappers:在mappers标签中可以配置多个sql映射文件的路径。
  • mapper:配置某个sql映射文件的路径
  • resource属性:使用相对于类路径的资源引用方式
  • url属性:使用完全限定资源定位符(URL)方式

各标签拆分解释说明版

文档类型说明

<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
  • 文档类型说明中的 configuration,是根标签的名称,一个文档只有一个根标签
  • http://mybatis.org/dtd/mybatis-3-config.dtd 是xml文档的dtd约束,约束文档中可以出现什么标签、标签能有什么子标签、标签中可以有什么属性、标签属性可以具有的值以及标签出现的顺序

根标签

<configuration>
  ...
</configuration>
  • configuration:根标签,表示配置信息

properties

  • java.util.Properties类,是一个Map集合,key和value都是String类型
  • property标签中的name属性为key,value属性为value
  • 在properties标签中可以配置很多属性
  • 在properties下面的标签中可以使用property配置的属性值,使用 ${property的name属性} 取出相应的值
<properties>
    <!-- <property name="属性名" value="属性值"/> -->
    <property name="jdbc.driver" value="com.mysql.cj.jdbc.Driver"/>
    <property name="jdbc.url" value="jdbc:mysql://localhost:3306/powernode"/>
    <property name="jdbc.username" value="root"/>
    <property name="jdbc.password" value="root"/>
</properties>
<dataSource type="POOLED">
    <property name="driver" value="${jdbc.driver}"/>
    <property name="url" value="${jdbc.url}"/>
    <property name="username" value="${jdbc.username}"/>
    <property name="password" value="${jdbc.password}"/>
</dataSource>
从指定路径下开始查找配置文件
  • properties中的property可以配置到配置文件中
<!-- resource,从类路径下开始查找资源 -->
<properties resource="jdbc.properties" />
<!-- 从绝对路径当中加载资源 -->
<!-- 绝对路径怎么写?file:///路径 -->
<properties url="file:///d:/jdbc.properties" />

environments

<environments default="powernodeDB">
  ...
</environments>
  • 在 environments 标签中配置数据库环境,可以配置多个数据库环境
  • default 表示默认使用的数据库环境
  • 当你使用mybatis创建SqlSessionFactory对象的时候,没有指定数据库环境的话,默认使用 default 属性指定的数据库环境
environment
  • environments 的子标签,在 environment 标签中配置每一个数据库环境
  • 一般一个数据库会对应一个SqlSessionFactory对象,一个环境environment会对应一个SqlSessionFactory对象,所以一个数据库一般对应一个环境
<!-- 第一个数据库环境 -->
<environment id="powernodeDB">
    <transactionManager type="JDBC"/>
    <dataSource type="POOLED">
        <property name="driver" value="${jdbc.driver}"/>
        <property name="url" value="${jdbc.url}"/>
        <property name="username" value="${jdbc.username}"/>
        <property name="password" value="${jdbc.password}"/>
        <property name="poolMaximumActiveConnections" value="10"/>
        <property name="poolTimeToWait" value="2000"/>
        <property name="poolMaximumCheckoutTime" value="10000"/>
        <property name="poolMaximumIdleConnections" value="5"/>
    </dataSource>
</environment>
<!-- 第二个数据库环境 -->
<environment id="mybatisDB">
    <transactionManager type="JDBC"/>
    <dataSource type="POOLED">
        <property name="driver" value="com.mysql.cj.jdbc.Driver"/>
        <property name="url" value="jdbc:mysql://localhost:3306/mybatis"/>
        <property name="username" value="root"/>
        <property name="password" value="root"/>
    </dataSource>
</environment>


相关实践学习
如何在云端创建MySQL数据库
开始实验后,系统会自动创建一台自建MySQL的 源数据库 ECS 实例和一台 目标数据库 RDS。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助 &nbsp; &nbsp; 相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
2月前
|
Java 数据库连接 Maven
mybatis使用一:springboot整合mybatis、mybatis generator,使用逆向工程生成java代码。
这篇文章介绍了如何在Spring Boot项目中整合MyBatis和MyBatis Generator,使用逆向工程来自动生成Java代码,包括实体类、Mapper文件和Example文件,以提高开发效率。
146 2
mybatis使用一:springboot整合mybatis、mybatis generator,使用逆向工程生成java代码。
|
1月前
|
分布式计算 Java MaxCompute
ODPS MR节点跑graph连通分量计算代码报错java heap space如何解决
任务启动命令:jar -resources odps-graph-connect-family-2.0-SNAPSHOT.jar -classpath ./odps-graph-connect-family-2.0-SNAPSHOT.jar ConnectFamily 若是设置参数该如何设置
|
2月前
|
搜索推荐 Java 数据库连接
Java|在 IDEA 里自动生成 MyBatis 模板代码
基于 MyBatis 开发的项目,新增数据库表以后,总是需要编写对应的 Entity、Mapper 和 Service 等等 Class 的代码,这些都是重复的工作,我们可以想一些办法来自动生成这些代码。
39 6
|
1月前
|
Java 数据库连接 API
Spring 框架的介绍(Java EE 学习笔记02)
Spring是一个由Rod Johnson开发的轻量级Java SE/EE一站式开源框架,旨在解决Java EE应用中的多种问题。它采用非侵入式设计,通过IoC和AOP技术简化了Java应用的开发流程,降低了组件间的耦合度,支持事务管理和多种框架的无缝集成,极大提升了开发效率和代码质量。Spring 5引入了响应式编程等新特性,进一步增强了框架的功能性和灵活性。
47 0
|
2月前
|
分布式计算 资源调度 Hadoop
大数据-01-基础环境搭建 超详细 Hadoop Java 环境变量 3节点云服务器 2C4G XML 集群配置 HDFS Yarn MapRedece
大数据-01-基础环境搭建 超详细 Hadoop Java 环境变量 3节点云服务器 2C4G XML 集群配置 HDFS Yarn MapRedece
93 4
|
2月前
|
分布式计算 Java Hadoop
Hadoop-30 ZooKeeper集群 JavaAPI 客户端 POM Java操作ZK 监听节点 监听数据变化 创建节点 删除节点
Hadoop-30 ZooKeeper集群 JavaAPI 客户端 POM Java操作ZK 监听节点 监听数据变化 创建节点 删除节点
70 1
|
3月前
|
缓存 前端开发 Java
【Java面试题汇总】Spring,SpringBoot,SpringMVC,Mybatis,JavaWeb篇(2023版)
Soring Boot的起步依赖、启动流程、自动装配、常用的注解、Spring MVC的执行流程、对MVC的理解、RestFull风格、为什么service层要写接口、MyBatis的缓存机制、$和#有什么区别、resultType和resultMap区别、cookie和session的区别是什么?session的工作原理
|
3月前
|
存储 安全 Java
Java修仙之路,十万字吐血整理全网最完整Java学习笔记(进阶篇)
本文是Java基础的进阶篇,对异常、集合、泛型、Java8新特性、I/O流等知识进行深入浅出的介绍,并附有对应的代码示例,重要的地方带有对性能、底层原理、源码的剖析。适合Java初学者。
Java修仙之路,十万字吐血整理全网最完整Java学习笔记(进阶篇)
|
2月前
|
Java 数据安全/隐私保护
java学习笔记(基础习题)
java学习笔记(基础习题)
44 0
|
2月前
|
Java 程序员 开发工具
java学习笔记
java学习笔记
46 0