环境
- IDEA
- springboot
- maven
- mysql5.7
开始
1.首先需要准备一张表user
CREATE TABLE user
(
id BIGINT(20) NOT NULL COMMENT '主键ID',
name VARCHAR(30) NULL DEFAULT NULL COMMENT '姓名',
age INT(11) NULL DEFAULT NULL COMMENT '年龄',
email VARCHAR(50) NULL DEFAULT NULL COMMENT '邮箱',
PRIMARY KEY (id)
);
INSERT INTO user (id, name, age, email) VALUES
(1, 'Jone', 18, 'test1@baomidou.com'),
(2, 'Jack', 20, 'test2@baomidou.com'),
(3, 'Tom', 28, 'test3@baomidou.com'),
(4, 'Sandy', 21, 'test4@baomidou.com'),
(5, 'Billie', 24, 'test5@baomidou.com');
2.创建一个springboot初始化工程
根据需要选择
完整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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.4.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.king</groupId>
<artifactId>mybatis_plus</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>mybatis_plus</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.3.1.tmp</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
3.在application.yml
中配置mysql
数据源
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
username: root
password: 123456
url: jdbc:mysql://localhost:3306/mybatis?useUnicode=true&characterEncoding=utf8&serverTimezone=UTC
4.编写表对应的实体类User
@Data
@NoArgsConstructor
@AllArgsConstructor
public class User {
private Long Id;
private String name;
private Integer age;
private String email;
}
5.编写操作实体类的 Mapper 类,直接继承 BaseMapper,这是 mybatis-plus 封装好的类。
6.先得在启动类里扫描 Mapper 类,即添加 @MapperScan
注解
@SpringBootApplication
//mapper类所在的目录路径
@MapperScan("com.king.mybatis_plus.mapper")
public class MybatisPlusApplication {
public static void main(String[] args) {
SpringApplication.run(MybatisPlusApplication.class, args);
}
}
7.编写测试类
@SpringBootTest
class MybatisPlusApplicationTests {
@Autowired(required = false)
private UserMapper userMapper;
/**
* 查询
*/
@Test
public void testSelect(){
/*查询所有的数据UserMapper
中的 selectList() 方法的参数为 MP 内置的条件封装器 Wrapper,
所以不填写就是无任何条件*/
List<User> list=userMapper.selectList(null);
for (User user:list){
System.out.println(user);
}
//根据主键查询
System.out.println("记录:");
System.out.println(userMapper.selectById(1));
}
/**
* 添加
*/
@Test
public void testInsert(){
//主键会自动生成
User user=new User();
user.setName("king");
user.setAge(20);
user.setEmail("123456@qq.com");
System.out.println("插入结果:"+userMapper.insert(user));
}
/**
* 删除
*/
@Test
public void testDelete(){
System.out.println("删除结果:"+userMapper.deleteById(1));
}
/**
* 修改
*/
@Test
public void testUpdate(){
User user=new User();
user.setId(2L);
user.setName("ting");
user.setAge(30);
user.setEmail("2345@qq.com");
System.out.println("修改结果:"+userMapper.updateById(user));
}
}
好的,到这里简单的CRUD就好了
注解
下面来看一下mybatis-plus的一些注解吧
@TableName
描述:表名注解
属性 | 类型 | 必须指定 | 默认值 | 描述 |
---|---|---|---|---|
value | String | 否 | “” | 表名 |
schema | String | 否 | “” | schema |
keepGlobalPrefix | boolean | 否 | false | 是否保持使用全局的 tablePrefix 的值(如果设置了全局 tablePrefix 且自行设置了 value 的值) |
resultMap | String | 否 | “” | xml 中 resultMap 的 id |
autoResultMap | boolean | 否 | false | 是否自动构建 resultMap 并使用(如果设置 resultMap 则不会进行 resultMap 的自动构建并注入) |
关于autoResultMap
的说明:
mp会自动构建一个ResultMap
并注入到mybatis里(一般用不上).下面讲两句: 因为mp底层是mybatis,所以一些mybatis的常识你要知道,mp只是帮你注入了常用crud到mybatis里 注入之前可以说是动态的(根据你entity的字段以及注解变化而变化),但是注入之后是静态的(等于你写在xml的东西) 而对于直接指定typeHandler
,mybatis只支持你写在2个地方:
- 定义在resultMap里,只作用于select查询的返回结果封装
- 定义在
insert
和update
sql的#{property}
里的property
后面(例:#{property,typehandler=xxx.xxx.xxx}
),只作用于设置值
而除了这两种直接指定typeHandler
,mybatis有一个全局的扫描你自己的typeHandler
包的配置,这是根据你的property
的类型去找typeHandler
并使用.
@TableId
- 描述:主键注解
属性 | 类型 | 必须指定 | 默认值 | 描述 |
---|---|---|---|---|
value | String | 否 | “” | 主键字段名 |
type | Enum | 否 | IdType.NONE | 主键类型 |
#IdType
值 | 描述 |
---|---|
AUTO | 数据库ID自增 |
NONE | 无状态,该类型为未设置主键类型(注解里等于跟随全局,全局里约等于 INPUT) |
INPUT | insert前自行set主键值 |
ASSIGN_ID | 分配ID(主键类型为Number(Long和Integer)或String)(since 3.3.0),使用接口IdentifierGenerator 的方法nextId (默认实现类为DefaultIdentifierGenerator 雪花算法) |
ASSIGN_UUID | 分配UUID,主键类型为String(since 3.3.0),使用接口IdentifierGenerator 的方法nextUUID (默认default方法) |
ID_WORKER | 分布式全局唯一ID 长整型类型(please use ASSIGN_ID ) |
UUID | 32位UUID字符串(please use ASSIGN_UUID ) |
ID_WORKER_STR | 分布式全局唯一ID 字符串类型(please use ASSIGN_ID ) |
#@TableField
- 描述:字段注解(非主键)
属性 | 类型 | 必须指定 | 默认值 | 描述 |
---|---|---|---|---|
value | String | 否 | “” | 数据库字段名 |
el | String | 否 | “” | 映射为原生 #{ ... } 逻辑,相当于写在 xml 里的 #{ ... } 部分 |
exist | boolean | 否 | true | 是否为数据库表字段 |
condition | String | 否 | “” | 字段 where 实体查询比较条件,有值设置则按设置的值为准,没有则为默认全局的 %s=#{%s} ,参考 |
update | String | 否 | “” | 字段 update set 部分注入, 例如:update="%s+1":表示更新时会set version=version+1(该属性优先级高于 el 属性) |
insertStrategy | Enum | N | DEFAULT | 举例:NOT_NULL: insert into table_a(<if test="columnProperty != null">column</if>) values (<if test="columnProperty != null">#{columnProperty}</if>) |
updateStrategy | Enum | N | DEFAULT | 举例:IGNORED: update table_a set column=#{columnProperty} |
whereStrategy | Enum | N | DEFAULT | 举例:NOT_EMPTY: where <if test="columnProperty != null and columnProperty!=''">column=#{columnProperty}</if> |
fill | Enum | 否 | FieldFill.DEFAULT | 字段自动填充策略 |
select | boolean | 否 | true | 是否进行 select 查询 |
keepGlobalFormat | boolean | 否 | false | 是否保持使用全局的 format 进行处理 |
jdbcType | JdbcType | 否 | JdbcType.UNDEFINED | JDBC类型 (该默认值不代表会按照该值生效) |
typeHandler | Class<? extends TypeHandler> | 否 | UnknownTypeHandler.class | 类型处理器 (该默认值不代表会按照该值生效) |
numericScale | String | 否 | “” | 指定小数点后保留的位数 |
关于jdbcType
和typeHandler
以及numericScale
的说明:
numericScale
只生效于 update 的sql. jdbcType
和typeHandler
如果不配合@TableName#autoResultMap = true
一起使用,也只生效于 update 的sql. 对于typeHandler
如果你的字段类型和set进去的类型为equals
关系,则只需要让你的typeHandler
让Mybatis加载到即可,不需要使用注解
FieldStrategy
值 | 描述 |
---|---|
IGNORED | 忽略判断 |
NOT_NULL | 非NULL判断 |
NOT_EMPTY | 非空判断(只对字符串类型字段,其他类型字段依然为非NULL判断) |
DEFAULT | 追随全局配置 |
FieldFill
值 | 描述 |
---|---|
DEFAULT | 默认不处理 |
INSERT | 插入时填充字段 |
UPDATE | 更新时填充字段 |
INSERT_UPDATE | 插入和更新时填充字段 |
更多注解可以看官方文档:https://baomidou.com/guide/annotation.html
代码生成器
AutoGenerator 是 MyBatis-Plus 的代码生成器,通过 AutoGenerator 可以快速生成 Entity、Mapper、Mapper XML、Service、Controller 等各个模块的代码,极大的提升了开发效率。与 mybatis 中的 mybatis-generator-core 类似。
1、创建一个新的springboot工程:
目录结构:
2、完整的pom依赖:
【大家可以使用我的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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.4.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.king</groupId>
<artifactId>mybatis_plus_generator</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>mybatis_plus_generator</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<!-- mybatisPlus 核心库 -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.1.0</version>
</dependency>
<!-- mybatis plus 代码生成器 -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-generator</artifactId>
<version>3.0.6</version>
</dependency>
<dependency>
<groupId>org.freemarker</groupId>
<artifactId>freemarker</artifactId>
<version>2.3.20</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
3、运行配置文件
配置文件(大家根据自己的工程进行修改相应的东西):
/**
* 代码生成器类
*
* @author king
* @version 1.0
* @date 2020/10/29 15:53
*/
public class CodeGenerator {
/**
* <p>
* 读取控制台内容
* </p>
*/
public static String scanner(String tip) {
Scanner scanner = new Scanner(System.in);
StringBuilder help = new StringBuilder();
help.append("请输入" + tip + ":");
System.out.println(help.toString());
if (scanner.hasNext()) {
String ipt = scanner.next();
if (StringUtils.isNotEmpty(ipt)) {
return ipt;
}
}
throw new MybatisPlusException("请输入正确的" + tip + "!");
}
public static void main(String[] args) {
// 代码生成器
AutoGenerator mpg = new AutoGenerator();
// 全局配置
GlobalConfig gc = new GlobalConfig();
final String projectPath = System.getProperty("user.dir");
gc.setOutputDir(projectPath + "/src/main/java");
gc.setAuthor("king");
gc.setBaseResultMap(true);
gc.setBaseColumnList(true);
// 是否打开输出目录 默认为true
gc.setOpen(false);
mpg.setGlobalConfig(gc);
// 数据源配置
DataSourceConfig dsc = new DataSourceConfig();
dsc.setUrl("jdbc:mysql://localhost:3306/mybatis?useUnicode=true&useSSL=false&characterEncoding=utf8&serverTimezone=UTC");
dsc.setDriverName("com.mysql.jdbc.Driver");
dsc.setUsername("root");
dsc.setPassword("123456");
mpg.setDataSource(dsc);
// 包配置
final PackageConfig pc = new PackageConfig();
// pc.setModuleName(scanner("模块名"));
pc.setParent("com.king");
mpg.setPackageInfo(pc);
// 自定义配置
InjectionConfig cfg = new InjectionConfig() {
@Override
public void initMap() {
// to do nothing
}
};
// 如果模板引擎是 freemarker
String templatePath = "/templates/mapper.xml.ftl";
// 如果模板引擎是 velocity
// String templatePath = "/templates/mapper.xml.vm";
// 自定义输出配置
List<FileOutConfig> focList = new ArrayList<FileOutConfig>();
// 自定义配置会被优先输出
focList.add(new FileOutConfig(templatePath) {
@Override
public String outputFile(TableInfo tableInfo) {
// 自定义输出文件名 , 如果你 Entity 设置了前后缀、此处注意 xml 的名称会跟着发生变化!!
return projectPath + "/src/main/resources/mapper/" + tableInfo.getEntityName() + "Mapper" + StringPool.DOT_XML;
}
});
cfg.setFileOutConfigList(focList);
mpg.setCfg(cfg);
// 配置模板
TemplateConfig templateConfig = new TemplateConfig();
// 配置自定义输出模板
// 指定自定义模板路径,注意不要带上.ftl/.vm, 会根据使用的模板引擎自动识别
// templateConfig.setEntity("templates/entity2.java");
// templateConfig.setService();
// templateConfig.setController();
templateConfig.setXml(null);
mpg.setTemplate(templateConfig);
// 策略配置
StrategyConfig strategy = new StrategyConfig();
strategy.setNaming(NamingStrategy.underline_to_camel);
strategy.setColumnNaming(NamingStrategy.underline_to_camel);
// strategy.setSuperEntityClass("com.fame.common.BaseEntity");
strategy.setEntityLombokModel(true);
strategy.setRestControllerStyle(true);
// strategy.setSuperControllerClass("com.fame.common.BaseController");
strategy.setInclude(scanner("表名,多个英文逗号分割").split(","));
//strategy.setSuperEntityColumns("id");
// strategy.setControllerMappingHyphenStyle(true);
strategy.setTablePrefix("sys");
mpg.setStrategy(strategy);
mpg.setTemplateEngine(new FreemarkerTemplateEngine());
mpg.execute();
}
}
4、自动生成了这些实体类
,业务类
,控制层类
,xml文件
等等
5、在启动类上需要加@MapperScanner
,用来扫描mapper类
@SpringBootApplication
@MapperScan("com.king.mapper")
public class MybatisPlusGeneratorApplication {
public static void main(String[] args) {
SpringApplication.run(MybatisPlusGeneratorApplication.class, args);
}
}
6、yml
文件配置
server:
port: 8089
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/mybatis?useUnicode=true&characterEncoding=utf8&serverTimezone=UTC
username: root
password: 123456
# mybatis-plus相关配置
mybatis-plus:
# xml扫描,多个目录用逗号或者分号分隔(告诉 Mapper 所对应的 XML 文件位置)
mapper-locations: classpath:mapper/*.xml
# 以下配置均有默认值,可以不设置
global-config:
db-config:
#主键类型 AUTO:"数据库ID自增" INPUT:"用户输入ID",ID_WORKER:"全局唯一ID (数字类型唯一ID)", UUID:"全局唯一ID UUID";
id-type: ID_WORKER
#字段策略 IGNORED:"忽略判断" NOT_NULL:"非 NULL 判断") NOT_EMPTY:"非空判断"
field-strategy: IGNORED
#数据库类型
db-type: MYSQL
# 指定实体类的包
type-aliases-package: com.king.entity
configuration:
# 是否开启自动驼峰命名规则映射:从数据库列名到Java属性驼峰命名的类似映射
map-underscore-to-camel-case: true
# 如果查询结果中包含空值的列,则 MyBatis 在映射的时候,不会映射这个字段
call-setters-on-nulls: true
# 这个配置会将执行的sql打印出来,在开发或测试的时候可以用
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
7、写测试类
@Autowired
private IUserService iUserService;
@Autowired(required = false)
private UserMapper userMapper;
/**
* 查询
*/
@Test
public void testSelect(){
//查询所有
System.out.println(userMapper.selectList(null));
System.out.println(iUserService.list());
//查询单个
System.out.println(userMapper.selectById(2));
System.out.println(iUserService.getById(2));
}
/**
* 添加数据
*/
@Test
public void insert(){
User user=new User();
user.setAge(20);
user.setName("ting");
user.setEmail("234242@qq.com");
User user2=new User();
user2.setAge(22);
user2.setName("ting2");
user2.setEmail("234242@qq.com");
//单条添加
//System.out.println("添加结果:"+userMapper.insert(user));
//System.out.println("添加结果:"+iUserService.save(user2));
//批量添加
List<User> list=new ArrayList<>();
list.add(user);
list.add(user2);
System.out.println("批量添加结果:"+iUserService.saveBatch(list));
}
/**
* 删除
*/
@Test
public void delete(){
//通过id删除
System.out.println("删除结果:"+userMapper.deleteById(2));
System.out.println("删除结果:"+iUserService.removeById(3));
//批量删除
List<Integer> list1=new ArrayList<>();
List<Long> list2=new ArrayList<>();
list1.add(1);
list1.add(5);
list2.add(1321747562349043714L);
list2.add(1321747562349043715L);
System.out.println("批量删除1:"+userMapper.deleteBatchIds(list1));
boolean flag=iUserService.removeByIds(list2);
System.out.println("批量删除2:"+flag);
}
/**
* 修改
*/
@Test
public void update(){
User user1=new User(1321972874844389378L,"aa",10,"2929292@qq.com");
User user2=new User(1321973036350185473L,"bb",20,"34242342@qq.com");
List<User> list=new ArrayList<>();
list.add(user1);
list.add(user2);
//单条修改
System.out.println("修改结果2:"+userMapper.updateById(user1));
System.out.println("修改结果2:"+iUserService.updateById(user2));
//批量修改
System.out.println("修改结果3:"+iUserService.updateBatchById(list));
}
用代码生成器生成的实体类、业务类、控制层就测试完了
源码
既然他这么方便,那么我们需要知道他是怎么实现的,来看看源码吧
1)mapper
他继承了BaseMapper
public interface UserMapper extends BaseMapper<User> {
}
BaseMapper
:
可以发现他实现了很多功能
public interface BaseMapper<T> {
int insert(T var1);
int deleteById(Serializable var1);
int deleteByMap(@Param("cm") Map<String, Object> var1);
int delete(@Param("ew") Wrapper<T> var1);
int deleteBatchIds(@Param("coll") Collection<? extends Serializable> var1);
int updateById(@Param("et") T var1);
int update(@Param("et") T var1, @Param("ew") Wrapper<T> var2);
T selectById(Serializable var1);
List<T> selectBatchIds(@Param("coll") Collection<? extends Serializable> var1);
List<T> selectByMap(@Param("cm") Map<String, Object> var1);
T selectOne(@Param("ew") Wrapper<T> var1);
Integer selectCount(@Param("ew") Wrapper<T> var1);
List<T> selectList(@Param("ew") Wrapper<T> var1);
List<Map<String, Object>> selectMaps(@Param("ew") Wrapper<T> var1);
List<Object> selectObjs(@Param("ew") Wrapper<T> var1);
IPage<T> selectPage(IPage<T> var1, @Param("ew") Wrapper<T> var2);
IPage<Map<String, Object>> selectMapsPage(IPage<T> var1, @Param("ew") Wrapper<T> var2);
}
业务类:
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService {
}
ServiceImpl源码:
他实现的功能更加多
public class ServiceImpl<M extends BaseMapper<T>, T> implements IService<T> {
@Autowired
protected M baseMapper;
public ServiceImpl() {
}
protected boolean retBool(Integer result) {
return SqlHelper.retBool(result);
}
protected Class<T> currentModelClass() {
return ReflectionKit.getSuperClassGenericType(this.getClass(), 1);
}
protected SqlSession sqlSessionBatch() {
return SqlHelper.sqlSessionBatch(this.currentModelClass());
}
protected void closeSqlSession(SqlSession sqlSession) {
SqlSessionUtils.closeSqlSession(sqlSession, GlobalConfigUtils.currentSessionFactory(this.currentModelClass()));
}
protected String sqlStatement(SqlMethod sqlMethod) {
return SqlHelper.table(this.currentModelClass()).getSqlStatement(sqlMethod.getMethod());
}
@Transactional(
rollbackFor = {Exception.class}
)
public boolean save(T entity) {
return this.retBool(this.baseMapper.insert(entity));
}
@Transactional(
rollbackFor = {Exception.class}
)
public boolean saveBatch(Collection<T> entityList, int batchSize) {
int i = 0;
String sqlStatement = this.sqlStatement(SqlMethod.INSERT_ONE);
SqlSession batchSqlSession = this.sqlSessionBatch();
Throwable var6 = null;
try {
for(Iterator var7 = entityList.iterator(); var7.hasNext(); ++i) {
T anEntityList = var7.next();
batchSqlSession.insert(sqlStatement, anEntityList);
if (i >= 1 && i % batchSize == 0) {
batchSqlSession.flushStatements();
}
}
batchSqlSession.flushStatements();
return true;
} catch (Throwable var16) {
var6 = var16;
throw var16;
} finally {
if (batchSqlSession != null) {
if (var6 != null) {
try {
batchSqlSession.close();
} catch (Throwable var15) {
var6.addSuppressed(var15);
}
} else {
batchSqlSession.close();
}
}
}
}
@Transactional(
rollbackFor = {Exception.class}
)
public boolean saveOrUpdate(T entity) {
if (null == entity) {
return false;
} else {
Class<?> cls = entity.getClass();
TableInfo tableInfo = TableInfoHelper.getTableInfo(cls);
if (null != tableInfo && StringUtils.isNotEmpty(tableInfo.getKeyProperty())) {
Object idVal = ReflectionKit.getMethodValue(cls, entity, tableInfo.getKeyProperty());
return !StringUtils.checkValNull(idVal) && !Objects.isNull(this.getById((Serializable)idVal)) ? this.updateById(entity) : this.save(entity);
} else {
throw ExceptionUtils.mpe("Error: Can not execute. Could not find @TableId.", new Object[0]);
}
}
}
@Transactional(
rollbackFor = {Exception.class}
)
public boolean saveOrUpdateBatch(Collection<T> entityList, int batchSize) {
if (CollectionUtils.isEmpty(entityList)) {
throw new IllegalArgumentException("Error: entityList must not be empty");
} else {
Class<?> cls = this.currentModelClass();
TableInfo tableInfo = TableInfoHelper.getTableInfo(cls);
int i = 0;
SqlSession batchSqlSession = this.sqlSessionBatch();
Throwable var7 = null;
try {
Iterator var8 = entityList.iterator();
while(var8.hasNext()) {
T anEntityList = var8.next();
if (null == tableInfo || !StringUtils.isNotEmpty(tableInfo.getKeyProperty())) {
throw ExceptionUtils.mpe("Error: Can not execute. Could not find @TableId.", new Object[0]);
}
Object idVal = ReflectionKit.getMethodValue(cls, anEntityList, tableInfo.getKeyProperty());
if (!StringUtils.checkValNull(idVal) && !Objects.isNull(this.getById((Serializable)idVal))) {
ParamMap<T> param = new ParamMap();
param.put("et", anEntityList);
batchSqlSession.update(this.sqlStatement(SqlMethod.UPDATE_BY_ID), param);
} else {
batchSqlSession.insert(this.sqlStatement(SqlMethod.INSERT_ONE), anEntityList);
}
if (i >= 1 && i % batchSize == 0) {
batchSqlSession.flushStatements();
}
++i;
batchSqlSession.flushStatements();
}
} catch (Throwable var19) {
var7 = var19;
throw var19;
} finally {
if (batchSqlSession != null) {
if (var7 != null) {
try {
batchSqlSession.close();
} catch (Throwable var18) {
var7.addSuppressed(var18);
}
} else {
batchSqlSession.close();
}
}
}
return true;
}
}
@Transactional(
rollbackFor = {Exception.class}
)
public boolean removeById(Serializable id) {
return SqlHelper.delBool(this.baseMapper.deleteById(id));
}
@Transactional(
rollbackFor = {Exception.class}
)
public boolean removeByMap(Map<String, Object> columnMap) {
if (ObjectUtils.isEmpty(columnMap)) {
throw ExceptionUtils.mpe("removeByMap columnMap is empty.", new Object[0]);
} else {
return SqlHelper.delBool(this.baseMapper.deleteByMap(columnMap));
}
}
@Transactional(
rollbackFor = {Exception.class}
)
public boolean remove(Wrapper<T> wrapper) {
return SqlHelper.delBool(this.baseMapper.delete(wrapper));
}
@Transactional(
rollbackFor = {Exception.class}
)
public boolean removeByIds(Collection<? extends Serializable> idList) {
return SqlHelper.delBool(this.baseMapper.deleteBatchIds(idList));
}
@Transactional(
rollbackFor = {Exception.class}
)
public boolean updateById(T entity) {
return this.retBool(this.baseMapper.updateById(entity));
}
@Transactional(
rollbackFor = {Exception.class}
)
public boolean update(T entity, Wrapper<T> updateWrapper) {
return this.retBool(this.baseMapper.update(entity, updateWrapper));
}
@Transactional(
rollbackFor = {Exception.class}
)
public boolean updateBatchById(Collection<T> entityList, int batchSize) {
if (CollectionUtils.isEmpty(entityList)) {
throw new IllegalArgumentException("Error: entityList must not be empty");
} else {
int i = 0;
String sqlStatement = this.sqlStatement(SqlMethod.UPDATE_BY_ID);
SqlSession batchSqlSession = this.sqlSessionBatch();
Throwable var6 = null;
try {
for(Iterator var7 = entityList.iterator(); var7.hasNext(); ++i) {
T anEntityList = var7.next();
ParamMap<T> param = new ParamMap();
param.put("et", anEntityList);
batchSqlSession.update(sqlStatement, param);
if (i >= 1 && i % batchSize == 0) {
batchSqlSession.flushStatements();
}
}
batchSqlSession.flushStatements();
return true;
} catch (Throwable var17) {
var6 = var17;
throw var17;
} finally {
if (batchSqlSession != null) {
if (var6 != null) {
try {
batchSqlSession.close();
} catch (Throwable var16) {
var6.addSuppressed(var16);
}
} else {
batchSqlSession.close();
}
}
}
}
}
public T getById(Serializable id) {
return this.baseMapper.selectById(id);
}
public Collection<T> listByIds(Collection<? extends Serializable> idList) {
return this.baseMapper.selectBatchIds(idList);
}
public Collection<T> listByMap(Map<String, Object> columnMap) {
return this.baseMapper.selectByMap(columnMap);
}
public T getOne(Wrapper<T> queryWrapper, boolean throwEx) {
return throwEx ? this.baseMapper.selectOne(queryWrapper) : SqlHelper.getObject(this.baseMapper.selectList(queryWrapper));
}
public Map<String, Object> getMap(Wrapper<T> queryWrapper) {
return (Map)SqlHelper.getObject(this.baseMapper.selectMaps(queryWrapper));
}
public int count(Wrapper<T> queryWrapper) {
return SqlHelper.retCount(this.baseMapper.selectCount(queryWrapper));
}
public List<T> list(Wrapper<T> queryWrapper) {
return this.baseMapper.selectList(queryWrapper);
}
public IPage<T> page(IPage<T> page, Wrapper<T> queryWrapper) {
return this.baseMapper.selectPage(page, queryWrapper);
}
public List<Map<String, Object>> listMaps(Wrapper<T> queryWrapper) {
return this.baseMapper.selectMaps(queryWrapper);
}
public List<Object> listObjs(Wrapper<T> queryWrapper) {
return (List)this.baseMapper.selectObjs(queryWrapper).stream().filter(Objects::nonNull).collect(Collectors.toList());
}
public IPage<Map<String, Object>> pageMaps(IPage<T> page, Wrapper<T> queryWrapper) {
return this.baseMapper.selectMapsPage(page, queryWrapper);
}
}
Wrapper条件查询器
它可以实现很多复杂的查询
参考
https://www.cnblogs.com/kzyuan/p/12706600.html
@Autowired(required = false)
private UserMapper userMapper;
@Autowired
private IUserService iUserService;
/**
* 以前默认是叫EntityWrapper,现在叫QueryWrapper
*/
/**
* 根据条件查询
*/
@Test
public void select(){
QueryWrapper<User> wrapper=new QueryWrapper<>();
wrapper.isNotNull("name") //name不为空的用户
.isNotNull("email") //邮箱不为空
.ge("age",12); //年龄大于等于12
List<User> list=userMapper.selectList(wrapper);
System.out.println(list);
}
/**
* 根据名字查询
*/
@Test
public void selectName(){
QueryWrapper<User> wrapper=new QueryWrapper<>();
wrapper.eq("name","ting");
List<User> list=userMapper.selectList(wrapper);
System.out.println(list);
}
/**
* 查询 10 到 20 岁的用户数
*/
@Test
public void selectByAge(){
QueryWrapper<User> wrapper=new QueryWrapper<>();
wrapper.between("age",10,21);
List<User> list=userMapper.selectList(wrapper);
System.out.println(list);
}
/**
* 模糊查询
*/
@Test
public void selectLike(){
QueryWrapper<User> wrapper=new QueryWrapper<>();
wrapper
.notLike("name","2")
.like("name","t")
//右查询
.likeRight("email","234");
List<Map<String,Object>> users=userMapper.selectMaps(wrapper);
System.out.println(users);
}
/**
* 子查询
*/
@Test
public void selectLike2(){
QueryWrapper<User> wrapper=new QueryWrapper<>();
wrapper.inSql("id","select id from user where age<21");
List<Object> users=userMapper.selectObjs(wrapper);
System.out.println(users);
}
/**
* 排序
*/
@Test
public void selectByOrder(){
QueryWrapper<User> wrapper=new QueryWrapper<>();
//降序排序
wrapper.orderByDesc("id");
List<User> users=userMapper.selectList(wrapper);
System.out.println(users);
}
/**
* 部分字段更新
*/
@Test
public void update(){
UpdateWrapper<User> wrapper=new UpdateWrapper<>();
User user=new User();
//更新字段
wrapper.set("name","xyz");
wrapper.eq("id",1321972874844389378L);
System.out.println("更新结果:"+iUserService.update(user,wrapper));
}
分页
需要新建一个配置类
@Configuration
@MapperScan("com.king.mapper")
public class MybatisPlusConfig {
@Bean
public PaginationInterceptor paginationInterceptor() {
PaginationInterceptor paginationInterceptor = new PaginationInterceptor();
// 设置请求的页面大于最大页后操作, true调回到首页,false 继续请求 默认false
// paginationInterceptor.setOverflow(false);
// 设置最大单页限制数量,默认 500 条,-1 不受限制
// paginationInterceptor.setLimit(500);
// 开启 count 的 join 优化,只针对部分 left join
//paginationInterceptor.setCountSqlParser(new JsqlParserCountOptimize(true));
return paginationInterceptor;
}
}
测试代码:
/**
* 分页
*/
@Test
public void page(){
//当前页1,每页大小2
IPage<User> userIPage=new Page<>(1,1);
userIPage=userMapper.selectPage(userIPage,null);
List<User> list=userIPage.getRecords();
System.out.println(list);
}
多表查询
看了一下网上说mybatis-plus
不支持多表操作,这就麻烦了,不然mybatis-plus
有啥用呢,虽然说网上也有方法,但是我不想用,感觉比较麻烦吧,大家可以自己选择。
现在来看看吧,我们可以用这个代码自动生成器,生成对应的代码,然后在其基础上进行修改就好了,毕竟单表的基本操作他都做好了,多表我们就自己写呗,还是省了不少事的
sql语句:
create TABLE user(
user_id INT PRIMARY KEY AUTO_INCREMENT,
user_name VARCHAR(100),
sex_id Int
)
create TABLE sex(
sex_id INT PRIMARY KEY AUTO_INCREMENT,
sex_name VARCHAR(100)
)
insert into user(user_name,sex_id) VALUES("king",1);
insert into user(user_name,sex_id) VALUES("ting",2);
insert into user(user_name,sex_id) VALUES("aaa",1);
insert into sex(sex_name) VALUES("男");
insert into sex(sex_name) VALUES("女");
insert into sex(sex_name) VALUES("变态");
1、配置文件和自动生成代码配置器文件也和上面一样的,结构如下:
2、运行自动生成代码器,输入多个表名
4、首先需要对实体类进行修改
这个外键改成他对应的实体类就好了,并且上面需要加上注解,表明映射结果到哪里
sex类也要进行修改,如果需要的话
5、修改xml文件,映射关系改一下
6、就OK了,就可以使用了,如果需要自定义sql,自己在mapper中添加就是了