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

本文涉及的产品
RDS MySQL DuckDB 分析主实例,集群系列 4核8GB
RDS DuckDB + QuickBI 企业套餐,8核32GB + QuickBI 专业版
RDS MySQL DuckDB 分析主实例,基础系列 4核8GB
简介: [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>


相关实践学习
每个IT人都想学的“Web应用上云经典架构”实战
本实验从Web应用上云这个最基本的、最普遍的需求出发,帮助IT从业者们通过“阿里云Web应用上云解决方案”,了解一个企业级Web应用上云的常见架构,了解如何构建一个高可用、可扩展的企业级应用架构。
MySQL数据库入门学习
本课程通过最流行的开源数据库MySQL带你了解数据库的世界。 &nbsp; 相关的阿里云产品:云数据库RDS MySQL 版 阿里云关系型数据库RDS(Relational Database Service)是一种稳定可靠、可弹性伸缩的在线数据库服务,提供容灾、备份、恢复、迁移等方面的全套解决方案,彻底解决数据库运维的烦恼。 了解产品详情:&nbsp;https://www.aliyun.com/product/rds/mysql&nbsp;
相关文章
|
9月前
|
Java
Java 数组学习笔记
本文整理Java数组常用操作:遍历、求和、查找、最值及二维数组行求和等典型练习,涵盖静态初始化、元素翻倍、去极值求平均等实例,帮助掌握数组基础与应用。
|
9月前
|
小程序 Java 知识图谱
Java 学习笔记 —— BMI & BMR 计算器
这是一个使用 Java 编写的 BMI 与 BMR 计算器小程序,可输入年龄、性别、身高和体重,计算身体质量指数(BMI)和基础代谢率(BMR),并输出健康评估结果。通过该项目,掌握了 Java 的输入处理、数据验证、条件判断、数学运算及格式化输出等基础知识,是 Java 初学者的理想练习项目。
|
12月前
|
Java API 微服务
2025 年 Java 从入门到精通学习笔记全新版
《Java学习笔记:从入门到精通(2025更新版)》是一本全面覆盖Java开发核心技能的指南,适合零基础到高级开发者。内容包括Java基础(如开发环境配置、核心语法增强)、面向对象编程(密封类、接口增强)、进阶技术(虚拟线程、结构化并发、向量API)、实用类库与框架(HTTP客户端、Spring Boot)、微服务与云原生(容器化、Kubernetes)、响应式编程(Reactor、WebFlux)、函数式编程(Stream API)、测试技术(JUnit 5、Mockito)、数据持久化(JPA、R2DBC)以及实战项目(Todo应用)。
610 5
|
SQL Java 数据库
解决Java Spring Boot应用中MyBatis-Plus查询问题的策略。
保持技能更新是侦探的重要素质。定期回顾最佳实践和新技术。比如,定期查看MyBatis-Plus的更新和社区的最佳做法,这样才能不断提升查询效率和性能。
736 1
|
Java 区块链 网络架构
酷阿鲸森林农场:Java 区块链系统中的 P2P 区块同步与节点自动加入机制
本文介绍了基于 Java 的去中心化区块链电商系统设计与实现,重点探讨了 P2P 网络在酷阿鲸森林农场项目中的应用。通过节点自动发现、区块广播同步及链校验功能,系统实现了无需中心服务器的点对点网络架构。文章详细解析了核心代码逻辑,包括 P2P 服务端监听、客户端广播新区块及节点列表自动获取等环节,并提出了消息签名验证、WebSocket 替代 Socket 等优化方向。该系统不仅适用于农业电商,还可扩展至教育、物流等领域,构建可信数据链条。
|
存储 Java
# 【Java全栈学习笔记-U1-day02】变量+数据类型+运算符
本篇笔记主要围绕Java全栈学习的第二天内容展开,涵盖了变量、数据类型、运算符以及Scanner类的应用。首先介绍了变量的概念与命名规范,以及如何定义和使用变量;接着详细讲解了Java中的基本数据类型,包括整型、浮点型、字符型、布尔型等,并通过实例演示了数据类型的运用。随后,深入探讨了各类运算符(赋值、算术、关系、逻辑)及其优先级,帮助理解表达式的构成。最后,介绍了如何利用Scanner类实现用户输入功能,并通过多个综合示例(如计算圆面积、购物打折、变量交换及银行利息计算)巩固所学知识。完成相关作业将进一步加深对这些基础概念的理解与实践能力。
300 13
|
开发框架 Java 开发工具
【Java全栈学习笔记-U1-day01】Java介绍
本笔记整理了Java学习的基础内容,涵盖程序理解、Java语言特性、JDK安装与配置、Java程序开发工具及编写步骤。重点介绍了Java程序的基本结构、编译和运行过程,以及输出语句的使用。通过实例演示了IDEA创建Java程序的方法,并强调了编码规范和注意事项。适合初学者复习和交流学习。 主要内容: 1. 理解程序:计算机组成、程序定义。 2. 简介:Java语言特点、技术平台、JDK作用。 3. 编写Java程序:编写、编译、运行步骤,基本结构。 4. 输出语句 5. DEA使用:新建工程、保存位置、文件介绍、新建类。 6. 扩展:注释、代码规范、大小写敏感、缩进等。
|
SQL Java 数据库连接
【潜意识Java】深入理解MyBatis的Mapper层,以及让数据访问更高效的详细分析
深入理解MyBatis的Mapper层,以及让数据访问更高效的详细分析
2993 1
|
SQL Java 数据库连接
【潜意识Java】MyBatis中的动态SQL灵活、高效的数据库查询以及深度总结
本文详细介绍了MyBatis中的动态SQL功能,涵盖其背景、应用场景及实现方式。
2015 6
|
SQL Java 数据库连接
【潜意识Java】深入理解MyBatis,从基础到高级的深度细节应用
本文详细介绍了MyBatis,一个轻量级的Java持久化框架。内容涵盖MyBatis的基本概念、配置与环境搭建、基础操作(如创建实体类、Mapper接口及映射文件)以及CRUD操作的实现。此外,还深入探讨了高级特性,包括动态SQL和缓存机制。通过代码示例,帮助开发者更好地掌握MyBatis的使用技巧,提升数据库操作效率。总结部分强调了MyBatis的优势及其在实际开发中的应用价值。
563 1