如果您想了解Mybatis和mybatisplus的知识,那么本篇文章将是您的不二之选。我们将深入剖析Mybatis的各个方面,并为您解答mybatisplus的疑在这篇文章中,我们将为您介绍Myba
如果您想了解Mybatis和mybatisplus的知识,那么本篇文章将是您的不二之选。我们将深入剖析Mybatis的各个方面,并为您解答mybatisplus的疑在这篇文章中,我们将为您介绍Mybatis的相关知识,同时也会详细的解释mybatisplus的运用方法,并给出实际的案例分析,希望能帮助到您!
本文目录一览:- Mybatis(mybatisplus)
- day63( MYBATIS框架基础1:关于Mybatis框架,创建Mybatis-Spring工程,配置开发环境,基本使用,删除与修改数据)
- Fluent Mybatis, 原生Mybatis, Mybatis Plus三者功能对比
- Fluent Mybatis,原生Mybatis,Mybatis Plus三者功能对比
- java day55【 Mybatis 连接池与事务深入 、 Mybatis 的动态 SQL 语句、 Mybatis 多表查询之一对多 、 Mybatis 多表查询之多对多】
Mybatis(mybatisplus)
Mybatis
环境:
- JDK1.8
- MysqL5.7
- maven3.6.1
- IDEA
回顾:
- JDBC 增删改查 事务
- MysqL 增删改查
- java基础
- Maven
- Junit
框架:配置文件的。最好的学习方式,看官网
Mybatis官网文档:(https://mybatis.net.cn/index.html)
1.简介
1.1什么是Mybatis?
- MyBatis 是一款优秀的持久层框架
- 它支持自定义 sql、存储过程以及高级映射。
- MyBatis 免除了几乎所有的 JDBC 代码以及设置参数和获取结果集的工作。MyBatis 可以通过简单的 XML 或注解来配置和映射原始类型、接口和 Java POJO(Plain Old Java Objects,普通老式 Java 对象)为数据库中的记录。
- MyBatis 本是apache的一个开源项目iBatis, 2010年这个项目由apache software foundation 迁移到了[google code](https://baike.baidu.com/item/google code/2346604),并且改名为MyBatis 。
- 2013年11月迁移到Github。
如何获得Mybatis
-
maven仓库
-
<!-- https://mvnrepository.com/artifact/org.mybatis/mybatis --> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.5.2</version> </dependency>
-
github (https://github.com/mybatis/mybatis-3)
-
中文文档:https://mybatis.org/mybatis-3/zh/index.html
-
(https://mvnrepository.com/)
1.2、持久化
数据持久化
- 持久化就是将程序的数据在持久状态和瞬时状态转换的过程
- 内存:断电即失
- 数据库(jdbc),io文件持久化。
- 生活:冷藏。罐头
为什么需要持久化?
-
有一些对象,不能让他丢掉。
-
内存太贵了
1.3、持久层
Dao层,Service层,Conreoller层
- 完成持久化工作的代码块
- 层界限十分明显
1.4、为什么需要Mybatis?
-
帮助程序员将数据存入到数据库中
-
方便
-
传统的JDBC代码太复杂了。简化框架。
-
不用Mybatis也可以,更容易上手。技术没有高低之分
-
优点:百度 简单易学 灵活 接触sql与程序代码的耦合性 提供标签 提供对象关系映射标签 提供XML标签
为什么要学? 使用它的人多呀!
2、第一个Mybatis程序
思路:搭建环境-->导入Mybatis-->编写代码-->测试!
2.1环境搭建
- 搭建数据库
create database `mybatis`;
use `mybatis`;
create table `user`(
`id` int(20) not null PRIMARY KEY,
`name` varchar(30) default null,
`pwd` varchar(30) default null
)engine=innodb default charset=utf8;
insert into `user`(`id`,`name`,`pwd`) values(1,'zhangsan','zhangsan'),(2,'lisi','lisi'),(3,'wangwu','wangwu');
-
新建项目
<?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"> <modelVersion>4.0.0</modelVersion> <!--父工程--> <groupId>org.example</groupId> <artifactId>jotian</artifactId> <version>1.0-SNAPSHOT</version> <!--导入依赖--> <dependencies> <!--mydql驱动--> <!-- https://mvnrepository.com/artifact/MysqL/mysql-connector-java --> <dependency> <groupId>MysqL</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.47</version> </dependency> <!--mybatis--> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.5.2</version> </dependency> <!--junit--> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> <scope>test</scope> </dependency> </dependencies> <properties> <maven.compiler.source>8</maven.compiler.source> <maven.compiler.target>8</maven.compiler.target> </properties> </project>
新建一个普通的maven项目
删除src目录
导入maven依赖
2.2、创建一个模块
-
编写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核心配置文件--> <configuration> <environments default="development"> <environment id="development"> <!--事务管理--> <transactionManager type="JDBC"/> <dataSource type="POOLED"> <property name="driver" value="com.MysqL.jdbc.Drivre"/> <property name="url" value="jdbc:MysqL://localhost:3306/mybatis?useSSL=true&useUnicode=true&characterEncoding=UTF-8"/> <property name="username" value="root"/> <property name="password" value="1121"/> </dataSource> </environment> </environments> </configuration>
-
编写mybatis工具类
-
package com.jotian.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; import java.io.InputStream; //sqlSessionFactory --> sqlSession public class MybatisUtils { private static sqlSessionFactory sqlSessionFactory; static{ try { //使用Mybatis第一步:获取sqlSessionFactory对象 String resource = "mybatis-config.xml"; InputStream inputStream = Resources.getResourceAsstream(resource); sqlSessionFactory = new sqlSessionFactoryBuilder().build(inputStream); } catch (IOException e) { e.printstacktrace(); } } //既然有了sqlSessionFactory,故名十一,我们就可以从中获得sqlSession的实例了。 //sqlsession完全包含了面向数据库执行sql执行命令所需要的所有方法。 public static sqlSession getsqlSession(){ return sqlSessionFactory.openSession(); } }
2.3编写代码
-
实体类
package com.jotian.pojo; public class User { private int id; private String name; private String pwd; public User() { } public User(int id, String name, String pwd) { this.id = id; this.name = name; this.pwd = pwd; } public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getPwd() { return pwd; } public void setPwd(String pwd) { this.pwd = pwd; } @Override public String toString() { return "User{" + "id=" + id + ", name='" + name + '\'' + ", pwd='" + pwd + '\'' + '}'; } }
-
Dao接口
package com.jotian.dao; import com.jotian.pojo.User; import java.util.List; public interface UserDao { List<User> getUserList(); }
-
接口实现类 由原来的impl装换成一个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"> <!--namespace 绑定一个对应的Dao/Mapper接口--> <mapper namespace="com.jotin.dao.UserDao"> <!--select查询语句--> <select id="getUserList" resultType="com.jotian.pojo.User"> select * from mybatis.user; </select> </mapper>
2.4 测试
org.apache.ibatis.binding.BindingException: Type interface com.jotian.dao.UserDao is not kNown to the MapperRegistry.
-
junit测试
<!--在build中配置rsources,来防止我们资源导出失败的问题--> <build> <resources> <resource> <directory>src/main/resources</directory> <includes> <include>**/*.properties</include> <include>**/*.xml</include> </includes> <filtering>true</filtering> </resource> <resource> <directory>src/main/java</directory> <includes> <include>**/*.properties</include> <include>**/*.xml</include> </includes> <filtering>false</filtering> </resource> </resources> </build>
-
可能遇到的问题:
- 配置文件没有注册
- 绑定接口错误
- 方法名不对
- 返回类型不对
- Maven导出资源问题
CRUD
事务管理机制
mybatis是默认开启事务机制,增删改需要提交事务(sqlSession.commit())
<?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">
<!--namespace 绑定一个对应的Dao/Mapper接口-->
<mapper namespace="com.jotian.Mapper.UserMapper">
<select id="getUserList" resultType="com.jotian.pojo.User">
select * from user
</select>
</mapper>
1.nameSpace
namespace中的包名要和Dao/mapper接口的包名一致
2.select
选择:查询语句!
-
id:就是对应的namespace中的方法名;
-
resultType:sql语句执行的返回值!
-
parameterType:参数的返回值类型
编写接口
/** * @param id 查询用户的ID * @return User */ User getUserByID(int id);
编写对应的mapper中的sql语句
<select id="getUserByID" parameterType="int" resultType="com.jotian.pojo.User"> select * from user where id = #{id}; </select>
测试
@Test public void Test1() { sqlSession sqlSession = null; try { sqlSession = MybatisUtil.getsqlsession(); UserMapper userMapper = sqlSession.getMapper(UserMapper.class); User user = userMapper.getUserByID(1); System.out.println(user); sqlSession.close(); } catch (Exception e) { e.printstacktrace(); } finally { if (sqlSession != null) { sqlSession.close(); } } }
3.Insert
<insert id="addUser" parameterType="com.jotian.pojo.User">
insert into user(id,name,pwd) values(#{id},#{name},#{pwd});
</insert>
4.update
<update id="updateUser" parameterType="com.jotian.pojo.User">
update user
set name= #{name},pwd=#{pwd}
where id=#{id};
</update>
5.Delete
<delete id="deleteUser" parameterType="com.jotian.pojo.User">
delete from user where id=#{id};
</delete>
6.万能的Map
map中传递参数,直接在sql中取出key即可!
假设,我们的实体类,或者数据库中的表,字段或者参数过多,我们应当考虑使用Map!
/**
* @param map 万能的map
* @return int
*/
int insertUser(Map<String,Object> map);
<insert id="insertUser" parameterType="map">
insert into user(id,name,pwd) values(#{userid},#{username},#{password})
</insert>
@Test
public void Test5(){
sqlSession sqlSession = null;
Map<String,Object> map = new HashMap<>();
map.put("username","wahaha");
map.put("userid",4);
map.put("password","4004");
try{
sqlSession = MybatisUtil.getsqlsession();
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
int count = userMapper.insertUser(map);
if(count>0){
System.out.println("插入成功");
}
}catch (Exception e){
e.printstacktrace();
}finally{
if(sqlSession!=null){
sqlSession.commit();
sqlSession.close();
}
}
}
7.思考题!
模糊查询怎么写?
1.java代码执行的时候,传递通配符% %
List<User> userList = mapper.getserLike("%李%");
2.在sql拼接中使用通配符!
select * from user where name like "%"#{valuse}"%"
4.配置解析
<?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="db.properties">
<property name="username" value="root"/>
<property name="pwd" value="1111"/>
</properties>
<!--可以给实体类起别名-->
<typeAliases>
<typeAlias type="com.jotian.pojo.User" alias="User"/>
</typeAliases>
<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-->
<mapper resource="com/jotian/dao/UserMapper.xml"/>
</mappers>
</configuration>
4.1.核心配置文件
- mybatis-config.xml
- MyBatis 的配置文件包含了会深深影响MyBatis行为的设置和属性的信息。
配置
MyBatis 的配置文件包含了会深深影响 MyBatis 行为的设置和属性信息。 配置文档的顶层结构如下:
configuration(配置)
properties(属性)
settings(设置)
typeAliases(类型别名)
typeHandlers(类型处理器)
objectFactory(对象工厂)
plugins(插件)
environments(环境配置)
environment(环境变量)
transactionManager(事务管理器)
dataSource(数据源)
databaseIdProvider(数据库厂商标识)
mappers(映射器)
4.2.环境配置(environments)
mybatis 可以配置成适应多种环境
不过要记住:尽管可以配置多个环境,但每个sqlSessionFactory实例只能选择一种环境
mybatis默认的事务管理器就是JDBC, 连接池:POOLED
4.3.属性(properties)
我们可以同故宫properties属性来实现引用配置文件
这些属性都是可外部配置且可动态替换的,既可以在典型的java属性文件中配置,亦可以通过properties元素的子元素来传递。【db.properties】
xml文件中的标签数据顺序(properties?,settings?,typeAliases?,typeHandlers?,objectFactory?,objectWrapperFactory?,reflectorFactory?,plugins?,environments?,databaseIdProvider?,mappers?)".
db.properties资源
driver=com.MysqL.jdbc.Driver
url=jdbc:MysqL://localhost:3306/mybatis?useUnicode=true&characterEncoding=utf8
username=root
password=1121
在核心配置文件中映入
mybatis-config.xml
<!--引入外部配置文件-->
<properties resource="db.properties">
<property name="username" value="root"/>
<property name="pwd" value="1111"/>
</properties>
<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>
- 可以直接引入外部文件
- 可以在其中增加一些属性配置
- 如果两个文件有同一个字段,优先使用外部配置文件
4.4.类型别名(typeAliases)
-
类型别名是java类型设置一个短的名字,它只和XML配置有关
-
存在的意义仅在于用来减少类完全限定的冗余。
-
第一种:
<!--可以给实体类起别名--> <typeAliases> <typeAlias type="com.jotian.pojo.User" alias="User"/> </typeAliases>
-
第二种:指定一个包名,MyBatis会在包下面搜索需要的java Bean,比如:烧苗实体类的包,它的默认别名就为这个类的 类名 首字母小写
<!--可以给实体类起别名--> <typeAliases> <package name="com.jotian.pojo"/> </typeAliases>
-
-
在实体类比较小的时候,使用第一种方式 如果实体类十分多,建议使用第二种
-
第一种可以DIY别名,第二种不行 如果非要改,需要在实体上增加注解
@Alias("user") public class User{}
5.设置
这是MyBatis中极为重要的调整设置,他们会改变MyBatis的运行时行为。
logimpl 指定MyBatis所用日志的具体实现,未指定时将自动查找。
cachenabled 全局地开启或关闭配置文件中的所有映射器已经配置的任何缓存
latyLiadingEnables 延迟加载的全局开关,当开启时,所有关联对象都会延迟加载,特定关联关系中可以通过该设置fetchType属性来覆盖该项的开关。
6.其他配置
- typeHandlers(类型处理器)
- objectFactory(对象工厂)
- plugins插件
- mybatis-generator-core
- mybatis-plus
- 通用mapper
7.映射器(mappers)
MapperRegistry:注册绑定我们的Mapper文件:
-
方式一:【推荐使用】
<mapper> <mapper resource="com/jotian/dao/UserMapper.xml"/> </mapper>
-
方式二:使用class文件绑定注册
<mappers> <mapper/> </mappers>
注意点:
- 接口和他的Mapper配置文件必须同名!
- 接口和他的Mapper配置文件必须在同一个包下!
-
方式三:使用扫描包进行注入绑定
<mappers> <mapper name="com.jotian.dao"/> </mappers>
注意点:
- 接口和他的Mapper配置文件必须同名!
- 接口和他的Mapper配置文件必须在同一个包下!
练习时间:
- 将数据库配置文件外部引入
- 实体类别名
- 保证UserMapper接口和UserMappper.xml改为一致!并且放在同一个包下!
9.Lombok
使用步骤:
1.在IDEA中安装lombok插件
2.在项目中导入Lombok的jar包
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.16.14</version>
</dependency>
3.在实体类上加注解即可!
@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
private int id;
private String name;
private String pwd;
}
//IntelliJ Lombok plugin
//A plugin that adds first-class support for Project Lombok Features
@Getter and @Setter
@FieldNameConstants
@ToString
@EqualsAndHashCode
@AllArgsConstructor, @requiredArgsConstructor and @NoArgsConstructor
@Log, @Log4j, @Log4j2, @Slf4j, @XSlf4j, @CommonsLog, @JBossLog, @Flogger, @CustomLog
@Data
@Builder
@SuperBuilder
@Singular
@Delegate
@Value
@Accessors
@Wither
@With
@SneakyThrows
@val
@var
experimental @var
@UtilityClass
//Lombok config system
//Code inspections
//Refactoring actions (lombok and delombok)
说明:
@Date:无参构造、get、set、tostring、hashcode、equals
@AllArgsConstructor:所有有参构造
@NoArgsConstructor:无参构造
@Gerter
@Setter
@Tostring
@EqualsAndHashCode
10.多对一
测试环境搭建
1.导入lombok
<!--lombok-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.16.14</version>
</dependency>
2.新建实体类 Teacher Student
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Student {
private int id;
private String name;
//学生需要关联一个老师
private Teacher teacher;
}
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Teacher {
private int id;
private String name;
}
3.建立Mapper接口
public interface StudentMapper {
}
public interface TeacherMapper {
}
4.建立Mapper.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.jotian.dao.TeacherMapper">
</mapper>
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.jotian.dao.StudentMapper">
</mapper>
5.在核心配置文件中绑定注册我们的Mapper接口或者文件!【方式很多谁心选】
<mappers>
<mapper/>
<mapper/>
<mapper/>
</mappers>
6.测试查询是否成功
按照查询嵌套处理
<!--思路
查询所有的学生信息
根据查询出来的学生的tid,寻找对应的老师!子查询-->
<select id="getStudent" resultMap="StudentTeacher">
select * from student
</select>
<resultMap id="StudentTeacher" type="Student">
<result property="id" column="id"/>
<result property="name" column="name"/>
<!--复杂的属性,我们需要单独处理对象:associatian集合: collection-->
<association property="teacher" column="tid" javaType="Teacher" select="getTeacher"/>
</resultMap>
<select id="getTeacher" resultType="Teacher">
select * from teacher where id = #{id}
</select>
按照结果嵌套处理
<!--按照结果进行嵌套处理-->
<select id="getStudent2" resultMap="StudentTeacher2">
select s.id sid,s.name sname,t.name tname
from student s,teacher t
where s.tid=t.id
</select>
<resultMap id="StudentTeacher2" type="Student">
<result property="id" column="sid"/>
<result property="name" column="sname"/>
<association property="teacher" javaType="Teacher">
<result property="name" column="tname"/>
</association>
</resultMap>
11.一对多
比如:一个老师拥有多个学生! 对于老师而言就是一对多的关系!
1.环境搭建,和刚才一样
实体类
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Teacher {
private int id;
private String name;
//一个老师拥有多个学生
private List<Student> students;
}
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Student {
private int id;
private String name;
private int tid;
}
按结果嵌套处理
按查询嵌套处理
小结:
1.关联-association【一对多】
2.集合 colection【一对多】
3.javaType $ ofType
1.javaType用来指定实体类中属性类型
2.ofType用来指定映射到List或集合中的pojo类型,泛型中的约束类型
注意点:
- 保证sql可读性,尽量保证通俗易懂
- 注意一对多和多对一中,属性名和字段的问题
- 如果问题不好排查错误,可以使用日志,建议使用LOG4J
12.动态sql
什么是动态sql:动态sql就是指根据不同的条件生产不同的sql语句
利用动态sql这一特性可以彻底拜托这种痛苦
1.动态sql元素和JSTL或基于类似XML的文本处理器相似。在MyBatis之前的版本中,有很多元素需要花时间了解,MyBatis 3大大精简了元素种类,现在只需要学习原来一半的元素即可。MyBatis采用强大的基于OGNL的表达式来淘汰其他大部分元素。
if
choose(when , otherwise)
trim(where,set)
foreach
搭建环境
CREATE TABLE `blog`(
`id` varchar(50) NOT NULL COMMENT '博客id',
`title` varchar(100) NOT NULL COMMENT '博客标题',
`author` varchar(30) NOT NULL COMMENT '博客作者'
`create_time` datatime NOT NULL COMMENT '创建时间'
`views` int(30) NOT NULL COMMENT '浏览量'
)ENGINE=InnoDB DEFAULT CHARSET=utf8
创建基础工程
导包
编写 工具类 配置文件
编写实体类
编写实体类对应的Mapper接口 和Mapper.XMl文件
sql
create database `mybatis`;
use `mybatis`;
create table `user`(
`id` int(20) not null PRIMARY KEY,
`name` varchar(30) default null,
`pwd` varchar(30) default null
)engine=innodb default charset=utf8;
insert into `user`(`id`,`name`,`pwd`) values(1,'zhangsan','zhangsan'),(2,'lisi','lisi'),(3,'wangwu','wangwu');
USE mybatis;
CREATE TABLE `TEACHER`(
`ID` INT(10) NOT NULL,
`NAME` VARCHAR(30) DEFAULT NULL,
PRIMARY KEY (`ID`)
) ENGINE = INNODB DEFAULT CHARSET=UTF8;
INSERT INTO TEACHER(`ID`,`NAME`) VALUE (1,'田老师');
CREATE TABLE `STUDENT`(
`ID` INT(10) NOT NULL,
`NAME` VARCHAR(30) DEFAULT NULL,
`TID` INT(10) DEFAULT NULL,
PRIMARY KEY (`ID`),
KEY `FKTID`(`TID`),
CONSTRAINT `FKTID` FOREIGN KEY (`TID`) REFERENCES `TEACHER`(`ID`)
) ENGINE = INNODB DEFAULT CHARSET =UTF8;
INSERT INTO STUDENT(ID,NAME,TID)VALUE (1,'小明',1);
INSERT INTO STUDENT(ID,NAME,TID)VALUE (2,'小红',1);
INSERT INTO STUDENT(ID,NAME,TID)VALUE (3,'小芳',1);
INSERT INTO STUDENT(ID,NAME,TID)VALUE (4,'小白',1);
INSERT INTO student(TID) VALUE (1);
面试高频
慢sql 别人查询花1s 我查询花1000s
- MysqL引擎
- InnoDB底层原理
- 索引
- 索引优化
各种问题!
文件中的需要重复的东西一定要复制,不要手打,出现错误难以寻找!
实现接口的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">
<!--namespace 绑定一个对应的Dao/Mapper接口-->
<mapper namespace="com.jotian.Mapper.UserMapper">
<!--id:就是对应的namespace中的方法名中的方法-->
<select id="getUserList" resultType="com.jotian.pojo.User">
select * from user;
</select>
<select id="getUserByID" parameterType="int" resultType="com.jotian.pojo.User">
select * from user where id = #{id};
</select>
<insert id="addUser" parameterType="com.jotian.pojo.User">
insert into user(id,name,pwd) values(#{id},#{name},#{pwd});
</insert>
<update id="updateUser" parameterType="com.jotian.pojo.User">
update user
set name= #{name},pwd=#{pwd}
where id=#{id};
</update>
<delete id="deleteUser" parameterType="com.jotian.pojo.User">
delete from user where id=#{id};
</delete>
</mapper>
<mapper namespace="com.jotian.Mapper.UserMapper">
namespace一定要是 .
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>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="com.MysqL.jdbc.Driver"/>
<property name="url" value="jdbc:MysqL://localhost:3306/mybatis"/>
<property name="username" value="root"/>
<property name="password" value="1121"/>
</dataSource>
</environment>
</environments>
<mappers>
<!--配置文件一定要注册Mapper-->
<mapper resource="com/jotian/Mapper/UserMapper.xml"/>
</mappers>
</configuration>
<mapper resource="com/jotian/Mapper/UserMapper.xml"/>
这里是 / 这个路径 不要忘记注册mapper!!!
我的成功!
-
Maven约定大于配置。资源过滤!!!
-
配置文件的绑定
-
准备pom.xml文件
<?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"> <modelVersion>4.0.0</modelVersion> <groupId>com.dahua</groupId> <artifactId>Mybatis</artifactId> <version>1.0-SNAPSHOT</version> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <maven.compiler.source>1.8</maven.compiler.source> <maven.compiler.target>1.8</maven.compiler.target> </properties> <dependencies> <!--测试Junit--> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.11</version> <scope>test</scope> </dependency> <!-- mybatis的jar--> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.5.1</version> </dependency> <!-- JDBC--> <dependency> <groupId>MysqL</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.9</version> </dependency> </dependencies> <build> <resources> <resource> <directory>src/main/java</directory> <includes> <include>**/*.properties</include> <include>**/*.xml</include> </includes> <filtering>false</filtering> </resource> </resources> <plugins> <plugin> <artifactId>maven-compiler-plugin</artifactId> <version>3.1</version> <configuration> <source>1.8</source> <target>1.8</target> </configuration> </plugin> </plugins> </build> </project>
-
第一步工具类编写
package com.jotian.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; import java.io.InputStream; public class MybatisUtil { public static sqlSessionFactory sqlSessionFactory; static { try{ String resource = "mybatis-config.xml"; InputStream inputStream = Resources.getResourceAsstream(resource); sqlSessionFactory =new sqlSessionFactoryBuilder().build(inputStream); } catch (IOException e) { e.printstacktrace(); } } public static sqlSession getsqlSession(){ return sqlSessionFactory.openSession(); } }
-
对应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> <environments default="development"> <environment id="development"> <transactionManager type="JDBC"/> <dataSource type="POOLED"> <property name="driver" value="com.MysqL.jdbc.Driver"/> <property name="url" value="jdbc:MysqL://localhost:3306/mybatis"/> <property name="username" value="root"/> <property name="password" value="1121"/> </dataSource> </environment> </environments> <mappers> <!--配置文件一定要注册Mapper--> <mapper resource="com/jotian/Mapper/UserMapper.xml"/> </mappers> </configuration>
-
编写实体类
package com.jotian.pojo; /** * @author jotian */ public class User { private int id; private String name; private String pwd; public User() { } public User(int id, String name, String pwd) { this.id = id; this.name = name; this.pwd = pwd; } public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getPwd() { return pwd; } public void setPwd(String pwd) { this.pwd = pwd; } @Override public String toString() { return "User{" + "id=" + id + ", name='" + name + '\'' + ", pwd='" + pwd + '\'' + '}'; } }
-
编写接口
package com.jotian.Mapper; import com.jotian.pojo.User; import java.util.List; public interface UserMapper { List<User> getUserList(); }
-
接口实现由impl编成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="com.jotian.Mapper.UserMapper"> <select id="getUserList" resultType="com.jotian.pojo.User"> select * from user </select> </mapper>
-
测试类编写
package com.jotian.Mapper; import com.jotian.pojo.User; import com.jotian.utils.MybatisUtil; import org.apache.ibatis.session.sqlSession; import org.junit.Test; import java.util.List; public class UserTest { @Test public void test(){ sqlSession sqlSession = MybatisUtil.getsqlSession(); UserMapper userMapper = sqlSession.getMapper(UserMapper.class); List<User> userList = userMapper.getUserList(); for (User user:userList ) { System.out.println(user); } } }
day63( MYBATIS框架基础1:关于Mybatis框架,创建Mybatis-Spring工程,配置开发环境,基本使用,删除与修改数据)
day63( MYBATIS框架基础1:关于Mybatis框架,创建Mybatis-Spring工程,配置开发环境,基本使用,删除与修改数据)
1.关于Mybatis框架
1.概念:
Mybatis的主要作用是快速实现对关系型数据库中的数据进行访问的框架
在原生的Java技术中,需要使用JDBC实现对数据库中的数据访问,执行过程繁琐且相对固定,使用框架可以有效的提高开发效率
2.创建Mybatis-Spring工程
前提: Mybatis可以不依赖于Spring等框架直接使用的,但是,就需要进行大量的配置,前期配置工作量较大,基于Spring框架目前是业内使用的标准之一,所以,通常会整合Spring与Mybatis,以减少配置
在创建工程时,创建普通的Maven工程即可(不需要选择特定的骨架)
1. 在pom.xml中添加几个依赖项
<dependencies>
<!-- Mybatis的依赖项:mybatis-->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.6</version>
</dependency>
<!-- Mybatis整合Spring的依赖项:mybatis-spring-->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>2.0.6</version>
</dependency>
<!-- Spring的依赖项:spring-context-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.3.14</version>
</dependency>
<!-- Spring JDBC的依赖项:spring-jdbc-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.3.14</version>
</dependency>
<!-- MysqL连接的依赖项:mysql-connector-java-->
<dependency>
<groupId>MysqL</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.21</version>
</dependency>
<!-- 数据库连接池的依赖项:commons-dbcp2-->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-dbcp2</artifactId>
<version>2.8.0</version>
</dependency>
<!-- JUnit测试的依赖项:junit-jupiter-api-->
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<version>5.8.2</version>
<scope>test</scope>
</dependency>
</dependencies>
2.创建测试类
可以在src/test/java下创建测试类,并编写测试方法,例如:
package cn.tedu.mybatis;
import org.junit.jupiter.api.Test;
public class MybatisTests {
@Test
public void contextLoads() {
System.out.println("MybatisTests.contextLoads()");
}
}
由于目前尚未编写实质的代码,以上测试代码也非常简单,应该是可以成功通过测试的,如果不能通过测试,必然是开发工具、开发环境、依赖项、项目创建步骤等问题
3.配置Mybatis的开发环境
1.创建数据库
登录MysqL控制台,创建名为mall_ams的数据库:
CREATE DATABASE mall_ams;
2.在IntelliJ IDEA中配置数据库视图:
http://doc.canglaoshi.org/doc/idea_database/index.html
通过数据库视图的Console面板创建数据表:
create table ams_admin (
id bigint unsigned auto_increment,
username varchar(50) default null unique comment '用户名',
password char(64) default null comment '密码(密文)',
nickname varchar(50) default null comment '昵称',
avatar varchar(255) default null comment '头像URL',
phone varchar(50) default null unique comment '手机号码',
email varchar(50) default null unique comment '电子邮箱',
description varchar(255) default null comment '描述',
is_enable tinyint unsigned default 0 comment '是否启用,1=启用,0=未启用',
last_login_ip varchar(50) default null comment '最后登录IP地址(冗余)',
login_count int unsigned default 0 comment '累计登录次数(冗余)',
gmt_last_login datetime default null comment '最后登录时间(冗余)',
gmt_create datetime default null comment '数据创建时间',
gmt_modified datetime default null comment '数据最后修改时间',
primary key (id)
) comment '管理员' charset utf8mb4;
3.创建datasource.properties配置文件
在src/main/resources下创建datasource.properties配置文件,用于配置连接数据库的参数,例如:
datasource.url=jdbc:MysqL://localhost:3306/mall_ams?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai
datasource.driver=com.MysqL.cj.jdbc.Driver
datasource.username=root
datasource.password=root
提示:以上配置中的属性名称应该添加前缀,避免与系统环境变量冲突,例如在Windows操作系统中,username则表示登录系统的用户名
4.创建SpringConfig类
在cn.tedu.mybatis包下(不存在,则创建)创建SpringConfig类,读取以上配置文件:
@Configuration
@PropertySource("classpath:datasource.properties")
public class SpringConfig {
}
提示:@PropertySource是Spring框架的注解,用于读取properties类型的配置文件,读取到的值将存入到spring容器的Environment对象中
5. 测试方法中补充测试代码:
@Test
public void contextLoads() {
System.out.println("MybatisTests.contextLoads()");
AnnotationConfigApplicationContext ac
= new AnnotationConfigApplicationContext(SpringConfig.class);ConfigurableEnvironment environment = ac.getEnvironment();
System.out.println(environment.getProperty("datasource.url"));
System.out.println(environment.getProperty("datasource.driver"));
System.out.println(environment.getProperty("datasource.username"));System.out.println(environment.getProperty("datasource.password"));ac.close();
}
6. 在SpringConfig中配置一个DataSource对象:
@Configuration
@PropertySource("classpath:datasource.properties")
public class SpringConfig {
@Bean
public DataSource dataSource(Environment env) {
BasicDataSource dataSource = new BasicDataSource();
dataSource.setUrl(env.getProperty("datasource.url"));
dataSource.setDriverClassName(env.getProperty("datasource.driver"));dataSource.setUsername(env.getProperty("datasource.username"));dataSource.setPassword(env.getProperty("datasource.password"));return dataSource;
}
}
7.测试方法中补充测试代码:
@Test
public void testConnection() throws Exception {
AnnotationConfigApplicationContext ac
= new AnnotationConfigApplicationContext(SpringConfig.class);DataSource dataSource = ac.getBean("dataSource"
, DataSource.class);Connection connection = dataSource.getConnection();
System.out.println(connection);
ac.close();
}
4.Mybatis的基本使用
1.作用:
当使用Mybatis实现数据访问时,主要:
编写数据访问的抽象方法
配置抽象方法对应的sql语句
2. 关于抽象方法:
必须定义在某个接口中,这样的接口通常使用Mapper作为名称的后缀,例如AdminMapper
Mybatis框架底层将通过接口代理模式来实现
方法的返回值类型:
如果要执行的数据操作是增、删、改类型的,统一使用int作为返回值类型,表示“受影响的行数” ,也可以使用void,但是不推荐
如果要执行的是查询操作,返回值类型只需要能够装载所需的数据即可
方法的名称:自定义,不要重载,建议风格如下:
插入数据使用insert
作为方法名称中的前缀或关键字
删除数据使用delete
作为方法名称中的前缀或关键字
更新数据使用update
作为方法名称中的前缀或关键字
查询数据时:
如果是统计,使用count
作为方法名称中的前缀或关键字
如果是单个数据,使用get
或find
作为方法名称中的前缀或关键字
如果是列表,使用list
作为方法名称中的前缀或关键字
如果操作数据时有条件,可在以上前缀或关键字右侧添加by字段名
,例如deleteById
方法的参数列表:取决于需要执行的sql语句中有哪些参数,如果有多个参数,可将这些参数封装到同一个类型中,使用封装的类型作为方法的参数类型
例如:假设当需要实现“插入一条管理员数据”,则需要执行的sql语句大致是
insert into ams_admin (username, password, nickname, avatar,phone,email, description, is_enable, last_login_ip, login_count,
gmt_last_login, gmt_create, gmt_modified) values (?,?,? ... ?);
由于以上sql语句中的参数数量较多,则应该将它们封装起来,则在cn.tedu.mybatis包下创建Admin类,声明一系列的属性,对应以上各参数值:
package cn.tedu.mybatis;
import java.time.LocalDateTime;
public class Admin {
private String username; private String password;
private String nickname; private String avatar;
private String phone; private String email;
private String description; private Integer isEnable;
private String lastLoginIp; private Integer loginCount;
private LocalDateTime gmtLastLogin; private LocalDateTime gmtCreate;
private LocalDateTime gmtModified;
// Setters & Getters // toString()
}
在cn.tedu.mybatis包下创建mapper.AdminMapper接口,并在接口中添加“插入1条管理员数据”的抽象方法:
package cn.tedu.mybatis.mapper;
import cn.tedu.mybatis.Admin;
public interface AdminMapper {
int insert(Admin admin);
}
所有用于Mybatis处理数据的接口都必须被Mybatis识别,有2种做法
在每个接口上添加@Mapper注解
【推荐】在配置类上添加@MapperScan注解,指定接口所在的根包
例如,在SpringConfig上添加配置@MapperScan:
@Configuration
@PropertySource("classpath:datasource.properties")
@MapperScan("cn.tedu.mybatis.mapper")
public class SpringConfig {
// ... ...
}
注意:因为Mybatis会扫描以上配置的包,并自动生成包中各接口中的代理对象,所以,千万不要放其它接口文件
接下来,需要配置抽象方法对应的sql语句,这些sql语句推荐配置在XML文件中
可以从 http://doc.canglaoshi.org/config/Mapper.xml.zip下载到XML文件。在项目的src/main/resources下创建mapper文件夹,并将下载得到的XML文件复制到此文件夹中,重命名为AdminMapper.xml。
打开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属性用于配置此XML对应哪个接口 -->
<mapper namespace="cn.tedu.mybatis.mapper.AdminMapper">
<!-- 根据需要执行的sql语句的种类选择需要配置的节点名称-->
<!-- 配置sql的节点的id属性取值为抽象方法名称 -->
<!-- 在节点内部配置sql语句 -->
<!-- sql语句中的参数值使用 #{} 格式的占位符表示 -->
<insert id="insert">
insert into ams_admin (
username, password, nickname, avatar,
phone, email, description, is_enable,
last_login_ip, login_count, gmt_last_login, gmt_create,
gmt_modified
) values (
#{username}, #{password}, #{nickname}, #{avatar},
#{phone}, #{email}, #{description}, #{isEnable},
#{lastLoginIp}, #{loginCount}, #{gmtLastLogin}, #{gmtCreate},#{gmtModified}
)
</insert>
</mapper>
最后,还需要将DataSource配置给Mybatis框架,并且,为Mybatis配置这些XML文件的路径,这2项配置都将通过配置sqlSessionfactorybean来完成
先在datasource.properties中补充一条配置:
mybatis.mapper-locations=classpath:mapper/AdminMapper.xml
在配置类中创建sqlSessionfactorybean类型的对象:
@Bean
public sqlSessionfactorybean sqlSessionfactorybean(DataSource dataSource,@Value("${mybatis.mapper-locations}") Resource mapperLocations){sqlSessionfactorybean sqlSessionfactorybean = new sqlSessionfactorybean();sqlSessionfactorybean.setDataSource(dataSource);
sqlSessionfactorybean.setMapperLocations(mapperLocations);
return sqlSessionfactorybean;
}
在测试类中补充测试方法,以检验是否可以通过调用AdminMapper的insert()方法插入数据:
@Test public void testInsert() { AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(SpringConfig.class);AdminMapper adminMapper = ac.getBean(AdminMapper.class); Admin admin = new Admin(); admin.setUsername("admin001"); admin.setPassword("12345678"); adminMapper.insert(admin); ac.close(); }
如果某数据的id是自动编号,当需要获取新增的数据的id时,需要先使得插入的数据类型中有id对应的属性,则在Admin类中添加id属性:
public class Admin { private Long id; // 原有其它属性及Setter & Getter // 补充id的Setter & Getter // 重新生成toString() }
接下来,在节点配置2个属性,分别是useGeneratedKeys和keyProperty:
<insert id="insert" useGeneratedKeys="true" keyProperty="id">原有代码 </insert>
当配置完成后,Mybatis执行此插入数据的操作后,会将自动编号的id赋值到参数Admin admin的id属性中,以上keyProperty指的就是将自动编号的值放回到参数对象的哪个属性中!
5.删除与修改数据
1.目标(根据id删除某一条数据 )
根据id删除某一条数据
2.执行
sql
delete from ams_admin where id=?
在AdminMapper接口中添加抽象方法:
int deleteById(Long id);
在AdminMapper.xml中配置以上抽象方法映射的sql语句:
<delete id="deleteById"> delete from ams_admin where id=#{id} </delete>
编写并执行测试:
@Test public void testDeleteById() { AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(SpringConfig.class); AdminMapper adminMapper = ac.getBean(AdminMapper.class); Long id = 12L; int rows = adminMapper.deleteById(id); // System.out.println("删除完成,受影响的行数=" + rows); if (rows == 1) { System.out.println("删除成功"); } else { System.out.println("删除失败,尝试删除的数据(id=" + id + ")不存在!"); } ac.close(); }
3.目标(根据 id修改某一条数据 )
4.执行
sql
update ams_admin set password=? where id=?
在AdminMapper接口中添加抽象方法:
int updatePasswordById(@Param("id") Long id, @Param("password") String password);
提示:在默认情况下,当Java程序源代码(.java文件)经过编译后,所有局部的量的名称都会丢失,为使得配置sql语句时可根据指定的名称使用方法中的参数值,需要在方法的各参数前添加@Param以指定名称
如果方法的参数只有1个,则可以不使用@Param指定名称,因为Mybatis可以直接找到此参数的值
在AdminMapper.xml中配置以上抽象方法映射的sql语句:
<update id="updatePasswordById"> update ams_admin set password=#{password} where id=#{id}</update>
提示:以上占位符中的名称是通过@Param注解指定的名称,而不是抽象方法的参数名称
编写并执行测试:
@Test public void testUpdatePasswordById() { AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(SpringConfig.class); AdminMapper adminMapper = ac.getBean(AdminMapper.class); Long id = 12L; String password = "000000"; int rows = adminMapper.updatePasswordById(id, password); if (rows == 1) { System.out.println("修改密码成功"); } else { System.out.println("修改密码失败,尝试访问的数据(id=" + id + ")不存在!"); } ac.close(); }
Fluent Mybatis, 原生Mybatis, Mybatis Plus三者功能对比
使用fluent mybatis可以不用写具体的xml文件,通过java api可以构造出比较复杂的业务sql语句,做到代码逻辑和sql逻辑的合一。不再需要在Dao中组装查询或更新操作,在xml或mapper中再组装参数。那对比原生Mybatis, Mybatis Plus或者其他框架,FluentMybatis提供了哪些便利呢?
需求场景设置
我们通过一个比较典型的业务需求来具体实现和对比下,假如有学生成绩表结构如下:
create table `student_score`
(
id bigint auto_increment comment ''主键ID'' primary key,
student_id bigint not null comment ''学号'',
gender_man tinyint default 0 not null comment ''性别, 0:女; 1:男'',
school_term int null comment ''学期'',
subject varchar(30) null comment ''学科'',
score int null comment ''成绩'',
gmt_create datetime not null comment ''记录创建时间'',
gmt_modified datetime not null comment ''记录最后修改时间'',
is_deleted tinyint default 0 not null comment ''逻辑删除标识''
) engine = InnoDB default charset=utf8;
现在有需求:
统计2000年三门学科(''英语'', ''数学'', ''语文'')及格分数按学期,学科统计最低分,最高分和平均分, 且样本数需要大于1条,统计结果按学期和学科排序
我们可以写SQL语句如下
select school_term,
subject,
count(score) as count,
min(score) as min_score,
max(score) as max_score,
avg(score) as max_score
from student_score
where school_term >= 2000
and subject in (''英语'', ''数学'', ''语文'')
and score >= 60
and is_deleted = 0
group by school_term, subject
having count(score) > 1
order by school_term, subject;
那上面的需求,分别用fluent mybatis, 原生mybatis 和 Mybatis plus来实现一番。
三者实现对比
使用fluent mybatis 来实现上面的功能
我们可以看到fluent api的能力,以及IDE对代码的渲染效果。
换成mybatis原生实现效果
- 定义Mapper接口
public interface MyStudentScoreMapper {
List<Map<String, Object>> summaryScore(SummaryQuery paras);
}
- 定义接口需要用到的参数实体 SummaryQuery
@Data
@Accessors(chain = true)
public class SummaryQuery {
private Integer schoolTerm;
private List<String> subjects;
private Integer score;
private Integer minCount;
}
- 定义实现业务逻辑的mapper xml文件
<select id="summaryScore" resultType="map" parameterType="cn.org.fluent.mybatis.springboot.demo.mapper.SummaryQuery">
select school_term,
subject,
count(score) as count,
min(score) as min_score,
max(score) as max_score,
avg(score) as max_score
from student_score
where school_term >= #{schoolTerm}
and subject in
<foreach collection="subjects" item="item" open="(" close=")" separator=",">
#{item}
</foreach>
and score >= #{score}
and is_deleted = 0
group by school_term, subject
having count(score) > #{minCount}
order by school_term, subject
</select>
- 实现业务接口(这里是测试类, 实际应用中应该对应Dao类)
@RunWith(SpringRunner.class)
@SpringBootTest(classes = QuickStartApplication.class)
public class MybatisDemo {
@Autowired
private MyStudentScoreMapper mapper;
@Test
public void mybatis_demo() {
// 构造查询参数
SummaryQuery paras = new SummaryQuery()
.setSchoolTerm(2000)
.setSubjects(Arrays.asList("英语", "数学", "语文"))
.setScore(60)
.setMinCount(1);
List<Map<String, Object>> summary = mapper.summaryScore(paras);
System.out.println(summary);
}
}
总之,直接使用mybatis,实现步骤还是相当的繁琐,效率太低。那换成mybatis plus的效果怎样呢?
换成mybatis plus实现效果
mybatis plus的实现比mybatis会简单比较多,实现效果如下
如红框圈出的,写mybatis plus实现用到了比较多字符串的硬编码(可以用Entity的get lambda方法部分代替字符串编码)。字符串的硬编码,会给开发同学造成不小的使用门槛,个人觉的主要有2点:
- 字段名称的记忆和敲码困难
- Entity属性跟随数据库字段发生变更后的运行时错误
其他框架,比如TkMybatis在封装和易用性上比mybatis plus要弱,就不再比较了。
生成代码编码比较
fluent mybatis生成代码设置
public class AppEntityGenerator {
static final String url = "jdbc:mysql://localhost:3306/fluent_mybatis_demo?useSSL=false&useUnicode=true&characterEncoding=utf-8";
public static void main(String[] args) {
FileGenerator.build(Abc.class);
}
@Tables(
/** 数据库连接信息 **/
url = url, username = "root", password = "password",
/** Entity类parent package路径 **/
basePack = "cn.org.fluent.mybatis.springboot.demo",
/** Entity代码源目录 **/
srcDir = "spring-boot-demo/src/main/java",
/** Dao代码源目录 **/
daoDir = "spring-boot-demo/src/main/java",
/** 如果表定义记录创建,记录修改,逻辑删除字段 **/
gmtCreated = "gmt_create", gmtModified = "gmt_modified", logicDeleted = "is_deleted",
/** 需要生成文件的表 ( 表名称:对应的Entity名称 ) **/
tables = @Table(value = {"student_score"})
)
static class Abc {
}
}
mybatis plus代码生成设置
public class CodeGenerator {
static String dbUrl = "jdbc:mysql://localhost:3306/fluent_mybatis_demo?useSSL=false&useUnicode=true&characterEncoding=utf-8";
@Test
public void generateCode() {
GlobalConfig config = new GlobalConfig();
DataSourceConfig dataSourceConfig = new DataSourceConfig();
dataSourceConfig.setDbType(DbType.MYSQL)
.setUrl(dbUrl)
.setUsername("root")
.setPassword("password")
.setDriverName(Driver.class.getName());
StrategyConfig strategyConfig = new StrategyConfig();
strategyConfig
.setCapitalMode(true)
.setEntityLombokModel(false)
.setNaming(NamingStrategy.underline_to_camel)
.setColumnNaming(NamingStrategy.underline_to_camel)
.setEntityTableFieldAnnotationEnable(true)
.setFieldPrefix(new String[]{"test_"})
.setInclude(new String[]{"student_score"})
.setLogicDeleteFieldName("is_deleted")
.setTableFillList(Arrays.asList(
new TableFill("gmt_create", FieldFill.INSERT),
new TableFill("gmt_modified", FieldFill.INSERT_UPDATE)));
config
.setActiveRecord(false)
.setIdType(IdType.AUTO)
.setOutputDir(System.getProperty("user.dir") + "/src/main/java/")
.setFileOverride(true);
new AutoGenerator().setGlobalConfig(config)
.setDataSource(dataSourceConfig)
.setStrategy(strategyConfig)
.setPackageInfo(
new PackageConfig()
.setParent("com.mp.demo")
.setController("controller")
.setEntity("entity")
).execute();
}
}
FluentMybatis特性一览
三者对比总结
看完3个框架对同一个功能点的实现, 各位看官肯定会有自己的判断,笔者这里也总结了一份比较。
- | Mybatis Plus | Fluent Mybatis |
---|---|---|
代码生成 | 生成 Entity | 生成Entity, 再通过编译生成 Mapper, Query, Update 和 SqlProvider |
Generator易用性 | 低 | 高 |
和Mybatis的共生关系 | 需替换原有的SqlSessionFactoryBean | 对Mybatis没有任何修改,原来怎么用还是怎么用 |
动态SQL构造方式 | 应用启动时, 根据Entity注解信息构造动态xml片段,注入到Mybatis解析器 | 应用编译时,根据Entity注解,编译生成对应方法的SqlProvider,利用mybatis的Mapper上@InsertProvider @SelectProvider @UpdateProvider注解关联 |
动态SQL结果是否容易DEBUG跟踪 | 不容易debug | 容易,直接定位到SQLProvider方法上,设置断点即可 |
动态SQL构造 | 通过硬编码字段名称, 或者利用Entity的get方法的lambda表达式 | 通过编译手段生成对应的方法名,直接调用方法即可 |
字段变更后的错误发现 | 通过get方法的lambda表达的可以编译发现,通过字段编码的无法编译发现 | 编译时便可发现 |
不同字段动态SQL构造方法 | 通过接口参数方式 | 通过接口名称方式, FluentAPI的编码效率更高 |
语法渲染特点 | 无 | 通过关键变量select, update, set, and, or可以利用IDE语法渲染, 可读性更高 |
Fluent Mybatis,原生Mybatis,Mybatis Plus三者功能对比
本文主要介绍了Fluent Mybatis,原生Mybatis,Mybatis Plus三者功能对比,分享给大家,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
目录
三者实现对比
使用fluent mybatis 来实现上面的功能
换成mybatis原生实现效果
换成mybatis plus实现效果
生成代码编码比较
fluent mybatis生成代码设置
mybatis plus代码生成设置
FluentMybatis特性一览
三者对比总结
Fluent Mybatis介绍和源码
使用fluent mybatis可以不用写具体的xml文件,通过java api可以构造出比较复杂的业务sql语句,做到代码逻辑和sql逻辑的合一。
不用再需要在Dao中组装查询或更新操作,在xml或mapper中再组装次参数。
那对比原生Mybatis, Mybatis Plus或者其他框架,FluentMybatis提供了哪些便利呢?
我们通过一个比较典型的业务需求来具体实现和对比下,假如有学生成绩表结构如下:
create table `student_score` ( id bigint auto_increment comment '主键ID' primary key, student_id bigint not null comment '学号', gender_man tinyint default 0 not null comment '性别, 0:女; 1:男', school_term int null comment '学期', subject varchar(30) null comment '学科', score int null comment '成绩', gmt_create datetime not null comment '记录创建时间', gmt_modified datetime not null comment '记录最后修改时间', is_deleted tinyint default 0 not null comment '逻辑删除标识' ) engine = InnoDB default charset=utf8;
现在有需求:
统计2000年三门学科(‘英语', ‘数学', ‘语文')及格分数按学期,学科统计最低分,最高分和平均分,
且样本数需要大于1条,统计结果按学期和学科排序
我们可以写sql语句如下
select school_term, subject, count(score) as count, min(score) as min_score, max(score) as max_score, avg(score) as max_score from student_score where school_term >= 2000 and subject in ('英语', '数学', '语文') and score >= 60 and is_deleted = 0 group by school_term, subject having count(score) > 1 order by school_term, subject;
那上面的需求,分别用fluent mybatis, 原生mybatis 和 Mybatis plus来实现一番。
三者实现对比
使用fluent mybatis 来实现上面的功能
具体代码
我们可以看到fluent api的能力,以及IDE对代码的渲染效果。
换成mybatis原生实现效果
定义Mapper接口
public interface MyStudentscoreMapper { List> summaryscore(SummaryQuery paras); }
定义接口需要用到的参数实体 SummaryQuery
@Data @Accessors(chain = true) public class SummaryQuery { private Integer schoolTerm; private List subjects; private Integer score; private Integer minCount; }
定义实现业务逻辑的mapper xml文件
select school_term, subject, count(score) as count, min(score) as min_score, max(score) as max_score, avg(score) as max_score from student_score where school_term >= #{schoolTerm} and subject in #{item} and score >= #{score} and is_deleted = 0 group by school_term, subject having count(score) > #{minCount} order by school_term, subject
实现业务接口(这里是测试类, 实际应用中应该对应Dao类)
@RunWith(springrunner.class) @SpringBoottest(classes = QuickStartApplication.class) public class MybatisDemo { @Autowired private MyStudentscoreMapper mapper; @Test public void mybatis_demo() { // 构造查询参数 SummaryQuery paras = new SummaryQuery() .setSchoolTerm(2000) .setSubjects(Arrays.asList("英语", "数学", "语文")) .setscore(60) .setMinCount(1); List> summary = mapper.summaryscore(paras); System.out.println(summary); } }
总之,直接使用mybatis,实现步骤还是相当的繁琐,效率太低。
那换成mybatis plus的效果怎样呢?
换成mybatis plus实现效果
mybatis plus的实现比mybatis会简单比较多,实现效果如下
但正如红框圈出的,写mybatis plus实现用到了比较多字符串的硬编码(可以用Entity的get lambda方法部分代替字符串编码)。字符串的硬编码,会给开发同学造成不小的使用门槛,个人觉的主要有2点:
字段名称的记忆和敲码困难
Entity属性跟随数据库字段发生变更后的运行时错误
其他框架,比如TkMybatis在封装和易用性上比mybatis plus要弱,就不再比较了。
生成代码编码比较
fluent mybatis生成代码设置
public class AppEntityGenerator { static final String url = "jdbc:MysqL://localhost:3306/fluent_mybatis_demo?useSSL=false&useUnicode=true&characterEncoding=utf-8"; public static void main(String[] args) { FileGenerator.build(Abc.class); } @Tables( /** 数据库连接信息 **/ url = url, username = "root", password = "password", /** Entity类parent package路径 **/ basePack = "cn.org.fluent.mybatis.springboot.demo", /** Entity代码源目录 **/ srcDir = "spring-boot-demo/src/main/java", /** Dao代码源目录 **/ daoDir = "spring-boot-demo/src/main/java", /** 如果表定义记录创建,记录修改,逻辑删除字段 **/ gmtCreated = "gmt_create", gmtModified = "gmt_modified", logicDeleted = "is_deleted", /** 需要生成文件的表 ( 表名称:对应的Entity名称 ) **/ tables = @Table(value = {"student_score"}) ) static class Abc { } }mybatis plus代码生成设置
public class CodeGenerator { static String dbUrl = "jdbc:MysqL://localhost:3306/fluent_mybatis_demo?useSSL=false&useUnicode=true&characterEncoding=utf-8"; @Test public void generateCode() { GlobalConfig config = new GlobalConfig(); DataSourceConfig dataSourceConfig = new DataSourceConfig(); dataSourceConfig.setDbType(DbType.MysqL) .setUrl(dbUrl) .setUsername("root") .setPassword("password") .setDriverName(Driver.class.getName()); StrategyConfig strategyConfig = new StrategyConfig(); strategyConfig .setCapitalMode(true) .setEntityLombokModel(false) .setNaming(NamingStrategy.underline_to_camel) .setColumnNaming(NamingStrategy.underline_to_camel) .setEntityTableFieldAnnotationEnable(true) .setFieldPrefix(new String[]{"test_"}) .setInclude(new String[]{"student_score"}) .setLogicDeleteFieldName("is_deleted") .setTableFillList(Arrays.asList( new TableFill("gmt_create", FieldFill.INSERT), new TableFill("gmt_modified", FieldFill.INSERT_UPDATE))); config .setActiveRecord(false) .setIdType(IdType.AUTO) .setoutputDir(System.getProperty("user.dir") + "/src/main/java/") .setFileOverride(true); new AutoGenerator().setGlobalConfig(config) .setDataSource(dataSourceConfig) .setStrategy(strategyConfig) .setPackageInfo( new PackageConfig() .setParent("com.mp.demo") .setController("controller") .setEntity("entity") ).execute(); } }
FluentMybatis特性一览
三者对比总结
看完3个框架对同一个功能点的实现, 各位看官肯定会有自己的判断,笔者这里也总结了一份比较。
-
Mybatis Plus
Fluent Mybatis
代码生成
生成 Entity, Mapper, Wrapper等文件, 并且Generator很好用
只生成Entity, 再通过编译生成 Mapper, Query, Update 和 sqlProvider
和Mybatis的共生关系
需要替换原有的sqlSessionfactorybean
对Mybatis没有任何修改,原来怎么用还是怎么用
动态sql构造方式
应用启动时, 根据Entity注解信息构造动态xml片段,注入到Mybatis解析器
应用编译时,根据Entity注解,编译生成对应方法的sqlProvider,利用mybatis的Mapper上@InsertProvider @SelectProvider @UpdateProvider注解关联
动态sql结果是否容易DEBUG跟踪
不容易debug
容易,直接定位到sqlProvider方法上,设置断点即可
动态sql构造
通过硬编码字段名称, 或者利用Entity的get方法的lambda表达式
通过编译手段生成对应的方法名,直接调用方法即可
字段变更后的错误发现
通过get方法的lambda表达的可以编译发现,通过字段编码的无法编译发现
编译时便可发现
不同字段动态sql构造方法
通过接口参数方式
通过接口名称方式, FluentAPI的编码效率更高
语法渲染特点
无
通过关键变量select, update, set, and, or可以利用IDE语法渲染, 可读性更高
Fluent Mybatis介绍和源码
Fluent Mybatis文档&示例
Fluent Mybatis源码, github
到此这篇关于Fluent Mybatis,原生Mybatis,Mybatis Plus三者功能对比的文章就介绍到这了,更多相关Fluent Mybatis,原生Mybatis,Mybatis Plus内容请搜索小编以前的文章或继续浏览下面的相关文章希望大家以后多多支持小编!
java day55【 Mybatis 连接池与事务深入 、 Mybatis 的动态 SQL 语句、 Mybatis 多表查询之一对多 、 Mybatis 多表查询之多对多】
第1章 Mybatis 连接池与事务深入
1.1 Mybatis 的连接池技术
1.1.1 Mybatis 连接池的分类
1.1.2 Mybatis 中数据源的配置
1.1.3 Mybatis 中 DataSource 的存取
1.1.4 Mybatis 中连接的获取过程分析
1.2 Mybatis 的事务控制
1.2.1 JDBC 中事务的回顾
1.2.2 Mybatis 中事务提交方式
1.2.3 Mybatis 自动提交事务的设置
第2章 Mybatis 的动态 SQL 语句
2.1 动态 SQL 之标签
2.1.1 持久层 Dao 接口
2.1.2 持久层 Dao 映射配置
2.1.3 测试
2.2 动态 SQL 之标签
2.2.1 持久层 Dao 映射配置
2.3 动态标签之标签
2.3.1 需求
2.3.1.1 在 QueryVo 中加入一个 List 集合用于封装参数
2.3.2 持久层 Dao 接口
2.3.3 持久层 Dao 映射配置
2.3.3.1 编写测试方法
2.4 Mybatis 中简化编写的 SQL 片段
2.4.1 定义代码片段
2.4.2 引用代码片段
第3章 Mybatis 多表查询之一对多
3.1 一对一查询(多对一)
3.1.1 方式一
3.1.1.1 定义账户信息的实体类
3.1.1.2 编写 Sql 语句
3.1.1.3 定义 AccountUser 类
3.1.1.4 定义账户的持久层 Dao 接口
3.1.1.5 定义 AccountDao.xml 文件中的查询配置信息
3.1.1.6 创建 AccountTest 测试类
3.1.1.7 小结:
3.1.2 方式二
3.1.2.1 修改 Account 类
在 Account 类中加入 User 类的对象作为 Account 类的一个属性。
3.1.2.2 修改 AccountDao 接口中的方法
3.1.2.3 重新定义 AccountDao.xml 文件
3.1.2.4 在 AccountTest 类中加入测试方法
3.2 一对多查询
3.2.1 编写 SQL 语句
3.2.2 User 类加入 List
3.2.3 用户持久层 Dao 接口中加入查询方法
3.2.4 用户持久层 Dao 映射文件配置
3.2.5 测试方法
第4章 Mybatis 多表查询之多对多
4.1 实现 Role 到 User 多对多
4.1.1 用户与角色的关系模型
4.1.2 业务要求及实现 SQL
4.1.3 编写角色实体类
4.1.4 编写 Role 持久层接口
4.1.5 编写映射文件
4.1.6 编写测试类
4.2 实现 User 到 Role 的多对多
4.2.1 User 到 Role 的多对多
4.2.2 作业:实现 User 到 Role 的一对多查询
今天关于Mybatis和mybatisplus的介绍到此结束,谢谢您的阅读,有关day63( MYBATIS框架基础1:关于Mybatis框架,创建Mybatis-Spring工程,配置开发环境,基本使用,删除与修改数据)、Fluent Mybatis, 原生Mybatis, Mybatis Plus三者功能对比、Fluent Mybatis,原生Mybatis,Mybatis Plus三者功能对比、java day55【 Mybatis 连接池与事务深入 、 Mybatis 的动态 SQL 语句、 Mybatis 多表查询之一对多 、 Mybatis 多表查询之多对多】等更多相关知识的信息可以在本站进行查询。
本文标签: