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<User> {
    /**
     * 测试自定义sql
     */
    List<User> 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<Integer, Integer> 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<Integer, Integer> 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

<!DOCTYPE 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类型也要初始化一下。

GitHub 加速计划 / js / json
41.72 K
6.61 K
下载
适用于现代 C++ 的 JSON。
最近提交(Master分支:1 个月前 )
960b763e 4 个月前
8c391e04 6 个月前
Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐