MyBatis中的接口代理机制及其使用

MyBatis中的接口代理机制及其使用

1. MyBatis中的接口代理机制及其使用

@

目录1. MyBatis中的接口代理机制及其使用2. 实操2.1 准备工作2.2 insert 增加操作2.3 delete 删除操作2.4 update 修改操作2.5 select 查询一条记录操作2.6 select 查询多条记录操作3. 总结:4. 最后:

MyBatis 中的接口代理类机制,MyBatis 框架中使用了动态代理的设计模式,让我们可以不用写,对应XxxMapper.java 接口的实现类,而是通过动态代理的方式,让MyBatis 自动为我们生成对应实现了该 XxxMapper.java接口的实现类,这个动态代理实现的类,我们可以直接使用。

核心代码:

// 获取到 SqlSessionFactoryBuilder

SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();

// 获取到SqlSessionFactory 对象

// SQlsessionFactory对象,一个SqlSessionFactory对应一个 environment, 一个environment通常是一个数据库

SqlSessionFactory sessionFactory = sqlSessionFactoryBuilder.build(Resources.getResourceAsStream("mybatis-config.xml"), "mybatis");

// 获取到 SalSession 会话,一次会话一个

SqlSession sqlSession = sessionFactory.openSession();

Car car = new Car(null, "999", "奥迪", 3.0, "2000-10-10", "新能源");

// 面向接口编程,获取接口的代理对象,也就是接口的实现类,实现类该接口中的方法

// 需要注意的是参数的 Xxxmapper.class 和 返回值是保持一致的。

XxxMapper mapper = sqlSession.getMapper(XxxMapper.class);

mapper.xxx(); // 执行的是该XxxMapper接口中的方法

// 获取到 SalSession 会话,一次会话一个

SqlSession sqlSession = sessionFactory.openSession();

Car car = new Car(null, "999", "奥迪", 3.0, "2000-10-10", "新能源");

// 面向接口编程,获取接口的代理对象,也就是接口的实现类,实现类该接口中的方法

// 需要注意的是参数的 Xxxmapper.class 和 返回值是保持一致的。

XxxMapper mapper = sqlSession.getMapper(XxxMapper.class);

mapper.xxx(); // 执行的是该XxxMapper接口中的方法

使用以上代码的前提是:XxxMapper.xml 文件中的 namespace 必须和 dao(mapper)接口的全限定名称一致,id 必须和 dao(mapper) 接口中方法名一致。

比如:我们这里的是:

CarMappe.xml

XxxMapper.xml 文件中的 namespace 必须和 dao(mapper)接口的全限定名称一致

对应的接口上的方法名,id 必须 和 dao(mapper) 接口中方法名一致。

使用的是 POJO 属性类赋值的话,#{} 的括号中的值,必须是 POJO类当中的属性名,比如这里我们用的是 Car ,则#{}括号中的值,则必须是 Car 的属性名。同时 #{} 括号中一定要有值(就算只有一个参数,也要有值(随便写都要有值),才行,不然编译无法通过)

2. 实操

下面我们使用 MyBatis 的接口代理机制,对数据库进行CRUD,(增删改查)的操作。

2.1 准备工作

数据表结构的设计,数据表名为:t_car

t_car 表中的数据信息:

在pom.xml 文件当中配置相关的依赖的 jar 包如下:

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">

4.0.0

com.rainbowsea

mybatis-005-crud-blog

1.0-SNAPSHOT

17

17

org.mybatis

mybatis

3.5.10

mysql

mysql-connector-java

8.0.30

junit

junit

4.13.2

test

ch.qos.logback

logback-classic

1.2.11

配置 logback 的配置文件,用于打印显示,我们的日志信息,方便我们查看我们的运行过程,效果。

%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n

配置 MyBatis 的核心配置文件,

PUBLIC "-//mybatis.org//DTD Config 3.0//EN"

"http://mybatis.org/dtd/mybatis-3-config.dtd">

对照 t_car 创建的ORM 映射的 Car 类

注意:在MyBatis 当中对应的ORM ,一般在框架里对应的 Bean实体类,一定要实现该 set 和 get 方法以及无参数构造方法,无法框架无法使用反射机制,进行操作 。

建议用包装类,这样可以防止 Null的问题,因为(简单类型 int num = null ,是不可以赋值为 null)的编译无法通过

package com.rainbowsea.mybatis.pojo;

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;

}

@Override

public String toString() {

return "Car{" +

"id=" + id +

", carNum='" + carNum + '\'' +

", brand='" + brand + '\'' +

", guidePrice=" + guidePrice +

", produceTime='" + produceTime + '\'' +

", catType='" + 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 catType) {

this.carType = catType;

}

}

对应操作实现CRUD(增删改查)的接口(这里是:CarMapper接口),在MyBtis 当中 ,关于 CRUD(增删改查)操作的接口/实现类,都是 mapper 结尾的作为持久层,而在 MVC的三层架构中,则是以 dao 为后缀作为CRUD(增删改查)操作的接口/实现类。

package com.rainbowsea.mybatis.mapper;

import com.rainbowsea.mybatis.pojo.Car;

import java.util.List;

public interface CarMapper {

/**

* 新增 Car

* @param car

* @return

*/

int insert(Car car);

/**

* 根据id 删除 Car

* @param id

* @return

*/

int deleteById(Long id);

/**

* 修改汽车信息

* @param car

* @return

*/

int update(Car car);

/**

* 根据id查询汽车信息

* @param id

* @return

*/

Car selectById(Long id);

/**

* 获取所有的汽车信息

* @return

*/

List selectAll();

}

2.2 insert 增加操作

对应 CarMapper 接口中的 insert( ) 抽象方法。

public interface CarMapper {

/**

* 新增 Car

* @param car

* @return

*/

int insert(Car car);

}

对应 CarMapper.xml SQL语句映射文件,上编写 insert 插入的 SQL语句。

PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"

"http://mybatis.org/dtd/mybatis-3-mapper.dtd">

insert into t_car values(null,#{carNum},#{brand},#{guidePrice},#{produceTime},#{carType})

Java当中编程运行程序:

注意:因为是对数据库进行了修改,所以需要 commit() 提交给数据库,以及 close() 关闭资源

package com.rainbowsea.mybatis.test;

import com.rainbowsea.mybatis.mapper.CarMapper;

import com.rainbowsea.mybatis.pojo.Car;

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 org.junit.Test;

import java.io.IOException;

public class CarMapperTest {

@Test

public void testInsert() throws IOException {

// 获取到 SqlSessionFactoryBuilder

SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();

// 获取到SqlSessionFactory 对象

// SQlsessionFactory对象,一个SqlSessionFactory对应一个 environment, 一个environment通常是一个数据库

SqlSessionFactory sessionFactory = sqlSessionFactoryBuilder.build(Resources.getResourceAsStream("mybatis-config.xml"), "mybatis");

// 获取到 SalSession 会话,一次会话一个

SqlSession sqlSession = sessionFactory.openSession();

Car car = new Car(null, "999", "奥迪", 3.0, "2000-10-10", "新能源");

// 面向接口编程,获取接口的代理对象,也就是接口的实现类,实现类该接口中的方法

CarMapper mapper = sqlSession.getMapper(CarMapper.class);

int count = mapper.insert(car);

System.out.println(count);

sqlSession.commit();

sqlSession.close();

}

}

2.3 delete 删除操作

根据 id 删除一条记录,删除id为 124的一条记录。

对应 CarMapper 接口中的 deleteById( Long id) 抽象方法。

public interface CarMapper {

/**

* 新增 Car

* @param car

* @return

*/

int insert(Car car);

/**

* 根据id 删除 Car

* @param id

* @return

*/

int deleteById(Long id);

}

对应 CarMapper.xml SQL语句映射文件,上编写 delete 删除的 SQL语句。

使用以上代码的前提是:XxxMapper.xml 文件中的 namespace 必须和 dao(mapper)接口的全限定名称一致,id 必须和 dao(mapper) 接口中方法名一致。

PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"

"http://mybatis.org/dtd/mybatis-3-mapper.dtd">

delete from t_car where id=#{id}

Java当中编程运行程序:

注意:因为是对数据库进行了修改,所以需要 commit() 提交给数据库,以及 close() 关闭资源

删除id为 124的一条记录。

import org.junit.Test;

import java.io.IOException;

public class CarMapperTest {

@Test

public void testDeleteById() throws IOException {

// 获取到 SqlSessionFactoryBuilder

SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();

// 获取到SqlSessionFactory 对象

// SQlsessionFactory对象,一个SqlSessionFactory对应一个 environment, 一个environment通常是一个数据库

SqlSessionFactory sessionFactory = sqlSessionFactoryBuilder.build(Resources.getResourceAsStream("mybatis-config.xml"), "mybatis");

// 获取到 SalSession 会话,一次会话一个

SqlSession sqlSession = sessionFactory.openSession();

// 面向接口编程,获取接口的代理对象,也就是接口的实现类,实现类该接口中的方法

CarMapper mapper = sqlSession.getMapper(CarMapper.class);

// 删除id为 124的一条记录。

int count = mapper.deleteById(124L);

sqlSession.commit(); // 提交给数据库

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

System.out.println(count);

}

}

2.4 update 修改操作

根据 id 修改记录信息。

将 id 为 128的 brand 改为小米su7, guide_price 改为 21.00 , 时间改为 2024-03-28

对应 CarMapper 接口中的 update( ) 抽象方法。

package com.rainbowsea.mybatis.mapper;

import com.rainbowsea.mybatis.pojo.Car;

import java.util.List;

public interface CarMapper {

/**

* 修改汽车信息

* @param car

* @return

*/

int update(Car car);

}

对应 CarMapper.xml SQL语句映射文件,上编写 update 修改的 SQL语句。

使用以上代码的前提是:XxxMapper.xml 文件中的 namespace 必须和 dao(mapper)接口的全限定名称一致,id 必须和 dao(mapper) 接口中方法名一致。

PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"

"http://mybatis.org/dtd/mybatis-3-mapper.dtd">

update t_car

set car_num=#{carNum},

brand=#{brand},

guide_price=#{guidePrice},

produce_time=#{produceTime},

car_type=#{carType}

where id = #{id}

Java当中编程运行程序:

注意:因为是对数据库进行了修改,所以需要 commit() 提交给数据库,以及 close() 关闭资源

将 id 为 128的 brand 改为小米su7, guide_price 改为 21.00 , 时间改为 2024-03-28

import com.rainbowsea.mybatis.mapper.CarMapper;

import com.rainbowsea.mybatis.pojo.Car;

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 org.junit.Test;

import java.io.IOException;

public class CarMapperTest {

@Test

public void testUpdate() throws IOException {

// 获取到 SqlSessionFactoryBuilder

SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();

// 获取到SqlSessionFactory 对象

// SQlsessionFactory对象,一个SqlSessionFactory对应一个 environment, 一个environment通常是一个数据库

SqlSessionFactory sessionFactory = sqlSessionFactoryBuilder.build(Resources.getResourceAsStream("mybatis-config.xml"), "mybatis");

// 获取到 SalSession 会话,一次会话一个

SqlSession sqlSession = sessionFactory.openSession();

Car car = new Car(128L, "999", "小米su7", 21.0, "2022-03-28", "新能源");

// 面向接口编程,获取接口的代理对象,也就是接口的实现类,实现类该接口中的方法

CarMapper mapper = sqlSession.getMapper(CarMapper.class);

int count = mapper.update(car);

sqlSession.commit(); // 提交给数据库

sqlSession.close();

}

}

2.5 select 查询一条记录操作

根据 id 查询一条记录。

查询 id 为 130 的一条记录。

对应 CarMapper 接口中的 selectById ( Long id) 抽象方法。

package com.rainbowsea.mybatis.mapper;

import com.rainbowsea.mybatis.pojo.Car;

import java.util.List;

public interface CarMapper {

/**

* 根据id查询汽车信息

* @param id

* @return

*/

Car selectById(Long id);

}

对应 CarMapper.xml SQL语句映射文件,上编写 select 查询 的 SQL语句。

使用以上代码的前提是:XxxMapper.xml 文件中的 namespace 必须和 dao(mapper)接口的全限定名称一致,id 必须和 dao(mapper) 接口中方法名一致。

需要注意的是:查询是会返回结果集的,所以我们需要在

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}

Java当中编程运行程序:

注意:因为我们仅仅是查询数据表中的信息,不涉及到对数据表的修改,删除操作,所以无需提交数据库commit,只要 close() 关闭资源就可以了

查询 id 为 130 的一条记录。

import com.rainbowsea.mybatis.mapper.CarMapper;

import com.rainbowsea.mybatis.pojo.Car;

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 org.junit.Test;

import java.io.IOException;

public class CarMapperTest {

@Test

public void testSelectById() throws IOException {

// 获取到 SqlSessionFactoryBuilder

SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();

// 获取到SqlSessionFactory 对象

// SQlsessionFactory对象,一个SqlSessionFactory对应一个 environment, 一个environment通常是一个数据库

SqlSessionFactory sessionFactory = sqlSessionFactoryBuilder.build(Resources.getResourceAsStream("mybatis-config.xml"), "mybatis");

// 获取到 SalSession 会话,一次会话一个

SqlSession sqlSession = sessionFactory.openSession();

// 面向接口编程,获取接口的代理对象,也就是接口的实现类,实现类该接口中的方法

CarMapper mapper = sqlSession.getMapper(CarMapper.class);

Car car = mapper.selectById(130L);

System.out.println(car);

sqlSession.close();

}

}

2.6 select 查询多条记录操作

查询t_car 数据表中的所有信息。

对应 CarMapper 接口中的 selectAll( Long id) 抽象方法。返回的是一个List 集合

package com.rainbowsea.mybatis.mapper;

import com.rainbowsea.mybatis.pojo.Car;

import java.util.List;

public interface CarMapper {

/**

* 获取所有的汽车信息

* @return

*/

List selectAll();

}

对应 CarMapper.xml SQL语句映射文件,上编写 select 查询 的 SQL语句。

使用以上代码的前提是:XxxMapper.xml 文件中的 namespace 必须和 dao(mapper)接口的全限定名称一致,id 必须和 dao(mapper) 接口中方法名一致。

需要注意的是:查询是会返回结果集的,所以我们需要在

select id,

car_num as carNum,

brand,

guide_price as guidePrice,

produce_time as produceTime,

car_type as carType

from t_car

Java当中编程运行程序:

注意:因为我们仅仅是查询数据表中的信息,不涉及到对数据表的修改,删除操作,所以无需提交数据库commit,只要 close() 关闭资源就可以了

查询 t_car 数据表中的所有记录。

import com.rainbowsea.mybatis.mapper.CarMapper;

import com.rainbowsea.mybatis.pojo.Car;

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 org.junit.Test;

import java.io.IOException;

import java.util.List;

public class CarMapperTest {

@Test

public void testSelectAll() throws IOException {

// 获取到 SqlSessionFactoryBuilder

SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();

// 获取到SqlSessionFactory 对象

// SQlsessionFactory对象,一个SqlSessionFactory对应一个 environment, 一个environment通常是一个数据库

SqlSessionFactory sessionFactory = sqlSessionFactoryBuilder.build(Resources.getResourceAsStream("mybatis-config.xml"), "mybatis");

// 获取到 SalSession 会话,一次会话一个

SqlSession sqlSession = sessionFactory.openSession();

// 面向接口编程,获取接口的代理对象,也就是接口的实现类,实现类该接口中的方法

CarMapper mapper = sqlSession.getMapper(CarMapper.class);

List cars = mapper.selectAll();

cars.forEach(car -> {

System.out.println(car);

});

sqlSession.close();

}

}

3. 总结:

// 获取到 SalSession 会话,一次会话一个

SqlSession sqlSession = sessionFactory.openSession();

Car car = new Car(null, "999", "奥迪", 3.0, "2000-10-10", "新能源");

// 面向接口编程,获取接口的代理对象,也就是接口的实现类,实现类该接口中的方法

// 需要注意的是参数的 Xxxmapper.class 和 返回值是保持一致的。

XxxMapper mapper = sqlSession.getMapper(XxxMapper.class);

mapper.xxx(); // 执行的是该XxxMapper接口中的方法

使用以上代码的前提是:XxxMapper.xml 文件中的 namespace 必须和 dao(mapper)接口的全限定名称一致,id 必须和 dao(mapper) 接口中方法名一致。

注意:因为是对数据库进行了修改,删除,改动了,所以需要 commit() 提交给数据库,以及 close() 关闭资源

需要注意的是:查询是会返回结果集的,所以我们需要在