由 杨柳依 于2020年2月26日创建,最近更新于 2020年2月26日。
数据库准备
运行脚本tb_user.sql:
# 创建数据库mybatisplus(字符集utf8mb4是utf8的超集,兼容四字节的unicode)CREATE DATABASE `mybatisplus` CHARACTER SET 'utf8';# 选择mybatisplus数据库USE mybatisplus;# 创建tb_user表CREATE TABLE `tb_user` (`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键ID',`user_name` varchar(20) NOT NULL COMMENT '用户名',`password` varchar(20) NOT NULL COMMENT '密码',`name` varchar(30) DEFAULT NULL COMMENT '姓名',`age` int(11) DEFAULT NULL COMMENT '年龄',`email` varchar(50) DEFAULT NULL COMMENT '邮箱',PRIMARY KEY (`id`)) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;# 填充数据INSERT INTO `tb_user` VALUES (1, 'zhangsan', '123456', '张三', 18, 'test1@itcast.cn');INSERT INTO `tb_user` VALUES (2, 'lisi', '123456', '李四', 20, 'test2@itcast.cn');INSERT INTO `tb_user` VALUES (3, 'wangwu', '123456', '王五', 19, 'test3@itcast.cn');INSERT INTO `tb_user` VALUES (4, 'zhaoliu', '123456', '赵六', 21, 'test4@itcast.cn');INSERT INTO `tb_user` VALUES (5, 'sunqi', '666666', '孙七', 24, 'test5@itcast.cn');
基本整合
1. MyBatis-Plus与普通Maven项目进行整合
新建Maven项目,groupId为cn.itcast.mp,artifactId为itcast-mybatis-plus-simple,Project name为itcast-mybatis-plus-simple,POM文件如下:
<?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>cn.itcast.mp</groupId><artifactId>itcast-mybatis-plus-simple</artifactId><version>1.0-SNAPSHOT</version><!-- 指定Java版本 --><properties><java.version>1.8</java.version><maven.compiler.source>1.8</maven.compiler.source><maven.compiler.target>1.8</maven.compiler.target></properties><dependencies><!-- mybatis-plus插件依赖 --><dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus</artifactId><version>3.3.1</version></dependency><!-- MySQL驱动 --><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>5.1.6</version></dependency><!-- druid连接池 --><dependency><groupId>com.alibaba</groupId><artifactId>druid</artifactId><version>1.0.11</version></dependency><!-- 简化bean代码的工具包 --><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional><version>1.18.4</version></dependency><!-- junit单元测试 --><dependency><groupId>org.junit.jupiter</groupId><artifactId>junit-jupiter-api</artifactId><version>5.5.2</version></dependency><!-- 日志 --><dependency><groupId>org.slf4j</groupId><artifactId>slf4j-log4j12</artifactId><version>1.6.4</version></dependency></dependencies></project>
在src/main/resources/下新建日志配置文件log4j.properties,内容如下:
log4j.rootLogger=DEBUG,A1log4j.appender.A1=org.apache.log4j.ConsoleAppenderlog4j.appender.A1.layout=org.apache.log4j.PatternLayoutlog4j.appender.A1.layout.ConversionPattern=[%t] [%c]-[%p] %m%n
在src/main/resources/下新建mybatis配置文件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"/><!-- mysql配置信息 --><dataSource type="POOLED"><property name="driver" value="com.mysql.jdbc.Driver"/><property name="url" value="jdbc:mysql://localhost:3306/mybatisplus"/><property name="username" value="root"/><property name="password" value="123456"/></dataSource></environment></environments><!-- mapper文件路径(不可少) --><mappers><mapper resource="UserMapper.xml"/></mappers></configuration>
在src/main/resources/下新建mapper文件UserMapper.xml,就算没有自定义查询也必须要有该文件,内容如下:
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd"><mapper namespace="cn.itcast.mp.simple.mapper.UserMapper"></mapper>
上面的
namespace用于指定对应的UserMapper类,type和resultType用于指定对应实体User类
在src/main/java/下新建包cn.itcast.mp.simple.pojo和cn.itcast.mp.simple.mapper,在pojo包内新建User类:
package cn.itcast.mp.simple.pojo;import com.baomidou.mybatisplus.annotation.TableName;import lombok.AllArgsConstructor;import lombok.Data;import lombok.NoArgsConstructor;@Data // 作用于类上,是以下注解的集合:@ToString @EqualsAndHashCode @Getter @Setter @RequiredArgsConstructor@NoArgsConstructor // 作用于类上,用于生成构造函数@AllArgsConstructor // 作用于类上,用于生成构造函数@TableName("tb_user") // 指定对应数据库表名public class User {private Long id;private String userName;private String password;private String name;private Integer age;private String email;}
在mapper包内新建UserMapper类:
package cn.itcast.mp.simple.mapper;import cn.itcast.mp.simple.pojo.User;import com.baomidou.mybatisplus.core.mapper.BaseMapper;import java.util.List;public interface UserMapper extends BaseMapper<User> {}
注意,使用接口
UserMapper继承MyBatis-Plus提供的基类BaseMapper<T>即可使用MyBatis-Plus提供的功能
至此,准备工作完成,我们可以测试MyBatis-Plus是否能正常工作了,在src/test/java/下新建同名包cn.itcast.mp.simple,在simple包内新建测试类TestMybatisPlus:
package cn.itcast.mp.simple;import cn.itcast.mp.simple.mapper.UserMapper;import cn.itcast.mp.simple.pojo.User;import com.baomidou.mybatisplus.core.MybatisSqlSessionFactoryBuilder;import org.apache.ibatis.io.Resources;import org.apache.ibatis.session.SqlSession;import org.apache.ibatis.session.SqlSessionFactory;import org.junit.jupiter.api.Test;import java.io.InputStream;import java.util.List;public class TestMybatisPlus {@Testpublic void testFindAll() throws Exception {String config = "mybatis-config.xml";InputStream inputStream = Resources.getResourceAsStream(config);// 使用MybatisSqlSessionFactoryBuilder完成整合SqlSessionFactory sqlSessionFactory = new MybatisSqlSessionFactoryBuilder().build(inputStream);SqlSession sqlSession = sqlSessionFactory.openSession();UserMapper userMapper = sqlSession.getMapper(UserMapper.class);// 测试查询List<User> users = userMapper.selectList(null);users.forEach(System.out::println);}}
运行结果如下:
==> Preparing: SELECT id,user_name,password,name,age,email FROM tb_user==> Parameters:<== Total: 5User(id=1, userName=zhangsan, password=123456, name=张三, age=18, email=test1@itcast.cn)User(id=2, userName=lisi, password=123456, name=李四, age=20, email=test2@itcast.cn)User(id=3, userName=wangwu, password=123456, name=王五, age=19, email=test3@itcast.cn)User(id=4, userName=zhaoliu, password=123456, name=赵六, age=21, email=test4@itcast.cn)User(id=5, userName=sunqi, password=666666, name=孙七, age=24, email=test5@itcast.cn)
可以看到,UserMapper的selectList方法我们没有定义,该方法是MyBatis-Plus提供的。
如果我们需要使用自定义方法,可以在UserMapper类中新建方法:
public interface UserMapper extends BaseMapper<User> {// 使用ResultMap映射字段名List<User> findAll();// sql语句内重命名List<User> findAll2();}
由于User类中字段与数据库中字段名不完全一致,我们使用2种方法来处理,在UserMapper.xml文件mapper节点下加入以下内容:
<!-- 配置别名 --><resultMap id="userMap" type="cn.itcast.mp.simple.pojo.User"><!--主键字段对应--><id property="id" column="id"/><!--非主键字段对应(每个都要对应,就算一模一样)--><result property="userName" column="user_name"/><result property="password" column="password"/><result property="name" column="name"/><result property="age" column="age"/><result property="email" column="email"/></resultMap><!--配置查询所有(使用配置别名)--><select id="findAll" resultMap="userMap">select * from tb_user;</select><!--配置查询所有(使用查询时别名)--><select id="findAll2" resultType="cn.itcast.mp.simple.pojo.User">select id, user_name userName, password, name, age, email from tb_user;</select>
在TestMybatisPlus类新建测试方法testCustomFindAll:
@Testpublic void testCustomFindAll() throws Exception {String config = "mybatis-config.xml";InputStream inputStream = Resources.getResourceAsStream(config);// 使用MybatisSqlSessionFactoryBuilder完成整合SqlSessionFactory sqlSessionFactory = new MybatisSqlSessionFactoryBuilder().build(inputStream);SqlSession sqlSession = sqlSessionFactory.openSession();UserMapper userMapper = sqlSession.getMapper(UserMapper.class);// 测试查询1List<User> users1 = userMapper.findAll();users1.forEach(System.out::println);// 测试查询2List<User> users2 = userMapper.findAll2();users2.forEach(System.out::println);}
结果为:
==> Preparing: select * from tb_user;==> Parameters:<== Total: 5User(id=1, userName=zhangsan, password=123456, name=张三, age=18, email=test1@itcast.cn)User(id=2, userName=lisi, password=123456, name=李四, age=20, email=test2@itcast.cn)User(id=3, userName=wangwu, password=123456, name=王五, age=19, email=test3@itcast.cn)User(id=4, userName=zhaoliu, password=123456, name=赵六, age=21, email=test4@itcast.cn)User(id=5, userName=sunqi, password=666666, name=孙七, age=24, email=test5@itcast.cn)==> Preparing: select id, user_name userName, password, name, age, email from tb_user;==> Parameters:<== Total: 5User(id=1, userName=zhangsan, password=123456, name=张三, age=18, email=test1@itcast.cn)User(id=2, userName=lisi, password=123456, name=李四, age=20, email=test2@itcast.cn)User(id=3, userName=wangwu, password=123456, name=王五, age=19, email=test3@itcast.cn)User(id=4, userName=zhaoliu, password=123456, name=赵六, age=21, email=test4@itcast.cn)User(id=5, userName=sunqi, password=666666, name=孙七, age=24, email=test5@itcast.cn)
2. MyBatis-Plus与Spring项目进行整合
新建Maven项目,groupId为cn.itcast.mp,artifactId为itcast-mybatis-plus-spring,Project name为itcast-mybatis-plus-spring,POM文件如下:
<?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>cn.itcast.mp</groupId><artifactId>itcast-mybatis-plus-spring</artifactId><version>1.0-SNAPSHOT</version><properties><!-- 指定Java版本 --><java.version>1.8</java.version><maven.compiler.source>1.8</maven.compiler.source><maven.compiler.target>1.8</maven.compiler.target><!-- 指定Spring版本 --><spring.version>5.1.6.RELEASE</spring.version></properties><dependencies><!-- Spring相关 --><dependency><groupId>org.springframework</groupId><artifactId>spring-webmvc</artifactId><version>${spring.version}</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-jdbc</artifactId><version>${spring.version}</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-test</artifactId><version>${spring.version}</version></dependency><!-- mybatis-plus插件依赖 --><dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus</artifactId><version>3.3.1</version></dependency><!-- MySQL驱动 --><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>5.1.6</version></dependency><!-- druid连接池 --><dependency><groupId>com.alibaba</groupId><artifactId>druid</artifactId><version>1.0.11</version></dependency><!-- 简化bean代码的工具包 --><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional><version>1.18.4</version></dependency><!-- junit单元测试 --><dependency><groupId>org.junit.jupiter</groupId><artifactId>junit-jupiter-api</artifactId><version>5.5.2</version></dependency><!-- 日志 --><dependency><groupId>org.slf4j</groupId><artifactId>slf4j-log4j12</artifactId><version>1.6.4</version></dependency></dependencies></project>
在src/main/resources/下新建日志配置文件log4j.properties,内容如下:
log4j.rootLogger=DEBUG,A1log4j.appender.A1=org.apache.log4j.ConsoleAppenderlog4j.appender.A1.layout=org.apache.log4j.PatternLayoutlog4j.appender.A1.layout.ConversionPattern=[%t] [%c]-[%p] %m%n
在src/main/resources/下新建数据库配置文件jdbc.properties,内容如下:
jdbc.driver=com.mysql.jdbc.Driverjdbc.url=jdbc:mysql://localhost:3306/mybatisplusjdbc.username=rootjdbc.password=123456
在src/main/resources/下新建Spring配置文件applicationContext.xml,内容如下:
<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:context="http://www.springframework.org/schema/context"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context.xsd"><context:property-placeholder location="classpath:*.properties"/><!-- 定义数据源 --><bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"destroy-method="close"><property name="url" value="${jdbc.url}"/><property name="username" value="${jdbc.username}"/><property name="password" value="${jdbc.password}"/><property name="driverClassName" value="${jdbc.driver}"/><property name="maxActive" value="10"/><property name="minIdle" value="5"/></bean><!-- 这里使用MP提供的sqlSessionFactory,完成了Spring与MP的整合 --><bean id="sqlSessionFactory"class="com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean"><property name="dataSource" ref="dataSource"/></bean><!-- 扫描mapper接口,使用的依然是Mybatis原生的扫描器 --><bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"><property name="basePackage" value="cn.itcast.mp.simple.mapper"/></bean></beans>
在src/main/java/下新建包cn.itcast.mp.spring.pojo和cn.itcast.mp.spring.mapper,在pojo包内新建User类:
package cn.itcast.mp.spring.pojo;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@NoArgsConstructor
@AllArgsConstructor
@TableName("tb_user")
public class User {
private Long id;
private String userName;
private String password;
private String name;
private Integer age;
private String email;
}
在mapper包内新建UserMapper类:
package cn.itcast.mp.spring.mapper;
import cn.itcast.mp.spring.pojo.User;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
public interface UserMapper extends BaseMapper<User> {
}
接入完成,接下来测试MyBatis-Plus是否能正常工作,在src/test/java/下新建包cn.itcast.mp.spring,在spring包内新建测试类TestMyBatisPlusWithSpring:
package cn.itcast.mp.spring;
import cn.itcast.mp.spring.mapper.UserMapper;
import cn.itcast.mp.spring.pojo.User;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import java.util.List;
@ExtendWith(SpringExtension.class)
@ContextConfiguration(locations = "classpath:applicationContext.xml") // 指定Spring配置文件
public class TestMyBatisPlusWithSpring {
@Autowired
private UserMapper userMapper;
@Test
public void testSelectList() {
List<User> users = userMapper.selectList(null);
users.forEach(System.out::println);
}
}
注意,由于test文件夹没有resources文件,所以直接运行会报错,可以将src/main/resources文件夹复制到test/文件夹下,再运行testSelectList方法,结果如下:
==> Preparing: SELECT id,user_name,password,name,age,email FROM tb_user
==> Parameters:
<== Total: 5
User(id=1, userName=zhangsan, password=123456, name=张三, age=18, email=test1@itcast.cn)
User(id=2, userName=lisi, password=123456, name=李四, age=20, email=test2@itcast.cn)
User(id=3, userName=wangwu, password=123456, name=王五, age=19, email=test3@itcast.cn)
User(id=4, userName=zhaoliu, password=123456, name=赵六, age=21, email=test4@itcast.cn)
User(id=5, userName=sunqi, password=666666, name=孙七, age=24, email=test5@itcast.cn)
3. MyBatis-Plus与SpringBoot项目进行整合
用IDEA新建SpringBoot项目,Group为cn.itcast.mp,Artifact为itcast-mybatis-plus-springboot,Name为itcast-mybatis-plus-springboot,Package为cn.itcast.mp.springboot,选择Lombok、JDBC API、MySQL Driver依赖。
在pom.xml中添加依赖:
<!-- mybatis-plus的SpringBoot支持 -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.3.1</version>
</dependency>
<!-- druid连接池 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.0.11</version>
</dependency>
在配置文件application.properties中添加如下内容:
# 项目名称
spring.application.name=itcast-mybatis-plus-springboot
# 开启彩色日志
spring.output.ansi.enabled=always
# 数据库连接
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/mp?serverTimezone=GMT%2B8&useUnicode=true&characterEncoding=utf8&useSSL=false
spring.datasource.username=root
spring.datasource.password=123456
# 开启SQL执行日志
logging.level.cn.itcast.mp.springboot.mapper=debug
在cn.itcast.mp.springboot包下新建pojo.User类:
package cn.itcast.mp.springboot.pojo;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@NoArgsConstructor
@AllArgsConstructor
@TableName("tb_user")
public class User {
@TableId(type = IdType.AUTO) // 指定id为自增长类型
private Long id;
private String userName;
@TableField(select = false) // 查询时不返回该字段
private String password;
private String name;
private Integer age;
@TableField(value = "email") // 指定数据库中的表字段名
private String mail;
@TableField(exist = false) // 在数据库中不存在
private String address;
}
在cn.itcast.mp.springboot包下新建mapper.UserMapper类:
package cn.itcast.mp.springboot.mapper;
import cn.itcast.mp.springboot.pojo.User;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
public interface UserMapper extends BaseMapper<User> {
}
在cn.itcast.mp.springboot包下新建config.MyBatisPlusConfig类:
package cn.itcast.mp.springboot.config;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.context.annotation.Configuration;
@Configuration
@MapperScan("cn.itcast.mp.springboot.mapper")
public class MyBatisPlusConfig {
}
准备工作完成,在ItcastMybatisPlusSpringbootApplicationTests类中注入UserMapper,并新建测试方法test:
@Autowired
private UserMapper userMapper;
// 测试功能
@Test
public void test() {
List<User> users = userMapper.selectList(null);
users.forEach(System.out::println);
}
运行方法,结果为:
==> Preparing: SELECT id,user_name,name,age,email AS mail FROM tb_user
==> Parameters:
<== Total: 5
User(id=1, userName=zhangsan, password=null, name=张三, age=18, mail=test1@itcast.cn, address=null)
User(id=2, userName=lisi, password=null, name=李四, age=20, mail=test2@itcast.cn, address=null)
User(id=3, userName=wangwu, password=null, name=王五, age=19, mail=test3@itcast.cn, address=null)
User(id=4, userName=zhaoliu, password=null, name=赵六, age=21, mail=test4@itcast.cn, address=null)
User(id=5, userName=sunqi, password=null, name=孙七, age=24, mail=test5@itcast.cn, address=null)
注意,userName字段能正确显示,是因为MyBatis Plus自动驼峰为true(MyBatis自动驼峰默认为false),可通过mybatis-plus.configuration.map-underscore-to-camel-case=false来设置;password字段使用@TableField(select = false)设置查询时不返回该字段内容;mail字段使用@TableField(value = "email")设置数据库中字段名;address字段使用@TableField(exist = false)指明数据库中不存在该字段。
基本使用
以下操作均以上一步操作中的SpringBoot项目作为示范,其它项目类似
1. 配置文件
可以在application.properties中指定MyBatis-Plus的配置文件路径:
# MyBatis-Plus全局配置文件,config-location和configuration不能同时使用
mybatis-plus.config-location=classpath:mybatis-config.xml
在同级目录下创建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>
</configuration>
也可以直接在application.properties中进行配置:
# 实体对象的扫描包,自定义mapper文件时可以只用写类名
mybatis-plus.type-aliases-package=cn.itcast.mp.springboot.pojo
# 指定Mapper文件路径,有*代表可以扫描所有依赖的classpath下的文件,没有*只扫描当前resources目录下的文件
mybatis-plus.mapper-locations=classpath*:mybatis/*.xml
# 全局id生成策略
mybatis-plus.global-config.db-config.id-type=auto
# 全局表名前缀
mybatis-plus.global-config.db-config.table-prefix=tb_
2. 插入
在ItcastMybatisPlusSpringbootApplicationTests类中新建测试方法testInsert:
@Test
public void testInsert() {
User user = new User();
user.setUserName("caocao");
user.setPassword("123456");
user.setName("曹操");
user.setAge(30);
user.setMail("1@itcast.cn");
// INSERT INTO tb_user ( user_name, password, name, age, email ) VALUES ( ?, ?, ?, ?, ? )
int result = userMapper.insert(user); // 返回数据库受影响的行数
System.out.println("result => " + result);
// 获取自增长id
System.out.println("id => " + user.getId());
}
3. 更新
3.1 根据主键进行更新
// 根据主键进行更新
@Test
public void testUpdateById() {
User user = new User();
user.setId(1L);
user.setAge(19);
// UPDATE tb_user SET age=? WHERE id=?
int result = userMapper.updateById(user);
System.out.println("result => " + result);
}
3.2 根据条件进行更新(使用QueryWrapper)
// 根据条件进行更新(使用QueryWrapper)
@Test
public void testUpdate() {
User user = new User();
user.setAge(19);
user.setPassword("666");
QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper.eq("user_name", "zhangsan");
// UPDATE tb_user SET password=?, age=? WHERE (user_name = ?)
int result = userMapper.update(user, wrapper);
System.out.println("result => " + result);
}
3.3 根据条件进行更新(使用UpdateWrapper)
// 根据条件进行更新(使用UpdateWrapper)
@Test
public void testUpdate2() {
UpdateWrapper<User> wrapper = new UpdateWrapper<>();
wrapper.set("age", 21).set("password", "999") // 更新字段
.eq("user_name", "zhangsan"); // 条件
// UPDATE tb_user SET age=?,password=? WHERE (user_name = ?)
int result = userMapper.update(null, wrapper);
System.out.println("result => " + result);
}
4. 删除
4.1 根据id删除数据
// 根据id删除数据
@Test
public void testDeleteById() {
// DELETE FROM tb_user WHERE id=?
int result = userMapper.deleteById(6);
System.out.println("result => " + result);
}
4.2 根据条件删除数据(使用Map)
// 根据条件删除数据(使用Map)
@Test
public void testDeleteByMap() {
Map<String, Object> map = new HashMap<>();
// 多条件是and关系
map.put("user_name", "zhangsan");
map.put("password", "999");
// DELETE FROM tb_user WHERE password = ? AND user_name = ?
int result = userMapper.deleteByMap(map);
System.out.println("result => " + result);
}
4.3 根据条件删除数据(使用QueryWrapper)
// 根据条件删除数据(使用QueryWrapper)
@Test
public void testDelete() {
// 用法1
// QueryWrapper<User> wrapper = new QueryWrapper<>();
// wrapper.eq("user_name", "caocao")
// .eq("password", "123456"); // 条件之间加上".or()"可以变成"或"
// 用法2
User user = new User();
user.setPassword("123456");
user.setUserName("lisi");
QueryWrapper<User> wrapper = new QueryWrapper<>(user);
// DELETE FROM tb_user WHERE user_name=? AND password=?
int result = userMapper.delete(wrapper);
System.out.println("result => " + result);
}
4.4 根据id批量删除
// 根据id批量删除
@Test
public void testDeleteBatchIds() {
// DELETE FROM tb_user WHERE id IN ( ? , ? )
int result = userMapper.deleteBatchIds(Arrays.asList(7, 8));
System.out.println("result => " + result);
}
5. 查询
5.1 根据id查询
// 根据id查询
@Test
public void testSelectById() {
// SELECT id,user_name,name,age,email AS mail FROM tb_user WHERE id=?
User user = userMapper.selectById(3);
System.out.println(user);
}
5.2 根据id批量查询
// 根据id批量查询
@Test
public void testSelectBatchIds() {
// SELECT id,user_name,name,age,email AS mail FROM tb_user WHERE id IN ( ? , ? , ? , ? )
List<User> users = userMapper.selectBatchIds(Arrays.asList(3, 4, 5, 100));
users.forEach(System.out::println);
}
5.3 查询一条数据
// 查询一条数据
@Test
public void testSelectOne() {
QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper.eq("user_name", "sunqi")
.or().eq("id", "100"); // 结果超过1条时会抛出异常
// SELECT id,user_name,name,age,email AS mail FROM tb_user WHERE (user_name = ? OR id = ?)
User user = userMapper.selectOne(wrapper);
System.out.println(user);
}
5.4 查询记录条数
// 查询记录条数
@Test
public void testSelectCount() {
QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper.gt("age", 24); // age>24
// SELECT COUNT( 1 ) FROM tb_user WHERE (age > ?)
int result = userMapper.selectCount(wrapper);
System.out.println("result => " + result);
}
5.5 查询符合条件的集合
// 查询符合条件的集合
@Test
public void testSelectList() {
QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper.le("age", 24); // age<=24
// 当参数为null时同样会把null当做sql语句的一部分,如果想忽略值为null的条件,可以使用同名方法
// wrapper.le(age != null, "age", 24); 这样当age为null时则不会将age作为查询条件之一
wrapper.like("email", "test"); // 多条件之间默认是AND关系
// SELECT id,user_name,name,age,email AS mail FROM tb_user WHERE (age <= ? AND email LIKE ?)
List<User> users = userMapper.selectList(wrapper); // wrapper为null则为查询所有
users.forEach(System.out::println);
}
5.6 分页查询
分页查询需要先配置分页插件,以下两种方式二选一即可:
在
mybatis-config.xml配置文件中configuration节点下添加插件:xml <plugins> <plugin interceptor="com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor"></plugin> </plugins>在
MyBatisPlusConfig类中添加插件:java // 配置分页插件 @Bean public PaginationInterceptor paginationInterceptor() { return new PaginationInterceptor(); }
然后即可进行分页查询:
// 分页查询
@Test
public void testSelectPage() {
Page<User> page = new Page<>(2, 2); // 查询第2页,每页2条
QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper.like("email", "test");
// SELECT COUNT(1) FROM tb_user WHERE (email LIKE ?)
// SELECT id,user_name,name,age,email AS mail FROM tb_user WHERE (email LIKE ?) LIMIT ?,?
Page<User> iPage = userMapper.selectPage(page, wrapper);
System.out.println("数据总条数:" + iPage.getTotal());
System.out.println("数据总页数:" + iPage.getPages());
System.out.println("当前页数:" + iPage.getCurrent());
iPage.getRecords().forEach(System.out::println);
}
5.7 自定义方法
自定义查询可以采用注解,也可以采用配置文件的方式。在UserMapper接口中新建方法:
@Select("select * from tb_user where id=#{id}")
User findById(long id);
User findByName(String name);
在resources文件夹下新建文件mybatis/UserMapper.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="cn.itcast.mp.springboot.mapper.UserMapper">
<select id="findByName" resultType="User">
select id, user_name, password, name, age, email as mail
from tb_user
where name = #{name}
</select>
</mapper>
然后就可以使用自定义方法了:
// 自定义方法
@Test
public void testConstomFind() {
User user = userMapper.findById(3L);
System.out.println(user);
User user2 = userMapper.findByName("王五");
System.out.println(user2);
}
5.8 条件构造器 —— allEq
// 条件构造器 —— allEq
@Test
public void testAllEq() {
Map<String, Object> params = new HashMap<>();
params.put("name", "李四");
params.put("age", "20");
params.put("password", null);
QueryWrapper<User> wrapper = new QueryWrapper<>();
// SELECT id,user_name,name,age,email AS mail FROM tb_user WHERE (password IS NULL AND name = ? AND age = ?)
// wrapper.allEq(params); // 包括null值比较
// SELECT id,user_name,name,age,email AS mail FROM tb_user WHERE (name = ? AND age = ?)
// wrapper.allEq(params, false); // 不包括null值比较
// SELECT id,user_name,name,age,email AS mail FROM tb_user WHERE (password IS NULL AND age = ?)
wrapper.allEq((k, v) -> (k.equals("age") || k.equals("id") || k.equals("password")), params); // 符合表达式才作为查询条件
List<User> users = userMapper.selectList(wrapper);
users.forEach(System.out::println);
}
5.9 基本比较操作
常用比较操作符如下:
| 方法 | eq | ne | gt | ge | lt | le | between | notBetween |
|---|---|---|---|---|---|---|---|---|
| 操作 | = | !=或者<> | > | >= | < | <= | BETWEEN 值1 AND 值2 | NOT BETWEEN 值1 AND 值2 |
| 方法 | in | notIn |
|---|---|---|
| 操作 | IN (value.get(0), value.get(1),…) | NOT IN (value.get(0), value.get(1),…) |
// 基本比较操作
@Test
public void testCompare() {
QueryWrapper<User> wrapper = new QueryWrapper<>();
// SELECT id,user_name,name,age,email AS mail FROM tb_user WHERE (password = ? AND age >= ? AND name IN (?,?,?))
wrapper.eq("password", "123456")
.ge("age", 20)
.in("name", "李四", "王五", "赵六");
List<User> users = userMapper.selectList(wrapper);
users.forEach(System.out::println);
}
5.10 模糊查询
| 方法 | like | likeLeft | likeRight |
|---|---|---|---|
| 操作 | 左右模糊 | 左边模糊(以给定值结尾) | 右边模糊(以给定值开头) |
// 模糊查询
@Test
public void testLike() {
QueryWrapper<User> wrapper = new QueryWrapper<>();
// wrapper.likeLeft("name", "五");
wrapper.likeRight("age", 2); // 数字也可以进行模糊匹配(先转成字符串)
// SELECT id,user_name,name,age,email AS mail FROM tb_user WHERE (age LIKE ?)
List<User> users = userMapper.selectList(wrapper);
users.forEach(System.out::println);
}
5.11 排序
| 方法 | orderBy | orderByAsc | orderByDesc |
|---|---|---|---|
| 操作 | 默认升序 | 升序 | 降序 |
@Test
public void testOrderBy() {
QueryWrapper<User> wrapper = new QueryWrapper<>();
// SELECT id,user_name,name,age,email AS mail FROM tb_user ORDER BY password DESC,age DESC
// wrapper.orderByDesc("password", "age"); // 先按password倒序,再按age倒序
// SELECT id,user_name,name,age,email AS mail FROM tb_user ORDER BY password DESC,age ASC
wrapper.orderByDesc("password") // 先按password倒序
.orderByAsc("age"); // 再按age升序
List<User> users = userMapper.selectList(wrapper);
users.forEach(System.out::println);
}
5.12 逻辑操作符
多条件连接默认为AND,多条件之间使用.or()进行连接则表示OR:
// 逻辑操作符
@Test
public void testOr() {
QueryWrapper<User> wrapper = new QueryWrapper<>();
// SELECT id,user_name,name,age,email AS mail FROM tb_user WHERE (name = ? OR age = ?)
wrapper.eq("name", "王五")
.or().eq("age", 21);
List<User> users = userMapper.selectList(wrapper);
users.forEach(System.out::println);
}
5.13 指定查询字段
// 指定查询字段
@Test
public void testSelect() {
QueryWrapper<User> wrapper = new QueryWrapper<>();
// SELECT id,name,age FROM tb_user WHERE (name = ? OR age = ?)
wrapper.eq("name", "王五")
.or().eq("age", 21)
.select("id", "name", "age"); // 指定查询字段
List<User> users = userMapper.selectList(wrapper);
users.forEach(System.out::println);
}
ActiveRecord
Active Record 是一种数据访问设计模式,它可以帮助你实现数据对象Object到关系数据库的映射,数据对象自身负责持久化。
将User类继承Model<T>类即可:
public class User extends Model<User> {
// ...
}
在src/test/java/cn/itcast/mp/springboot文件夹下新建一个测试类ActiveRecordTest,无须注入UserMapper即可直接使用数据对象自身提供的数据持久化方法,方法名与使用Mapper类一致:
package cn.itcast.mp.springboot;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest
public class ActiveRecordTest {
// 无须注入UserMapper
// 根据主键查询
@Test
public void testSelectById() {
User user = new User();
user.setId(2L);
// SELECT id,user_name,name,age,email AS mail FROM tb_user WHERE id=?
User result = user.selectById(); // 或者直接向方法传入id
System.out.println(result);
}
// 插入
@Test
public void testInsert() {
User user = new User();
user.setUserName("liubei");
user.setPassword("666");
user.setName("刘备");
user.setAge(30);
user.setMail("liubei@itcast.cn");
// INSERT INTO tb_user ( user_name, password, name, age, email ) VALUES ( ?, ?, ?, ?, ? )
boolean result = user.insert();
System.out.println("result => " + result);
}
// 根据主键更新
@Test
public void testUpdateById() {
User user = new User();
user.setId(12L);
user.setAge(31);
// UPDATE tb_user SET age=? WHERE id=?
boolean result = user.updateById(); // 这里不接收参数
System.out.println("result => " + result);
}
// 根据条件更新
@Test
public void testUpdate() {
User user = new User();
user.setPassword("111111");
UpdateWrapper<User> wrapper = new UpdateWrapper<>();
wrapper.eq("user_name", "liubei");
// UPDATE tb_user SET password=? WHERE (user_name = ?)
boolean result = user.update(wrapper);
System.out.println("result => " + result);
}
// 根据主键删除
@Test
public void testDeleteById() {
User user = new User();
user.setId(10L);
// DELETE FROM tb_user WHERE id=?
boolean result = user.deleteById(); // 或者直接向方法传入id
System.out.println("result => " + result);
}
// 根据条件删除
@Test
public void testDelete() {
User user = new User();
QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper.eq("name", "刘备");
// DELETE FROM tb_user WHERE (name = ?)
boolean result = user.delete(wrapper);
System.out.println("result => " + result);
}
// 根据条件查询
@Test
public void testSelect() {
User user = new User();
QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper.ge("age", 25);
// SELECT id,user_name,name,age,email AS mail FROM tb_user WHERE (age >= ?)
List<User> users = user.selectList(wrapper);
users.forEach(System.out::println);
}
}
Oracle中使用序列生成主键值
MySQL中可以设定主键自增长,但是Oracle数据库不支持设置,需要使用序列来生成id值。
1. 数据库准备
这里使用docker进行安装Oracle,如果已有Oracle环境,该步骤可以省略。
# 拉取镜像
docker pull sath89/oracle-12c
# 创建容器
docker create --name=oracle -p 1521:1521 sath89/oracle-12c
# 启动容器
docker start oracle && docker logs -f oracle
# 出现以下内容即启动成功
Database ready to use. Enjoy! ;)
# 用户名:system
# 密码:oracle
使用navicat进行连接,注意连接类型为Basic,服务名为xe。
接下来创建表及序列(注意,Oracle不支持#注释,只能使用--注释):
-- 创建表,表名以及字段名都要大写
CREATE TABLE "TB_USER" (
"ID" NUMBER(20) VISIBLE NOT NULL,
"USER_NAME" VARCHAR2(255 BYTE) VISIBLE,
"PASSWORD" VARCHAR2(255 BYTE) VISIBLE,
"NAME" VARCHAR2(255 BYTE) VISIBLE,
"AGE" NUMBER(10) VISIBLE,
"EMAIL" VARCHAR2(255 BYTE) VISIBLE
);
-- 创建序列
CREATE SEQUENCE SEQ_USER START WITH 1 INCREMENT BY 1;
在Navicat中选择其它选项卡,点击序列,可以查看到我们刚刚创建的SEQ_USER序列。
2. Java准备
由于版权原因,Maven中央仓库中没有Oracle的jdbc驱动包,我们手动将驱动包安装到Maven仓库,在ojdbc8.jar所在目录下运行以下命令:
mvn install:install-file -DgroupId=com.oracle -DartifactId=ojdbc8 -Dversion=19.3.0 -Dpackaging=jar -Dfile=ojdbc8.jar
安装完成后ojdbc8.jar的Maven坐标为,并添加到SpringBoot项目的POM文件中:
<dependency>
<groupId>com.oracle</groupId>
<artifactId>ojdbc8</artifactId>
<version>19.3.0</version>
</dependency>
接着修改配置文件application.properties,将数据库连接修改为:
# Oracle设置
spring.datasource.driver-class-name=oracle.jdbc.OracleDriver
spring.datasource.url=jdbc:oracle:thin:@49.233.88.245:1521:xe
spring.datasource.username=system
spring.datasource.password=oracle
在MyBatisPlusConfig配置类中配置生成器:
// 配置Oracle序列生成器
@Bean
public OracleKeyGenerator oracleKeyGenerator() {
return new OracleKeyGenerator();
}
接着在User上添加注解@KeySequence(value = "SEQ_USER"),修改id生成策略:
// ...
@KeySequence(value = "SEQ_USER")
public class User extends Model<User> {
@TableId(type = IdType.INPUT) // 指定id为输入类型
private Long id;
// ...
}
3. 测试
运行方法ItcastMybatisPlusSpringbootApplicationTests#testInsert(),成功插入一条数据,运行结果如下:
==> Preparing: SELECT SEQ_USER.NEXTVAL FROM DUAL
==> Parameters:
<== Total: 1
==> Preparing: INSERT INTO tb_user (id, user_name, password, name, age, email) VALUES (?,?,?,?,?,?)
==> Parameters: 1(Long), caocao(String), 123456(String), 曹操(String), 30(Integer), 1@itcast.cn(String)
<== Updates: 1
result => 1
id => 1
插件
1. 插件机制
在src/main/java/cn/itcast/mp/springboot/目录下新建一个包plugins用于放置插件,在plugins包下新建MyInterceptor类:
package cn.itcast.mp.springboot.plugins;
import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.plugin.*;
import java.util.Properties;
@Intercepts({@Signature(
type = Executor.class,
method = "update",
args = {MappedStatement.class, Object.class})})
public class MyInterceptor implements Interceptor {
@Override
public Object intercept(Invocation invocation) throws Throwable {
// 拦截方法,具体业务逻辑编写的位置
return invocation.proceed();
}
@Override
public Object plugin(Object target) {
// 创建target对象的代理对象,目的是将当前拦截器加入到该对象中
return Plugin.wrap(target, this);
}
@Override
public void setProperties(Properties properties) {
// 属性设置
}
}
将MyInterceptor配置到MyBatisPlusConfig中:
// 注入自定义拦截器(插件)
@Bean
public MyInterceptor myInterceptor() {
return new MyInterceptor();
}
2. SQL分析插件
该插件只能在开发环境中使用,不建议在生产环境中使用(性能原因)
在MyBatisPlusConfig中进行配置:
// SQL分析插件
@Bean
public SqlExplainInterceptor sqlExplainInterceptor() {
SqlExplainInterceptor sqlExplainInterceptor = new SqlExplainInterceptor();
List<ISqlParser> list = new ArrayList<>();
list.add(new BlockAttackSqlParser()); // 全表更新/删除阻断器
// 添加解析器
sqlExplainInterceptor.setSqlParserList(list);
return sqlExplainInterceptor;
}
测试,在ActiveRecordTest类中添加测试方法,运行会抛出异常:
// 测试全表更新阻断
@Test
public void testUpdateAll() {
User user = new User();
user.setPassword("111111");
boolean result = user.update(null);
System.out.println("result => " + result);
}
3. 性能分析插件[TODO]
性能分析拦截器,用于输出每条SQL语句及其执行时间,可以设置最大执行时间,超过时间会抛出异常。官方推荐使用p6spy。
添加依赖:
<dependency>
<groupId>p6spy</groupId>
<artifactId>p6spy</artifactId>
<version>3.7.0</version>
</dependency>
添加配置文件spy.properties:
4. 乐观锁插件
意图:当更新一条记录的时候,希望这条记录没有被别人更新
实现: ①取出记录时,获取当前version;
②更新时带上version;
③执行更新时,`set version=newVersion where version=oldVersion`
④如果version不对则更新失败
在MyBatisPlusConfig中进行配置:
// 乐观锁插件
@Bean
public OptimisticLockerInterceptor optimisticLockerInterceptor() {
return new OptimisticLockerInterceptor();
}
为表添加version字段,并且设置初始值为1:
ALTER TABLE `tb_user`
ADD COLUMN `version` int(10) NULL AFTER `email`;
UPDATE `tb_user` SET `version`=1;
为实体对象User添加version字段:
// 乐观锁版本字段
@Version
private Integer version;
新建测试方法testUpdateVersion():
// 测试乐观锁
@Test
public void testUpdateVersion() {
User user = new User();
user.setId(4L);
Integer version = user.selectById().getVersion();
System.out.println("插入之前的version:" + version);
user.setPassword("222222");
user.setVersion(version);
System.out.println(user.getVersion()); // 这里还是之前的版本号
// UPDATE tb_user SET password=?, version=? WHERE id=? AND version=?
boolean result = user.updateById();
System.out.println("version => " + user.getVersion()); // 不管成功与否版本号均会自增
System.out.println("result => " + result);
}
