前言
在项目中,获取到数据库中的数据后,需要将其映射成class才能使用,一般的程序中都有上百个实体类,繁重且重复的赋值映射操作,是在让人不愉快。有没有一个东西可以自动帮我们处理实体类的映射操作,使我们的工作简化呢?
现在市面上广泛使用两种解决方案
1、Hibernate的 Spring Data Jpa
2、Mybatis的:mybatis-spring-boot-starter
它们的作用都是通过封装简化了开发人员对数据库的操作。本文主要讲的是Mybatis的使用,对Hibernate不做概述
mybatis官网
了解更多细节,可以前往mybatis官方文档
使用mybatis与不使用mybatis的区别
不使用mybatis
我们对于executeQuery查询出来的数据,需要通过迭代ResultSet来读取,如果对象非常复杂,属性繁多,那么就需要定义一大堆的变量,重复使用一大堆方法(getInt、getString)
Connection conn= //...获取connection PreparedStatement ps = conn.prepareStatement("select * from user"); ResultSet rs = ps.executeQuery(); List<UserMap> list = new ArrayList<>(); while (rs.next()) { UserMap um = new UserMap(); um.id = rs.getInt("id"); um.account = rs.getString("account"); ...// 大量的赋值操作 }
使用mybatis
只需要两步
1、定义一个映射接口
@Mapper public interface Myb { @Select("SELECT * FROM user")
List<UserMap> getAll();
//实体类UserMap中的字段会自动被赋予,与sql语句查询结果相同列名的值,举例:UserMap中的存在属性字段id,那么会自动与sql执行结果中的id列的值进行绑定。当然也可以手动指定对应的列,详情请前往mybatis官方文档
}
2、使用
@Autowired private Myb my; //无需手动实现Myb接口,Mybatis已经自动实现,所以自动装载后直接使用即可 @RequestMapping("login") public Object index() { List<UserMap> listUser = my.getAll();//直接getAll方法,获取到通过sql select * from user查询到的数据映射结果 return listUser; }
总结
不使用mybatis
1、需要定义PreparedStatement 、Connection、ResultSet对象,并处理响应的异常
2、需要迭代ResultSet对象,将executeQuery查询出来的数据手动转化车class对象,如果数据结构复杂,那么整个项目成百上千个Class映射,会产生大量重复劳动的工具量,以及大量重复代码
如何使用mybatis
mybatis的使用有两种方式,注解方式和xml方式
=============注解方式====================
1、下载依赖
//mybatis没有集成jdbc,所以对不同数据库的链接,还是需要对应的库
<dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.26</version> </dependency>
//mybatis <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>2.0.0</version> </dependency>
2、配置application.yml
spring: datasource: driver-class-name: com.mysql.cj.jdbc.Driver url: jdbc:mysql://localhost:3306/test?allowMultiQueries=true&autoReconnect=true&characterEncoding=utf-8 username: root password: root
3、定义Mapper
@Mapper //表明此接口是一个mapper,加上此注解会自动被spring boot扫描到 public interface Myb { //在接口中定义一个返回UserMap类型数据方法,会根据定义的数据类型,去映射数据 @Select("SELECT * FROM user") List<UserMap> getAll();//定义执行sql,会将sql执行的结果映射到getAll()的return中
}
(1)也可以不使用@Mapper注解,在启动类上使用@MapperScan("com.example.mybitesstudy02.service"),指定扫描的包
//@Mapper //去掉@Mapper public interface Myb {
@Select("SELECT * FROM user") List<UserMap> getAll(); }
@MapperScan("com.example.mybitesstudy02.service") //在启动类中指定扫描包 @SpringBootApplication public class MybitesStudy02Application { public static void main(String[] args) { SpringApplication.run(MybitesStudy02Application.class, args); } }
4、调用
@RestController public class Index { @Autowiredprivate Myb my; //无需手动实现Myb接口,Mybatis已经自动实现,所以自动装载后直接使用即可 @RequestMapping("login") public Object index() { List<UserMap> listUser = my.getAll();//直接getAll方法,获取到通过sql select * from user查询到的数据映射结果 return listUser; } }
(1)如果是使用@MapperScan指定扫描路劲的话,那么Autowired需要设置required=false
@RestController public class Index { @Autowired(required = false) //使用@MapperScan无法在编译时注入my private Myb my; @RequestMapping("login") public Object index() { List<UserMap> listUser = my.getAll(); return listUser; } }
=============xml方式====================
因为依赖已经下载过了,所以我们直接跳过
1.修改application.yml
...//旧的配置 #新增配置项 mybatis: # config-location: classpath:mybatis/mybatis.config.xml #指定Mybatis配置文件放置目录,学习阶段可以先不管他, mapper-locations: classpath:mybatis/sql/*Map.xml #指定映射xml文件放置目录,以及匹配规则
2.在classpath:mybatis/sql目录下编写映射xml文件
<?xml version="1.0" encoding="UTF-8" ?> <!--这个是必须要的 对xml文档进行标注功能--> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <!--mapper 的namespace 要与你的映射接口的完整包名一致 --> <mapper namespace="com.example.mybitesstudy02.service.Myb"> <!-- 定义一个接收的数据对象--> <!-- id 表明后续xml中使用的id--> <!-- type 为对应实体类的完整包名--> <resultMap id="UserMapXml" type="com.example.mybitesstudy02.service.UserMap"> <id column="id" property="id"/> <result column="account" property="account"/> </resultMap> <!-- 定义一个查询语句--> <!-- id 必须要与映射接口com.example.mybitesstudy02.service.Myb中的方法名一致,下例表示映射到com.example.mybitesstudy02.service.Myb 接口上的 getAll方法,返回一个id为UserMapXml的<resultMap>作为数据类型--> <select id="getAll" resultMap="UserMapXml"> SELECT * FROM user </select> </mapper>
3、改造com.example.mybitesstudy02.service.Myb接口
package com.example.mybitesstudy02.service; import org.apache.ibatis.annotations.Mapper; import java.util.List; @Mapper //不使用@Mapper的话,可以在启动类使用@MapperScan指定扫描 public interface Myb {
//@Select("select * from user) 此注解可以不用了 List<UserMap> getAll(); }
4、造就使用即可
@RestController public class Index { @Autowired //自动装载 private Myb my; @RequestMapping("login") public Object index() { List<UserMap> um = my.getAll(); return um; } }
一些问题
BindingException 异常
原因:
1.mapper.xml文件的namespace与mapper接口完整包路径不一致
解决方案:
参照xml方式使用mybatis的第二步
2.mapper.xml文件中的sql语句所在标签的id属性与mapper接口中的方法名称不一致
解决方案:
参照xml方式使用mybatis的第二步
3.xml资源未被扫描到
解决方案:
修改pom.xml的build,使其能够扫描到Mybatis的映射xml放置的位置
<build>
<resources>
<resource>
<directory>src/main/resources</directory>
</resource>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.xml</include>
</includes>
</resource>
</resources>
</build>