1.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.7.16</version>
- <relativePath/> <!-- lookup parent from repository -->
- </parent>
- <groupId>com.example</groupId>
- <artifactId>StudyMybatisPlus</artifactId>
- <version>0.0.1-SNAPSHOT</version>
- <name>StudyMybatisPlus</name>
- <description>Demo project for Spring Boot</description>
- <properties>
- <java.version>11</java.version>
- </properties>
- <dependencies>
- <dependency>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter</artifactId>
- </dependency>
- <dependency>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter-web</artifactId>
- </dependency>
-
- <dependency>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter-test</artifactId>
- <scope>test</scope>
- </dependency>
-
- <dependency>
- <groupId>com.baomidou</groupId>
- <artifactId>mybatis-plus-boot-starter</artifactId>
- <version>3.5.1</version>
- </dependency>
- <dependency>
- <groupId>mysql</groupId>
- <artifactId>mysql-connector-java</artifactId>
- <version>8.0.21</version>
- </dependency>
- <dependency>
- <groupId>org.projectlombok</groupId>
- <artifactId>lombok</artifactId>
- <version>1.18.12</version>
- </dependency>
-
- <dependency>
- <groupId>org.reflections</groupId>
- <artifactId>reflections</artifactId>
- <version>0.9.10</version>
- </dependency>
- </dependencies>
-
- <build>
- <plugins>
- <plugin>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-maven-plugin</artifactId>
- </plugin>
- </plugins>
- </build>
-
- </project>
2.application.yml
- #配置端口
- server:
- port: 80
-
- spring:
- #配置数据源
- datasource:
- #配置数据源类型
- type: com.zaxxer.hikari.HikariDataSource
- #配置连接数据库的信息
- driver-class-name: com.mysql.cj.jdbc.Driver
- url: jdbc:mysql://localhost:3306/mybatis_plus?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=CTT&allowPublicKeyRetrieval=true
- username: root
- password: root
-
- #mybatis plus配置
- mybatis-plus:
- configuration:
- log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
-
- # 字段名和数据库中字段名一致
- map-underscore-to-camel-case: false
- global-config:
- db-config:
- #配置mybatis plus 在更新时只更新非空和非NULL的字段
- update-strategy: not_empty
-
- # 实体名字和数据库表名一致
- table-underline: false
-
- # 需要转化为json的字段
- map-field-scan-package: "com.example"
3.MapData.java
- package com.example.studymybatisplus.anno;
-
- import java.lang.annotation.ElementType;
- import java.lang.annotation.Retention;
- import java.lang.annotation.RetentionPolicy;
- import java.lang.annotation.Target;
-
- @Target({ElementType.FIELD})
- @Retention(RetentionPolicy.RUNTIME)
- public @interface MapData {
- }
4.TypeConfig.java
- package com.example.studymybatisplus.config;
-
- import com.baomidou.mybatisplus.annotation.TableName;
- import com.baomidou.mybatisplus.autoconfigure.MybatisPlusProperties;
- import com.baomidou.mybatisplus.autoconfigure.MybatisPlusPropertiesCustomizer;
- import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler;
- import com.example.studymybatisplus.anno.MapData;
- import org.reflections.Reflections;
- import org.springframework.beans.factory.annotation.Value;
- import org.springframework.context.annotation.Configuration;
-
- import java.lang.reflect.Field;
- import java.util.HashSet;
- import java.util.Set;
-
- /**
- * 注册需要转换为Map的处理器
- */
- @Configuration
- public class TypeConfig implements MybatisPlusPropertiesCustomizer {
-
- @Value("${map-field-scan-package}")
- String packageName;
-
- @Override
- public void customize(MybatisPlusProperties properties) {
- Reflections reflections = new Reflections(this.packageName);
- Set<Class<?>> typesAnnotatedWith = reflections.getTypesAnnotatedWith(TableName.class);
- Set<Class<?>> mapTypeSet = new HashSet<>();
- typesAnnotatedWith.forEach(clazz -> {
- Field[] fields = clazz.getDeclaredFields();
- for (Field field : fields) {
- field.setAccessible(true);
- if (field.getAnnotation(MapData.class) != null) {
- if(mapTypeSet.contains(field.getType())){
- continue;
- }
- mapTypeSet.add(field.getType());
-
- properties.getConfiguration().getTypeHandlerRegistry().register(field.getType(), JacksonTypeHandler.class);
- }
- }
- });
- }
- }
5.UserMapper.java
- package com.example.studymybatisplus.mapper;
-
- import com.baomidou.mybatisplus.core.mapper.BaseMapper;
- import com.example.studymybatisplus.pojo.User;
- import org.springframework.stereotype.Repository;
-
- import java.util.List;
-
- @Repository
- public interface UserMapper extends BaseMapper
{ - /**
- * 测试自定义sql
- */
- List
getUserList(); - }
6.User.java
- package com.example.studymybatisplus.pojo;
-
- import com.baomidou.mybatisplus.annotation.IdType;
- import com.baomidou.mybatisplus.annotation.TableId;
- import com.baomidou.mybatisplus.annotation.TableName;
- import com.example.studymybatisplus.anno.MapData;
- import lombok.Data;
-
- @Data
- @TableName(autoResultMap = true)
- public class User {
- @TableId(type = IdType.AUTO)
- private Long id;
- private String name = "";
- private Integer age = 0;
-
- @MapData
- private UserInfo info = new UserInfo();
- }
7.UserInfo.java
- package com.example.studymybatisplus.pojo;
-
- import lombok.Data;
-
- import java.util.HashMap;
- import java.util.Map;
-
- @Data
- public class UserInfo {
- private String address="";
- private Map
map = new HashMap<>(); - private DataVo dataVo = new DataVo();
- private Integer aaa;
- }
8.DataVo.java
- package com.example.studymybatisplus.pojo;
-
- import lombok.Data;
-
- import java.util.HashMap;
- import java.util.Map;
-
- @Data
- public class DataVo {
- private Integer num;
- private Map
map2 = new HashMap<>(); - }
9.主方法
- package com.example.studymybatisplus;
-
- import org.mybatis.spring.annotation.MapperScan;
- import org.springframework.boot.SpringApplication;
- import org.springframework.boot.autoconfigure.SpringBootApplication;
-
- @SpringBootApplication
- @MapperScan("com.example.studymybatisplus.mapper")
- public class StudyMybatisPlusApplication {
- public static void main(String[] args) {
- SpringApplication.run(StudyMybatisPlusApplication.class, args);
- }
- }
10.UserMapper.xml // 测试自定义sql
- mapper
- PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
- "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
-
- <mapper namespace="com.example.studymybatisplus.mapper.UserMapper">
- <select id="getUserList" resultType="com.example.studymybatisplus.pojo.User">
- SELECT id, name, age, info
- FROM user
- select>
- mapper>
可见,完全不需要ResultMap了,非常完美!!!
11.测试用例
- package com.example.studymybatisplus;
-
- import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
- import com.example.studymybatisplus.mapper.UserMapper;
- import com.example.studymybatisplus.pojo.User;
- import org.junit.jupiter.api.Test;
- import org.springframework.beans.factory.annotation.Autowired;
- import org.springframework.boot.test.context.SpringBootTest;
- import org.springframework.transaction.annotation.Transactional;
-
- import java.util.List;
- import java.util.Map;
- import java.util.Random;
-
- @SpringBootTest
- class StudyMybatisPlusApplicationTests {
-
- @Autowired
- UserMapper userMapper;
-
- @Test
- void insertAndQuery() {
- for (int i = 0; i < 10; i++) {
- User newUser = new User();
- newUser.setName("xx");
- newUser.setAge(30);
-
- newUser.getInfo().setAddress("北京 " + new Random().nextInt(10000));
- newUser.getInfo().getMap().put(1, 123);
-
- newUser.getInfo().getDataVo().setNum(222);
- newUser.getInfo().getDataVo().getMap2().put(666, 888);
-
- newUser.getInfo().getDataVo2().setNum(112222);
-
- int insert = userMapper.insert(newUser);
- System.out.println("insert:" + insert);
- System.out.println(newUser);
-
- // 测试QueryWrapper
- List<User> userList1 = userMapper.selectList(new QueryWrapper<User>().lambda());
- System.out.println(userList1);
-
- // 现在自定义sql也完全不需要ResultMap了
- List<User> userList2 = userMapper.getUserList();
- System.out.println(userList2);
- }
- }
-
- @Test
- void clearAllData() {
- userMapper.delete(null);
- }
-
- @Test
- void addOneUser() {
- User user = new User();
- Map<Integer, Integer> receiveState = user.getInfo().getReceiveState();
- receiveState.put(1, 0);
- receiveState.put(2, 1);
-
- userMapper.insert(user);
-
- System.out.println(user.getId());
- }
-
- @Test
- void updateUser() {
- User user = userMapper.selectById(58);
- user.getInfo().getReceiveState().put(3, 3);
- userMapper.updateById(user);
-
- User user2 = userMapper.selectById(59);
- user2.getInfo().getReceiveState().put(33, 33);
- userMapper.updateById(user2);
- }
- }
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
9.输出
- JDBC Connection [HikariProxyConnection@1111497601 wrapping com.mysql.cj.jdbc.ConnectionImpl@f1d1463] will not be managed by Spring
- ==> Preparing: SELECT id,name,age,info FROM user
- ==> Parameters:
- <== Columns: id, name, age, info
- <== Row: 1, xx, 30, <<BLOB>>
- <== Row: 2, xx, 30, <<BLOB>>
- <== Row: 3, xx, 30, <<BLOB>>
- <== Total: 3
- Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@27502e5c]
- [User(id=1, name=xx, age=30, info=UserInfo(address=北京2, map={1=123}, dataVo=DataVo(num=222, map2={666=888}), aaa=null)), User(id=2, name=xx, age=30, info=UserInfo(address=北京1, map={1=123}, dataVo=DataVo(num=222, map2={666=888}), aaa=null)), User(id=3, name=xx, age=30, info=UserInfo(address=北京 5542, map={1=123}, dataVo=DataVo(num=222, map2={666=888}), aaa=null))]
- Creating a new SqlSession
- SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@12266084] was not registered for synchronization because synchronization is not active
- JDBC Connection [HikariProxyConnection@1839613624 wrapping com.mysql.cj.jdbc.ConnectionImpl@f1d1463] will not be managed by Spring
- ==> Preparing: SELECT id, name, age, info FROM user
- ==> Parameters:
- <== Columns: id, name, age, info
- <== Row: 1, xx, 30, <<BLOB>>
- <== Row: 2, xx, 30, <<BLOB>>
- <== Row: 3, xx, 30, <<BLOB>>
- <== Total: 3
- Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@12266084]
- [User(id=1, name=xx, age=30, info=UserInfo(address=北京2, map={1=123}, dataVo=DataVo(num=222, map2={666=888}), aaa=null)), User(id=2, name=xx, age=30, info=UserInfo(address=北京1, map={1=123}, dataVo=DataVo(num=222, map2={666=888}), aaa=null)), User(id=3, name=xx, age=30, info=UserInfo(address=北京 5542, map={1=123}, dataVo=DataVo(num=222, map2={666=888}), aaa=null))]
- 2023-10-22 00:14:07.258 INFO 10232 --- [ionShutdownHook] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Shutdown initiated...
- 2023-10-22 00:14:07.274 INFO 10232 --- [ionShutdownHook] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Shutdown completed.
可见,业务层可以愉快的使用Entity了,完全不需要关心是不是自定义sql,完美支持json,这样子mysql和mongodb就是一模一样了,只不过是复杂的类型多了一个自定义的@MapData注解!!
总结:
1.增加字段发现确实是可以的,删除字段就报错,所以这也符合游戏的目标也就是不能删和改字段名字。
2.注意在Entity中给默认值,因为我们用的都是包装类型,使用xdb的经验告诉我,所有的数据要给默认值,Map类型也要初始化一下。