-
2021-06-01 12:26:08
1.什么是数据持久层?
数据持久层负责对数据库中的数据进行增删改查。
2.JDBC是什么?有什么缺点?
JDBC代表Java Database Connectivity,它是提供了一组Java API来访问关系数据库的Java程序。使用框架的访问都是在原生的JDBC基础上进行封装。
缺点:需要写的代码量比较多,不利于快速开发
获取到的结果集非面向对象,解析结果的时候需要自己编码处理
3.主流数据持久层框架有哪些?
Hibernate, MyBatis, Springdata Jpa
4.Hibernate
Hibernate是一个采用ORM的主流数据持久层框架。
- ORM框架
- 提供简单APIs直接储存和检索数据库,不需要程序员写SQL5.MyBatis特点
- 半ORM框架
- 需要程序员自己维护SQL,一方面可以增加对SQL的掌控,有利于提高某些SQL执行速度,另一方面也增加了工作量和代码量
- 因为需要自己维护SQL,不利于在不同数据库之间移植6.Spring Data Jpa
JPA是Sun公司提出的一套持久化规范,意在整合ORM框架,简化开发。
Spring Data Jpa是Spring生态的一部分。Spring Data Jpa进一步精简了ORM框架的代码量,可以做到无缝切换ORM,而无需改变代码。
更多相关内容 -
MyBatis持久层框架的用法知识小结
2020-09-02 01:42:17MyBatis 本是apache的一个开源项目iBatis,接下来通过本文给大家介绍MyBatis持久层框架的用法知识小结,非常不错,具有参考借鉴价值,感兴趣的朋友一起学习吧 -
MyBatis支持定制化SQL存储过程以及高级映射的优秀的持久层框架
2019-08-08 02:48:37MyBatis 是支持定制化 SQL、存储过程以及高级映射的优秀的持久层框架。MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集。 -
Hibernate数据持久层框架 v5.2.13
2020-11-07 16:11:54Hibernate是一种Java语言下的对象关系映射解决方案。 它是使用GNU宽通用公共许可证发行的自由、开源的软件。它为面向对象的领域模型到传统的关系型数据库的映射,提供了一个使用方 -
java持久层框架mybatis防止sql注入的方法
2020-09-01 10:14:00下面小编就为大家带来一篇java持久层框架mybatis防止sql注入的方法。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧 -
Hibernate数据持久层框架v5.2.13
2019-07-28 07:08:05Hibernate也是目前Java开发中最为流行的数据库持久层框架,现已归JBOSS所有。 它的设计目标是将软件开发人员从大量相同的数据持久层相关编程工作中解放出来。无论是从设计草案还是从一个遗留数据库开 -
Java数据持久层框架MyBatis.zip
2019-07-19 17:30:48iBATIS提供的持久层框架包括SQL Maps和Data Access Objects(DAO),同时还提供一个利用这个框架开发的 JPetStore实例。 在线Javadoc:http://tool.oschina.net/apidocs/apidoc?api=mybatis-3.1.1 标签:... -
java持久层框架对比
2012-02-10 15:07:52java持久层框架对比 -
mybatis持久层框架技术
2021-06-13 02:22:21MyBatis 是一款优秀的持久层框架,它支持定制化 SQL、存储过程以及高级映射。MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集。MyBatis 可以使用简单的 XML 或注解来配置和映射原生信息,将接口和... -
Java持久层框架MyBatis简单实例
2020-09-02 01:57:44MyBatis 本是apache的一个开源项目iBatis, 2010年这个项目由apache software foundation 迁移到了google ...本文重点给大家介绍Java持久层框架MyBatis简单实例,非常不错,具有参考借鉴价值,感兴趣的朋友一起看下吧 -
java 自定义持久层框架代码
2020-10-18 00:42:50java 实现自定义持久层框架代码,解析配置文件,手动封装返回结果,使用到了构建者模式、工厂模式、代理模式 -
Hibernate数据持久层框架源代码
2021-03-15 16:16:16Hibernate是一种Java语言下的对象关系映射解决方案。 它是使用GNU宽通用公共许可证发行的自由、开源的软件。它为面向对象的领域模型到传统的关系型...Hibernate也是目前Java开发中最为流行的数据库持久层框架,现已归JB -
Java持久层框架
2020-05-28 22:19:46一、常用的ORM框架 ORM:对象关系映射(英语:(Object Relational Mapping,简称ORM,或O/RM,或O/R mapping),是一种程序技术,用于实现面向对象编程语言里不同类型系统的数据之间的转换 。从效果上说,它其实是创建...一、ORM框架
ORM:对象关系映射(英语:(Object Relational Mapping,简称ORM,或O/RM,或O/R mapping),是一种程序技术,用于实现面向对象编程语言里不同类型系统的数据之间的转换 。从效果上说,它其实是创建了一个可在编程语言里使用的--"虚拟对象数据库"。面向对象是从软件工程基本原则(如耦合、聚合、封装)的基础上发展起来的,而关系数据库则是从数学理论发展而来的,两套理论存在显著的区别。为了解决这个不匹配的现象,对象关系映射技术应运而生。
对象关系映射(ORM)是一种功能,用于通过将对象状态映射到数据库列来开发和维护对象和关系数据库之间的关系。 它能够轻松处理(或执行)各种数据库操作,如插入,更新,删除等。
映射方向
单向关系 - 在这种关系中,只有一个实体可以将属性引用到另一个实体。它仅包含一个侧面,由于指定如何更新可以在数据库中进行。
双向关系 - 这种关系包含两边 - 既包含一个侧面,也包含另一个侧面。 所以这里每个实体都有一个关系字段或将该属性引用到其他实体。
映射类型
一对一 - 此关联由
@OneToOne
注释表示。在这里,每个实体的实例与另一个实体的单个实例相关。一对多 - 此关联由
@OneToMany
注释表示。 在这种关系中,一个实体的实例可以与另一个实体的多个实例相关联。多对一 - 此映射由
@ManyToOne
注释定义。 在这种关系中,一个实体的多个实例可以与另一个实体的单个实例相关联。多对多 - 此关联由
@ManyToMany
注释表示。 在这种关系中,一个实体的多个实例可能与另一个实体的多个实例有关。 在这个映射中,任何一方都可以成为所有者方。二、Mybatis
什么是 MyBatis?
MyBatis 是一款优秀的持久层框架,它支持自定义 SQL、存储过程以及高级映射。MyBatis 免除了几乎所有的 JDBC 代码以及设置参数和获取结果集的工作。MyBatis 可以通过简单的 XML 或注解来配置和映射原始类型、接口和 Java POJO(Plain Old Java Objects,普通老式 Java 对象)为数据库中的记录。
使用mybatis
(1)引入jar包
<dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>x.x.x</version> </dependency>
(2)从 XML 中构建 SqlSessionFactory
每个基于 MyBatis 的应用都是以一个 SqlSessionFactory 的实例为核心的。
String resource = "org/mybatis/example/mybatis-config.xml"; InputStream inputStream = Resources.getResourceAsStream(resource); SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
XML 配置文件中包含了对 MyBatis 系统的核心设置,包括获取数据库连接实例的数据源(DataSource)以及决定事务作用域和控制方式的事务管理器(TransactionManager)。
<?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="${driver}"/> <property name="url" value="${url}"/> <property name="username" value="${username}"/> <property name="password" value="${password}"/> </dataSource> </environment> </environments> <mappers> <mapper resource="org/mybatis/example/BlogMapper.xml"/> </mappers> </configuration>
(3)从 SqlSessionFactory 中获取 SqlSession
try (SqlSession session = sqlSessionFactory.openSession()) { BlogMapper mapper = session.getMapper(BlogMapper.class); Blog blog = mapper.selectBlog(101); }
(4)探究已映射的 SQL 语句 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="org.mybatis.example.BlogMapper"> <select id="selectBlog" resultType="Blog"> select * from Blog where id = #{id} </select> </mapper>
(5)通过java注解方式
package org.mybatis.example; public interface BlogMapper { @Select("SELECT * FROM blog WHERE id = #{id}") Blog selectBlog(int id); }
使用注解来映射简单语句会使代码显得更加简洁,但对于稍微复杂一点的语句,Java 注解不仅力不从心,还会让你本就复杂的 SQL 语句更加混乱不堪。 因此,如果你需要做一些很复杂的操作,最好用 XML 来映射语句。
(6)MyBatis 动态SQL
动态 SQL:MyBatis 的强大特性之一便是它的动态 SQL。
<select id="findActiveBlogLike" resultType="Blog"> SELECT * FROM BLOG <where> <if test="state != null"> state = #{state} </if> <if test="title != null"> AND title like #{title} </if> <if test="author != null and author.name != null"> AND author_name like #{author.name} </if> </where> </select>
三、Spring Data JPA
什么是Spring data jpa ?
Spring data jpa 是较大的 spring家族的一部分,它使得很容易实现基于 jpa 的存储库。
Spring Data JPA 进行持久层(即Dao)开发一般分三个步骤:
(1)声明持久层的接口,该接口继承 Repository(或Repository的子接口,其中定义了一些常用的增删改查,以及分页相关的方法)。
(2)在接口中声明需要的业务方法。Spring Data 将根据给定的策略生成实现代码。
(3)在 Spring 配置文件中增加一行声明,让 Spring 为声明的接口创建代理对象。配置了 <jpa:repositories> 后,Spring 初始化容器时将会扫描 base-package 指定的包目录及其子目录,为继承 Repository 或其子接口的接口创建代理对象,并将代理对象注册为 Spring Bean,业务层便可以通过 Spring 自动封装的特性来直接使用该对象。
(1)整合springboot,引入jar包
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>6.0.6</version> </dependency>
(2)项目配置
#通用数据源配置 spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver spring.datasource.url=jdbc:mysql://10.110.2.56:3306/springboot_jpa?charset=utf8mb4&useSSL=false spring.datasource.username=springboot spring.datasource.password=springboot # Hikari 数据源专用配置 spring.datasource.hikari.maximum-pool-size=20 spring.datasource.hikari.minimum-idle=5 # JPA 相关配置 spring.jpa.database-platform=org.hibernate.dialect.MySQL5InnoDBDialect spring.jpa.show-sql=true spring.jpa.hibernate.ddl-auto=create
(3)实体类
@Entity @Table(name = "AUTH_USER") public class UserDO { @Id private Long id; @Column(length = 32) private String name; @Column(length = 32) private String account; @Column(length = 64) private String pwd; public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getAccount() { return account; } public void setAccount(String account) { this.account = account; } public String getPwd() { return pwd; } public void setPwd(String pwd) { this.pwd = pwd; } }
(4)持久层服务,实现JpaRepository可以包含很多可用的方法,比如分页,内置的各类查找,无需再编写代码实现。
@Repository public interface UserDao extends JpaRepository<UserDO, Long> { }
-
mybatis雏形之自定义持久层框架
2020-11-05 23:02:41接触过JDBC的同学应该不陌生,那么既然JDBC已经能够完成数据库的操作,为什么还会出现各种持久层框架呢?有新框架出现说明JDBC本身还是存在一些问题, 针对jdbc存在的问题 ,通过学习自定义持久层框架能帮助我们更好的... -
Mybatis持久层框架精讲
2021-06-12 19:59:59MyBatis 本是apache的一个开源项目iBatis, 2010年这个项目由apache software foundation 迁移到了google code,并且改名为MyBatis 。2013年11月迁移到Github! -
MyBatis数据持久层框架-其他
2021-06-11 23:21:54是一个数据持久层(ORM)框架。 MyBatis SQL映射器框架使将关系数据库与面向对象的应用程序结合使用变得更加容易。MyBatis使用XML描述符或注释将对象与存储过程或SQL语句耦合。相对于对象关系映射工具,简单性是... -
Mybatis持久层框架快速入门(环境搭建、xml配置文件、注解).zip
2021-12-06 13:18:00mybatis 是一个优秀的基于 java 的持久层框架,它内部封装了 jdbc,使开发者只需要关注 sql 语句本身, 而不需要花费精力去处理加载驱动、创建连接、创建 statement 等繁杂的过程。 mybatis 通过 xml 或注解的方式... -
Hibernate数据持久层框架-其他
2021-06-11 21:59:00Hibernate也是目前Java开发中最为流行的数据库持久层框架,现已归JBOSS所有。 它的设计目标是将软件开发人员从大量相同的数据持久层相关编程工作中解放出来。无论是从设计草案还是从一个遗留数据库开始,开发人员都... -
17-Spring持久层框架整合
2020-11-04 19:15:231.为什么Spring要与持久层框架进行整合 spring是一个优秀的框架,他的优秀支持就是能整合所有程序员想要让他整合的框架,这里所说的持久成也不例外。 JavaEE开发需要持久层进行数据库的访问操作,spring 当然不让。...上一篇:16-Spring 基于注解的AOP编程、AOP总结https://blog.csdn.net/fsjwin/article/details/109482768
1.为什么Spring要与持久层框架进行整合
spring是一个优秀的框架,他的优秀支持就是能整合所有程序员想要让他整合的框架,这里所说的持久成也不例外。
- JavaEE开发需要持久层进行数据库的访问操作,spring
当然不让。 - JDBC Hibernate MyBatis进行持久开发过程存在大量的代码冗余
- Spring基于模板设计模式对于上述的持久层技术进行了封装
2.Spring要可以与那些持久层框架进行整合
- jdbc JdbcTemplate
- Hibernate (JPA) HibernateTemplate
- Mybatis SqlSessionFactoryBean、MapperScannerConfiger
3.Mybatis开发回顾,在Spring没有整合前
- 实体
- 实体别名
- 表
- 创建DAO接口
- 实现Mapper文件(对maper编程)
- 注册Mapper文件
- MyBatisApi调用
3.1 实体 User.java
package mybatis; import java.io.Serializable; /** * @author yuhl * @Date 2020/11/4 10:51 * @Classname User * @Description 1. 实体 */ public class User implements Serializable { private Integer id; private String name; private String password; public User() { } public User(Integer id, String name, String password) { this.id = id; this.name = name; this.password = password; } public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } @Override public String toString() { return "User{" + "id=" + id + ", name='" + name + '\'' + ", password='" + password + '\'' + '}'; } }
3.2. 实体别名mybatis-config.xml
<?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> <typeAliases> <!-- 2. 实体别名--> <typeAlias alias="user" type="mybatis.User"/> </typeAliases> <environments default="mysql"> <environment id="mysql"> <transactionManager type="JDBC"></transactionManager> <dataSource type="POOLED"> <property name="driver" value="com.mysql.jdbc.Driver"/> <property name="url" value="jdbc:mysql://localhost:3306/yuhl?useSSL=false"/> <property name="username" value="root"/> <property name="password" value="root"/> </dataSource> </environment> </environments> <mappers> </mappers> </configuration>
3.3. 表
-- ---------------------------- -- Table structure for t_user -- ---------------------------- DROP TABLE IF EXISTS `t_user`; CREATE TABLE `t_user` ( `id` int(0) NOT NULL AUTO_INCREMENT, `name` varchar(12) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL, `password` varchar(12) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL, PRIMARY KEY (`id`) USING BTREE ) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci ROW_FORMAT = Dynamic;
3.4. 创建DAO接口 UserDao.java
package mybatis; /** * @author yuhl * @Date 2020/11/4 10:59 * @Classname UserDao * @Description TODO */ public interface UserDao { //保存用户 public void save(User user); }
3.5. 实现Mapper文件UserDAOMapper.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="mybatis.UserDao"> <!--接口名--> <!--id:mybatis.UserDao接口中的方法面 parameterType:面向对象的对象名字--> <insert id="save" parameterType="user"> insert into t_user(name,password) value (#{name},#{password}) </insert> </mapper>
3.6. 注册Mapper文件UserDAOMapper.xml
<?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> <typeAliases> <!-- 2. 实体别名--> <typeAlias alias="user" type="mybatis.User"/> </typeAliases> <environments default="mysql"> <environment id="mysql"> <transactionManager type="JDBC"></transactionManager> <dataSource type="POOLED"> <property name="driver" value="com.mysql.jdbc.Driver"/> <property name="url" value="jdbc:mysql://localhost:3306/yuhl?useSSL=false"/> <property name="username" value="root"/> <property name="password" value="root"/> </dataSource> </environment> </environments> <mappers> <!--注册mapper.xml到mybatis--> <mapper resource="UserDAOMapper.xml"/> </mappers> </configuration>
3.7. MyBatisApi调用
import mybatis.User; import mybatis.UserDao; 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.io.InputStream; /** * @author yuhl * @Date 2020/11/4 11:06 * @Classname MybatisTest * @Description 测试 */ public class MybatisTest { @Test public void test1(){ try { //通过流加载mybatis的主配置文件:mybatis-config.xml InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml"); // SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); SqlSession sqlSession = sqlSessionFactory.openSession(); UserDao userDao = sqlSession.getMapper(UserDao.class); userDao.save(new User("yuhl", "222222")); sqlSession.commit(); sqlSession.close(); } catch (IOException e) { e.printStackTrace(); } } }
插入成功:
3.单纯的Mybatis编程存在的问题
- 配置繁琐 第2步和第7步
如果有9999个类该怎办?
- 代码冗余
主要指的是API代码冗余 。
由于以上两个原因,我们不会使用mybatis单独做开发,会使用spring对于mybatis的整合,下面看对于整合后的mybitis的使用是不是更为丝滑呢!
即spring可以积极2.6.7三个步骤的问题。
4.Spring的Mybatis整合
1. 实体 2. 实体别名(<property name="typeAliasesPackage" value="com.yuhl.entity"/>) 3. 表 4. 创建DAO接口 5. 实现Mapper文件(对maper编程) 6. 注册Mapper文件(<value>classpath:com.yuhl.mapper/*DAOMapper.xml</value>) 7. MyBatisApi调用(被优化了直接从factory.getBean("userDAO")) 以上步在使用spring整合后 1. 实体 2. 表 3. 创建DAO接口 4. 实现Mapper文件(对maper编程)
引入jar包:pom.xml 特别注意与mybatis整合是使用druid连接池
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" 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"> <parent> <artifactId>spring5_20201031</artifactId> <groupId>org.yuhl</groupId> <version>1.0-SNAPSHOT</version> </parent> <modelVersion>4.0.0</modelVersion> <artifactId>Spring_mybatis</artifactId> <dependencies> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-tx</artifactId> <version>5.1.14.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> <version>5.1.14.RELEASE</version> </dependency> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis-spring</artifactId> <version>2.0.2</version> </dependency> <!--阿里巴巴连接池--> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> <version>1.1.18</version> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.48</version> </dependency> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.4.6</version> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.11</version> <scope>test</scope> </dependency> <!-- https://mvnrepository.com/artifact/org.springframework/spring-context --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>5.1.4.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-aop</artifactId> <version>5.1.14.RELEASE</version> </dependency> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjrt</artifactId> <version>1.8.8</version> </dependency> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjweaver</artifactId> <version>1.8.3</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-log4j12</artifactId> <version>1.7.25</version> </dependency> <dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>1.2.17</version> </dependency> </dependencies> </project>
4.1在mybatis-config.xml中的有所东西均可以在applicationContex.xml配置消灭mybatis-config.xml
至此可以完全消灭mybatis-config.xml文件。仅使用applicationContex.xml4.1 代码如下
- 实体User .java
package com.yuhl.entity; import java.io.Serializable; /** * @author yuhl * @Date 2020/11/4 10:51 * @Classname User * @Description 1. 实体 */ public class User implements Serializable { private Integer id; private String name; private String password; public User() { } public User(String name, String password) { this.name = name; this.password = password; } public User(Integer id, String name, String password) { this.id = id; this.name = name; this.password = password; } public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } @Override public String toString() { return "User{" + "id=" + id + ", name='" + name + '\'' + ", password='" + password + '\'' + '}'; } }
- 表t_user 复用之前的表
-- ---------------------------- -- Table structure for t_user -- ---------------------------- DROP TABLE IF EXISTS `t_user`; CREATE TABLE `t_user` ( `id` int(0) NOT NULL AUTO_INCREMENT, `name` varchar(12) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL, `password` varchar(12) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL, PRIMARY KEY (`id`) USING BTREE ) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci ROW_FORMAT = Dynamic;
3 创建DAO接口UserDAO.java
package com.yuhl.dao; import com.yuhl.entity.User; /** * @author yuhl * @Date 2020/11/4 10:59 * @Classname UserDao * @Description TODO */ public interface UserDAO { //保存用户 public void save(User user); }
- 实现Mapper文件(对maper编程)com.yuhl.mapper/UserDAOMapper.xml
特别注意:com.yuhl.mapper是一个文件集,不是三级包
<?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="com.yuhl.dao.UserDAO"> <!--接口名--> <!--id:mybatis.UserDao接口中的方法面 parameterType:面向对象的对象名字--> <insert id="save" parameterType="user"> insert into t_user(name,password) value (#{name},#{password}) </insert> </mapper>
- 测试
import com.yuhl.dao.UserDAO; import com.yuhl.entity.User; import org.junit.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; /** * @author yuhl * @Date 2020/11/4 11:06 * @Classname MybatisTest * @Description 测试 */ public class MybatisTest2 { @Test public void test1() { ApplicationContext ctx = new ClassPathXmlApplicationContext("/applicationContext.xml"); UserDAO userDao = (UserDAO) ctx.getBean("userDAO"); userDao.save(new User("zhangsan","ddd")); } }
- 结果
5.Mybatis和spring整合事务控制
这句话告诉我们spring并没有提交事务,我们的事务是被谁提交的呢?
前面我们单独使用mybatis的时候手动提交了了事务
session.commint;
这里直接给出答案,是我们引入的第三方数据源druid控制了事务的提交。
但是在实战中我们不会让他控制我们的事务,我们会把事务的控制权交给spring,让spring来控制事务。
下一篇:18-Spring事务控制@Transactional https://blog.csdn.net/fsjwin/article/details/109497305 - JavaEE开发需要持久层进行数据库的访问操作,spring
-
java自定义持久层框架
2021-07-30 21:51:27自定义持久层框架 -
MyBatis是什么?使用它作为持久层框架有什么优点?
2022-03-19 21:10:34MyBatis是一个基于Java的持久层框架,本篇讲述mybatis映射文件、#{} 、${} 之间的区别是什么?mybatis缓存是什么?分步查询该如何使用?等等面试常问知识。适合新手的学习和老手的复习。文章目录
一、前言
大家好,我是卷心菜,大二学生一枚。
为了冲一冲暑假的实习,周末两天的时间复习完了B站上的mybatis相关的视频教程,发现一部分的知识点已经完全忘记了,甚至说完全不记得了,这是件很可怕的事情。之前没有整理过学习笔记,这次就干脆整个大的,全文大概2万个字,认真记录下来,以后要是忘记了,打开博客看看,巩固一下,这就是写博客的好处吧!正在找实习工作的小伙伴,可以和博主一起交流面试题,一起学习打卡呀~
在阅读本篇文章之前,自己还记录了一点点小bug,写在我的石墨文档里面了,感兴趣的可以看一看:我的错误记录,我先提问一下:
- mybatis映射文件、核心配置文件、properties配置文件、日志文件到底在这个框架中各自的功能是什么?它们在文件夹中的位置该如何设定?
- resultMap、resultType有什么不同?什么时候要使用它们?
- 遇到像模糊查询时,我们该如何正确操作?
- #{} 、${} 之间的区别是什么?各自使用的情景是什么?
- mybatis缓存是什么?
- 分步查询会不会?
- …
废话不多说,满满的干货,赶快来看看吧~
二、基本介绍
一句话总结一下,MyBatis是一个基于Java的持久层框架,是一个半自动的ORM框架。那么可爱的它具有哪些很好的特性呢?
- 支持定制化 SQL、存储过程以及高级映射
- 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集的操作
- 可以使用简单的XML或注解用于配置和原始映射,将接口和Java的POJO(实体类)映射成数据库中的记录
那么它有哪些优点呢?
- 轻量级,性能出色
- SQL 和 Java 编码分开,功能边界清晰。Java代码专注业务、SQL语句专注数据
好了,了解这些就差不多了,接下来进入Mybatis的知识世界!
三、搭建开发环境
首先要做的就是引入依赖,具体的
pom.xml
如下:<packaging>jar</packaging> <dependencies> <!-- Mybatis核心 --> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.5.7</version> </dependency> <!-- junit测试 --> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> <scope>test</scope> </dependency> <!-- MySQL驱动 --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.28</version> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.18.10</version> </dependency><!-- log4j日志 --> <dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>1.2.17</version> </dependency> </dependencies>
这里需要注意的就是MySQL的驱动依赖了,我直接跟着视频走,使用的是版本5.7,结果可想而知,报错了,呜呜呜~
接着就是创建实体类、mapper接口、核心配置文件、映射文件,我给大家依次演示一下如何使用:
实体类:与数据库字段相关联,这个数据库在我的石墨文档第一个位置,大家可以自己运行一下SQL代码试一试
@Data @AllArgsConstructor @NoArgsConstructor public class User { private Integer id; private String username; private String password; private Integer age; private String sex; private String email; }
mapper接口:可以从官方文档中找案例复制下来——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"> <mapper namespace="com.cabbage.mappers.UserMapper"> </mapper>
核心配置文件:跟mapper接口一样,也可以从官方中复制下来
<?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> <properties resource="jdbc.properties"/> <typeAliases> <package name="com.cabbage.pojo"/> </typeAliases> <environments default="development"> <environment id="development"> <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}"/> </dataSource> </environment> </environments> <mappers> <!--<mapper resource="mappers/UserMapper.xml"/>--> <package name="com.cabbage.mappers"/> </mappers> </configuration>
最后再来一个日记文件记录信息以及jdbc.properties配置文件
日志文件:可以当做是一种模板
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE log4j:configuration SYSTEM "log4j.dtd"> <log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/"> <appender name="STDOUT" class="org.apache.log4j.ConsoleAppender"> <param name="Encoding" value="UTF-8"/> <layout class="org.apache.log4j.PatternLayout"> <param name="ConversionPattern" value="%-5p %d{MM-dd HH:mm:ss,SSS} %m (%F:%L) \n"/> </layout> </appender> <logger name="java.sql"> <level value="debug"/> </logger> <logger name="org.apache.ibatis"> <level value="info"/> </logger> <root> <level value="debug"/> <appender-ref ref="STDOUT"/> </root> </log4j:configuration>
jdbc.properties
配置文件:配置数据库的连接信息——用户名、密码等等jdbc.driver=com.mysql.cj.jdbc.Driver jdbc.url=jdbc:mysql://localhost:3306/mybatis jdbc.username= jdbc.password=
说了这么多配置文件,大家估计都懵了,这些文件各自放在什么目录下呢?大家可以参考一下我的位置
好了,各位小伙伴们,基本的环境搭建已经完成了,熟悉mybatis的小伙伴们看到这些文件中的属性,也知道各自是什么功能;不知道的小伙伴也不要着急,从案例中慢慢就会解密他们的各自功能以及使用方法。
四、核心配置文件
让我们回过头来看看刚才搭建的核心配置文件,如何使用?
- 1、
<properties/>
- 2、
<typeAliases></typeAliases>
- 3、
<mappers></mappers>
需要特别注意的是:在resources
文件夹下建包时,格式应该是下图的样式
五、mapper映射文件
先看一下映射文件的命名规则:
- 表所对应的实体类的
类名+Mapper.xml
例如:表t_user,映射的实体类为User,所对应的映射文件为UserMapper.xml
因此一个映射文件对应一个实体类,对应一张表的操作- MyBatis映射文件用于编写SQL,访问以及操作表中的数据
- MyBatis映射文件存放的位置是
src/main/resources/mappers目录
下
此外,MyBatis中可以面向接口操作数据,要保证两个一致:
- mapper接口的全类名和映射文件的命名空间
(namespace)
保持一致 - mapper接口中方法的方法名和映射文件中编写SQL的标签的id属性保持一致
写一个代码演示一下:查询表中id=3的user
<!--User selectById();--> <select id="selectById" resultType="User"> SELECT * FROM t_user WHERE id = 3 </select>
public interface UserMapper { User selectById(); }
运行结果完全正确:
需要注意的是:- 查询的标签select必须设置属性
resultType
或resultMap
,用于设置实体类和数据库表的映射 - resultType:自动映射,用于属性名和表中字段名一致的情况
- resultMap:自定义映射,用于一对多或多对一或字段名和属性名不一致的情况,这个后面就会讲到
- 当查询的数据为多条时,不能使用实体类作为返回值,只能使用集合,否则会抛出异常
TooManyResultsException;
但是若查询的数据只有一条,可以使用实体类或集合作为返回值
六、参数值的两种方式(重点)
-
MyBatis获取参数值的两种方式:
${}和#{}
-
${}的本质就是
字符串拼接
,#{}的本质就是占位符赋值
-
${}使用字符串拼接的方式拼接sql,若为字符串类型或日期类型的字段进行赋值时,需要手动加单引号;但是#{}使用占位符赋值的方式拼接sql,此时为字符串类型或日期类型的字段进行赋值时,可以自动添加单引号
在学习中,原本把参数值分为五种情况,最后介绍了注解
@Param
的使用,最后就把这五种情况归纳为两种情况,那就来介绍这两种情况吧!- 1、实体类类型参数
- 2、使用@Param标识参数,使用该注解时,以@Param注解的值为键,以参数为值,或者以param1、param2为键,以参数为值
下面找一些具有代表性的代码,方便以后的回忆,小伙伴们也可以看看这些代码是否还知道是什么意思呀,测试代码就不写了
七、select的重点介绍
查询单个数据,这个很简单了 <!--Integer getCount();--> <select id="getCount" resultType="integer"> select count(*) from t_user </select> 查询一条数据为map集合,会把查询到的一个对象封装在map中 <!--Map<String,Object> getUserByIdToMap(@Param("id") Integer id);--> <select id="getUserByIdToMap" resultType="map"> select * from t_user where id = #{id} </select> 查询所有数据放入到map集合中 //方式一: List<Map<String,Object>> getAllUsersToMap(); @MapKey("id"),<!--把id当做map的键,查询的对象作为值返回过来--> Map<String, Object> getAllUsersToMap();
对
查询所有数据放入到map集合中
这种方式,进行代码测试一下:@Test public void test4() throws IOException { SqlSession sqlSession = GetSqlSession.getSqlSession(); UserMapper mapper = sqlSession.getMapper(UserMapper.class); // List<Map<String, Object>> mapList = mapper.getAllUsersToMap(); Map<String, Object> map = mapper.getAllUsersToMap(); // System.out.println(mapList); System.out.println(map); }
看一下查询的部分结果:
八、特殊SQL的查询
- 1、
模糊查询
<!--List<User> getUserByLike(@Param("username") String username);--> <select id="getUserByLike" resultType="User"> select * from t_user where username like "%"#{username}"%" </select>
- 2、
批量删除
<!--Integer deleteMore(@Param("ids") String ids);--> <delete id="deleteMore"> delete from t_user where id in (${ids}) </delete>
代码演示一下:
@Test public void test2() throws IOException { SqlSession sqlSession = GetSqlSession.getSqlSession(); SQLMapper mapper = sqlSession.getMapper(SQLMapper.class); Integer result = mapper.deleteMore("7,8,9"); System.out.println(result); }
运行结果:
- 3、
动态设置表名
<!--List<User> getAllUserByTableName(@Param("tableName") String tableName);--> <select id="getAllUserByTableName" resultType="User"> select * from ${tableName} </select>
- 4、
添加功能获取自增的主键
<!--int insertUser(User user); useGeneratedKeys:设置使用自增的主键 keyProperty:因为增删改有统一的返回值是受影响的行数, 因此只能将获取的自增的主键放在传输的参数user对象的某个属性中 --> <insert id="insertUser" useGeneratedKeys="true" keyProperty="id"> insert into t_user values (null,#{username},#{password},#{age},#{sex},#{email}) </insert> <!--这句话是什么意思呢?也就是说加入一个user对象的同时 ,把该对象的自增键的值赋给id,通过调用getter方法拿到id值-->
代码演示一下:
@Test public void test4() throws IOException { SqlSession sqlSession = GetSqlSession.getSqlSession(); SQLMapper mapper = sqlSession.getMapper(SQLMapper.class); User user = new User(null, "cabbage8" , "123454", 23, "男" , "cabbage8@qq.com"); int result = mapper.insertUser(user); System.out.println(result); System.out.println(user.getId()); }
运行结果:
九、自定义resultMap
- 1、
resultMap处理字段和属性的映射关系
,若字段名和实体类中的属性名不一致,则可以通过resultMap设置自定义映射
<resultMap id="mapEmp" type="Emp"> <id property="eid" column="eid"/> <result property="empName" column="emp_name"/> </resultMap> <!--List<Emp> getAllEmp();--> <select id="getAllEmp" resultMap="mapEmp"> select eid,emp_name,age,sex,email,did from t_emp --或者select eid,emp_name empName,age,sex,email,did from t_emp </select>
resultMap:设置自定义映射属性:
- id:表示自定义映射的唯一标识
- type:查询的数据要映射的实体类的类型子标签:
- id:设置主键的映射关系
result:设置普通字段的映射关系
- property:设置映射关系中实体类中的属性名
- column:设置映射关系中表中的字段名
当然,若字段名和实体类中的属性名不一致,但是字段名符合数据库的规则(使用_),实体类中的属性名符合Java的规则(使用驼峰)时,
可以在MyBatis的核心配置文件中设置一个全局配置信息mapUnderscoreToCamelCase,
在查询表中数据时,自动将_类型的字段名转换为驼峰
例如:字段名user_name,设置了mapUnderscoreToCamelCase
,此时字段名就会转换为userName- 2、
多对一映射处理
,这是重点!
我们需要修改一下核心配置文件的内容,添加一些配置(这些配置在官方文档中都有介绍):
<settings> <setting name="mapUnderscoreToCamelCase" value="true"/> <!--开启延迟加载--> <setting name="lazyLoadingEnabled" value="true"/> </settings>
三种方式的介绍:
<!--Emp getEmpAndDept(@Param("eid") Integer eid);--> <!--方式一:级联属性赋值--> <resultMap id="getEmpAndDeptMap1" type="Emp"> <id property="eid" column="eid"/> <result property="empName" column="emp_name"/> <result property="dept.did" column="did"/> <result property="dept.deptName" column="dept_name"/> </resultMap> <!--方式二:association解决映射关系--> <resultMap id="getEmpAndDeptMap2" type="Emp"> <id property="eid" column="eid"/> <result property="empName" column="emp_name"/> <association property="dept" javaType="Dept"> <result property="did" column="did"/> <result property="deptName" column="dept_name"/> </association> </resultMap> <!--方式三:分步查询--> <!-- select:设置分步查询的SQL的唯一标识(namespace.方法名) column:设置分步的查询条件 fetchType:当开启了全局的延迟加载之后,可通过此属性手动控制延迟加载的效果 eager,立即加载;lazy,懒加载 --> <resultMap id="getEmpAndDeptByStepMap" type="Emp"> <id property="eid" column="eid"/> <result property="empName" column="emp_name"/> <association property="dept" select="com.cabbage.mappers.DeptMapper.getEmpAndDeptByStepTwo" column="did" fetchType="eager"> </association> </resultMap> <!--Emp getEmpAndDeptByStepOne(@Param("eid") Integer eid);--> <select id="getEmpAndDeptByStepOne" resultMap="getEmpAndDeptByStepMap"> select * from t_emp where eid = #{eid} </select>
方式三中
DeptMapper.xml
对应的分步查询的第二步:<!--Dept getEmpAndDeptByStepTwo(@Param("did") Integer did);--> <select id="getEmpAndDeptByStepTwo" resultType="Dept"> select * from t_dept where did = #{did} </select>
老师说,方式三在实际开发中使用的最多,方式三是一种懒加载,那咱们就测试一下方式三:
@Test public void test3() throws IOException { SqlSession sqlSession = SqlSessionUtil.getSqlSession(); EmpMapper mapper = sqlSession.getMapper(EmpMapper.class); Emp emp = mapper.getEmpAndDeptByStepOne(1); System.out.println(emp.getEmpName()); System.out.println("----------------"); System.out.println(emp.getDept()); }
运行结果:
我们把eager改成lazy后的运行结果:
- 3、
一对多映射处理
,这是重点!
<!--方式一: collection:处理一对多的映射关系 ofType:表示该属性所对应的集合中存储数据的类型 --> <resultMap id="getDeptAndEmpMap" type="Dept"> <result property="did" column="did"></result> <result property="deptName" column="dept_name"></result> <collection property="emps" ofType="Emp"> <result property="eid" column="eid"></result> <result property="empName" column="emp_name"></result> <result property="age" column="age"></result> <result property="email" column="email"></result> <result property="sex" column="sex"></result> <result property="did" column="did"></result> </collection> </resultMap> <!--Dept getDeptAndEmp(@Param("did") Integer did);--> <select id="getDeptAndEmp" resultMap="getDeptAndEmpMap"> select * from t_dept t1 left join t_emp t2 on t1.did = t2.did where t1.did = #{did} </select> <!--方式二--> <resultMap id="getDeptAndEmpOneMap" type="Dept"> <id property="did" column="did"></id> <result property="deptName" column="dept_name"></result> <collection property="emps" select="com.cabbage.mappers.EmpMapper.getDeptAndEmpByStepTwo" column="did"> </collection> </resultMap> <!-- Dept getDeptAndEmpOne(@Param("did") Integer did);--> <select id="getDeptAndEmpOne" resultMap="getDeptAndEmpOneMap"> select * from t_dept where did = #{did} </select>
方式二中
EmpMapper.xml
对应的分步查询的第二步:<!--List<Emp> getDeptAndEmpByStepTwo(@Param("eid") Integer eid);--> <select id="getDeptAndEmpByStepTwo" resultType="Emp"> select * from t_emp where did= #{eid} </select>
写个测试代码:
@Test public void test4() throws IOException { SqlSession sqlSession = SqlSessionUtil.getSqlSession(); DeptMapper mapper = sqlSession.getMapper(DeptMapper.class); Dept dept = mapper.getDeptAndEmpOne(1); System.out.println(dept); }
十、动态SQL
Mybatis框架的动态SQL技术是一种根据特定条件动态拼装SQL语句的功能,它存在的意义是为了解决拼接SQL语句字符串时的痛点问题。接下来就为大家逐一介绍他们的使用代码
- 1、
if的使用
:if标签可通过test属性的表达式进行判断,若表达式的结果为true,则标签中的内容会执行;反之标签中的内容不会执行
<!--List<User> getUserByCondition(User user);--> <select id="getUserByCondition" resultType="User"> select * from t_user where 1=1 <if test="username !=null and username != ''"> and username = #{username} </if> <if test="password != null and password != ''"> and password = #{password} </if> </select>
这个语句是什么意思呢?其实就是我们传入一个实体对象,对象的username、password属性不为空或者不为null,就查询。对应的SQL语句是:select * from t_user where 1=1 and username = ? and password = ?
- 2、
where的使用
<!--List<User> getUserByWhere(User user);--> <select id="getUserByWhere" resultType="User"> select * from t_user <where> <if test="username != null and username != ''"> and username = #{username} </if> <if test="password != null and password != ''"> and password = #{password} </if> </where> </select>
where和if一般结合使用:
1、若where标签中的if条件都不满足,则where标签没有任何功能,即不会添加where关键字
2、若where标签中的if条件满足,则where标签会自动添加where关键字,并将条件最前方多余的 and去掉
3、注意:where标签不能去掉条件最后多余的and- 3、
trim的使用
<!--List<User> getUserByTrim(User user);--> <select id="getUserByTrim" resultType="User"> select * from t_user <trim prefix="where" suffixOverrides="and"> <if test="username != null and username != ''"> username = #{username} and </if> <if test="password != null and password != ''"> password = #{password} and </if> </trim> </select>
trim用于去掉或添加标签中的内容,常用属性:
1、prefix:在trim标签中的内容的前面添加某些内容
2、prefixOverrides:在trim标签中的内容的前面去掉某些内容
3、suffix:在trim标签中的内容的后面添加某些内容
4、suffixOverrides:在trim标签中的内容的后面去掉某些内容- 4、
choose、when、otherwise的使用
,相当于if…else if…else,满足一个if条件就不会执行下一个条件了
<!--List<User> getUserByIfElse(User user);--> <select id="getUserByIfElse" resultType="User"> select * from t_user <where> <choose> <when test="username != null and username != ''"> username = #{username} </when> <when test="password != null and password != ''"> password = #{password} </when> <otherwise> id = 3 </otherwise> </choose> </where> </select>
- 5、
foreach的使用
<!--int insertByForeach(@Param("users") List<User> list);--> <insert id="insertByForeach"> insert into t_user values <foreach collection="users" item="item" separator=","> (null,#{item.username},#{item.password},#{item.age},#{item.sex},#{item.email}) </foreach> </insert> <!--对应的SQL语句就是:insert into t_user values (null,?,?,?,?,?) , (null,?,?,?,?,?)--> <!--int deleteByForeach(@Param("id") int[] id);--> <delete id="deleteByForeach"> delete from t_user where id in <foreach collection="id" open="(" close=")" separator="," item="item"> #{item} </foreach> </delete> <!--对应的SQL语句是:delete from t_user where id in ( ? , ? )-->
一起来看看其中的属性:
1、collection:设置要循环的数组或集合
2、item:表示集合或数组中的每一个数据
3、separator:设置循环体之间的分隔符
4、open:设置foreach标签中的内容的开始符
5、close:设置foreach标签中的内容的结束符- 6、
SQL片段的使用
,可以记录一段公共sql片段,在使用的地方通过include标签进行引入
<sql id="selectAll"> id,username,password,age,sex,email </sql> <!--比如我们把select * 这个查询字段可以改为表中所有的字段到sql片段中, 最后再把 *去掉,引入sql片段就可以了--> select <include refid="selectAll"></include> from t_user
十一、MyBatis的缓存
对于这一部分的讲解,我不打算举例代码,因为相信学过mybatis的小伙伴们,看看对缓存的文字介绍,就可以回想起缓存所具有的特点,那么咱们就先从一级缓存开始吧!
一级缓存是SqlSession级别的,通过同一个SqlSession查询的数据会被缓存,下次查询相同的数据,就会从缓存中直接获取,不会从数据库重新访问。把握两点:一是同一个sqlsession,二是查询相同的数据。缓存影响着我们的查询速度,但不影响我的查询数据!
使一级缓存失效的四种情况:
- 不同的SqlSession对应不同的一级缓存
- 同一个SqlSession但是查询条件不同
- 同一个SqlSession两次查询期间执行了任何一次增删改操作(注意一下)
- 同一个SqlSession查询期间手动清空了缓存(
sqlSession.clearCache();
)
还是演示一下手动清空缓存的情况吧:
@Test public void test1() throws IOException { InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml"); SqlSessionFactoryBuilder factoryBuilder = new SqlSessionFactoryBuilder(); SqlSessionFactory factory = factoryBuilder.build(inputStream); SqlSession sqlSession = factory.openSession(true); UserMapper mapper = sqlSession.getMapper(UserMapper.class); UserMapper mapper1 = sqlSession.getMapper(UserMapper.class); User user = mapper.selectById(1); sqlSession.clearCache(); User user1 = mapper1.selectById(1); System.out.println(user); System.out.println(user1); }
运行结果:
二级缓存是SqlSessionFactory级别,通过同一个SqlSessionFactory创建的SqlSession查询的结果会被缓存;此后若再次执行相同的查询语句,结果就会从缓存中获取二级缓存开启的条件:
- 在核心配置文件中,设置全局配置属性cacheEnabled=“true”,默认为true,不需要设置
- 在映射文件中设置标签
<cache />
- 二级缓存必须在SqlSession关闭或提交之后有效(不要忘记了哦)
- 查询的数据所转换的实体类类型必须实现序列化的接口(
implements Serializable
)
使二级缓存失效的情况:
- 两次查询之间执行了任意的增删改,会使一级和二级缓存同时失效
演示一下二级缓存:
@Test public void test2() throws IOException { InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml"); SqlSessionFactoryBuilder factoryBuilder = new SqlSessionFactoryBuilder(); SqlSessionFactory factory = factoryBuilder.build(inputStream); SqlSession sqlSession = factory.openSession(true); UserMapper mapper = sqlSession.getMapper(UserMapper.class); User user1 = mapper.selectById(1); System.out.println(user1); sqlSession.close();//关闭一个后,放入了二级缓存中 SqlSession sqlSession1 = factory.openSession(true); UserMapper mapper1 = sqlSession1.getMapper(UserMapper.class); User user = mapper1.selectById(1); System.out.println(user); sqlSession1.close(); }
运行结果:
二级缓存的相关配置,这一部分老师没有细讲,摘录下来,了解一下。在mapper配置文件中添加的cache标签可以设置一些属性:
eviction属性:缓存回收策略
LRU(Least Recently Used) – 最近最少使用的:移除最长时间不被使用的对象。
FIFO(First in First out) – 先进先出:按对象进入缓存的顺序来移除它们。
SOFT – 软引用:移除基于垃圾回收器状态和软引用规则的对象。
WEAK – 弱引用:更积极地移除基于垃圾收集器状态和弱引用规则的对象。
默认的是 LRU。flushInterval属性
:刷新间隔,单位毫秒,默认情况是不设置,也就是没有刷新间隔,缓存仅仅调用语句时刷新size属性
:引用数目,正整数代表缓存最多可以存储多少个对象,太大容易导致内存溢出readOnly属性
:只读,true/false
true:只读缓存;会给所有调用者返回缓存对象的相同实例。因此这些对象不能被修改。这提供了很重要的性能优势。
false:读写缓存;会返回缓存对象的拷贝(通过序列化)。这会慢一些,但是安全,因此默认是false。
最后来讲一讲MyBatis缓存查询的顺序:
- 先查询二级缓存,因为二级缓存中可能会有其他程序已经查出来的数据,可以拿来直接使用。
- 如果二级缓存没有命中,再查询一级缓存
- 如果一级缓存也没有命中,则查询数据库
SqlSession
关闭之后,一级缓存中的数据会写入二级缓存
十二、创建逆向工程
什么是逆向工程呢?就是先创建数据库表,由框架负责根据数据库表,反向生成如下资源:
- Java实体类、mapper接口、mapper映射文件
那么就开始根据步骤创建逆向工程吧!
首先需要添加依赖和插件,这里有些依赖使用已经在前面使用过了,大家可以注意一下哦
<!-- 依赖MyBatis核心包 --> <dependencies> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.5.7</version> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.18.10</version> </dependency> <!-- MySQL驱动 --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.28</version> </dependency> <!-- junit测试 --> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> <scope>test</scope> </dependency> <dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>1.2.17</version> </dependency> </dependencies> <!-- 控制Maven在构建过程中相关配置 --> <build> <!-- 构建过程中用到的插件 --> <plugins> <!-- 具体插件,逆向工程的操作是以构建过程中插件形式出现的 --> <plugin> <groupId>org.mybatis.generator</groupId> <artifactId>mybatis-generator-maven-plugin</artifactId> <version>1.3.0</version> <!-- 插件的依赖 --> <dependencies> <!-- 逆向工程的核心依赖 --> <dependency> <groupId>org.mybatis.generator</groupId> <artifactId>mybatis-generator-core</artifactId> <version>1.3.2</version> </dependency> <!-- 数据库连接池 --> <dependency> <groupId>com.mchange</groupId> <artifactId>c3p0</artifactId> <version>0.9.2</version> </dependency> <!-- MySQL驱动 --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.28</version> </dependency> </dependencies> </plugin> </plugins> </build>
接着创建MyBatis的核心配置文件以及逆向工程的配置文件,第一个配置文件已经讲过了,来看看逆向工程配置文件如何创建(使用时,发现实体类属性值补全,后来完善了一下视频中的笔记,加了一个配置):
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE generatorConfiguration PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN" "http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd"> <generatorConfiguration> <!-- targetRuntime: 执行生成的逆向工程的版本 MyBatis3Simple: 生成基本的CRUD(清新简洁版) MyBatis3: 生成带条件的CRUD(奢华尊享版) --> <context id="DB2Tables" targetRuntime="MyBatis3"> <!-- 数据库的连接信息 --> <jdbcConnection driverClass="com.mysql.cj.jdbc.Driver" connectionURL="jdbc:mysql://localhost:3306/mybatis" userId="root" password=""> <!-- 解决table schema中有多个重名的表生成表结构不一致问题 --> <property name="nullCatalogMeansCurrent" value="true"/> </jdbcConnection> <!-- javaBean的生成策略--> <javaModelGenerator targetPackage="com.cabbage.pojo" targetProject=".\src\main\java"> <property name="enableSubPackages" value="true"/> <property name="trimStrings" value="true"/> </javaModelGenerator> <!-- SQL映射文件的生成策略 --> <sqlMapGenerator targetPackage="com.cabbage.mappers" targetProject=".\src\main\resources"> <property name="enableSubPackages" value="true"/> </sqlMapGenerator> <!-- Mapper接口的生成策略 --> <javaClientGenerator type="XMLMAPPER" targetPackage="com.cabbage.mappers" targetProject=".\src\main\java"> <property name="enableSubPackages" value="true"/> </javaClientGenerator> <!-- 逆向分析的表 --> <!-- tableName设置为*号,可以对应所有表,此时不写domainObjectName --> <!-- domainObjectName属性指定生成出来的实体类的类名 --> <table tableName="t_user" domainObjectName="User"/> </context> </generatorConfiguration>
需要注意的是:逆向工程配置文件的数据库相关的信息还是需要自己修改配置的
最后执行插件,如图所示:
使用逆向工程生成的目录给大家看一下,可以看出跟我们自己手动创建的一模一样,是不是很简便呢?
好了,本文对MyBatis的知识总结就到这里了,在复习的过程中,对使用逆向工程后的方法没有具体举例介绍,因为方法实在是太多了;还有一个知识点就是分页插件的使用也没有在本文中介绍,原因也是提供的方法很多,不方便介绍,自己认为最好的办法就是找一个小项目,在实际开发中慢慢熟练使用这些框架给的方法!
十三、总结
乐莫乐兮新相知,很高兴各位小伙伴可以坚持看完这篇关于mybatis的文章。希望大家可以从这篇文章中收获一些新的知识点,这就是进步了~
如果对你有帮助,可以给博主三连支持一下哦~~ 非常感谢, 一起加油,一起进步! -
java开源持久层框架集
2018-07-25 10:38:17Hibernate是一个开放源代码的对象关系映射框架,它对JDBC进行了非常轻量级的对象封装,使得Java程序员可以随心所欲的使用对象编程思维来操纵数据库。 Hibernate可以应用在任何使用JDBC的场合,既可以在Java的客户端... -
自定义持久层框架之MyBatis.zip
2021-02-05 16:04:58无聊时写着玩之徒手撸自定义持久层MyBatis框架; 将会涉及到的一些知识点:工厂模式(Factory工厂模式)、构造者模式(Builder模式)、代理模式,反射,自定义注解,注解的反射,xml解析, 数据库元数据,元数据的... -
持久层框架有哪些?区别是什么?Mybatis框架的优点和缺点
2018-07-31 22:50:50在 java 应用的数据库开发中,不可避免地会使用到持久层框架,而现在开源项目中持久层框架用到最多的基本就是 iBatis、myBatis 和 Hibernate 了。这里就重点分析下这三个框架之间的区别。 iBatis 与 Hibernate ... -
框架专题 Mybatis基于Java的持久层框架,介绍及使用总结
2020-09-05 09:29:45Mybatis ...iBATIS一词来源于“internet”和“abatis”的组合,是一个基于Java的持久层框架。iBATIS提供的持久层框架包括SQL Maps和Data Access Objects(DAOs) 作用 Mybatis 可以帮你整合service的数 -
Java持久层框架之mybatis使用
2020-04-11 16:14:09什么是框架,框架从何而来,为什么使用框架? 框架(framework): 1.是一系列jar包,其本质是对JDK功能的拓展.(jar包,jar:class文件的压缩包) 2.框架是一组程序的集合,包含了一系列的最佳实践,作用是解决某一个领域的问题.... -
数据持久层框架Mybatis
2018-10-23 08:54:45目录 1.软件开发3层架构 2.什么是框架? 3.传统JDBC开发的不足?... 软件开发的3层架构是Java提出分层开发(经典开发)模式,即将软件开发分为表示层、业务逻辑层、数据持久层开发,互相独立,... -
mybatis持久层框架
2014-06-16 11:36:14该配置文件描述mybatis持久层框架技术的,可有将SQL放到配置文件并且规范数据库连接等 -
什么叫持久层框架
2017-03-14 20:19:07下面就对 持久层这个令我懵逼了好久的名词进行解释什么是持久层?持久是相对于瞬时来说的,* 持久层,可以理解成数据 保存在 数据库或者 硬盘一类可以保存很长时间的设备里面,不像放在内存中那样断电就消失了,也...