I haven’t used MyBatis since I encountered the spring-data-jPA + QueryDSL combination.

QueryDsl is simple

QueryDSL can build queries on any supported ORM framework or SQL platform as a common API. Currently, QueryDSL supports JPA,JDO,SQL,Mongodb and so on.

website

www.querydsl.com

Gitthub

Github.com/querydsl/qu…

Introduction to meeting

This tutorial demonstrates the queryDSL + Spring-data-JPA integration (I don’t know anything else). With Spring-data-JPA, it doesn’t matter if you’re not familiar with it, so use QueryDSL.

Before we begin, there are a few caveats.

There won’t be much jPA-related stuff here

QueryDsl and JPA integration is actually quite simple (just a few lines of code). But the integration of JAP and SpringBoot involves a lot of configuration properties, code. I won’t explain them too much here.

Entity class modeling does not adopt object-oriented modeling

A big reason JPA is annoying is because of all the @ontoone, @onetomany… And so on. And it brings a lot of concepts: lazy loading, cascading deletion, cascading save, orphan deletion… More headache. Code is dead, people are alive, you don’t have to follow the rules. These problems are solved completely without object – oriented modeling.

Demo project creation

During the editor initialization project, omit.

Maven’s complete core dependencies

<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>
	<groupId>io.springboot.querydsl</groupId>
	<artifactId>springboot-querydsl</artifactId>
	<version>0.0.1 - the SNAPSHOT</version>

	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.3.3. RELEASE</version>
		<relativePath /> <! -- lookup parent from repository -->
	</parent>

	<properties>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
		<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
		<java.version>1.8</java.version>

		<skipTests>true</skipTests>
	</properties>

	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
			<exclusions>
				<exclusion>
					<groupId>org.springframework.boot</groupId>
					<artifactId>spring-boot-starter-tomcat</artifactId>
				</exclusion>
			</exclusions>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-undertow</artifactId>
		</dependency>
		
		<! -- jpa -->
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-data-jpa</artifactId>
		</dependency>
		
		<! -- Mysql driver -->
		<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
		</dependency>
		
		<! -- Data source -->
		<dependency>
			<groupId>com.zaxxer</groupId>
			<artifactId>HikariCP</artifactId>
		</dependency>
		
		<! -- QueryDsl -->
		<dependency>
			<groupId>com.querydsl</groupId>
			<artifactId>querydsl-jpa</artifactId>
		</dependency>
		<dependency>
			<groupId>com.querydsl</groupId>
			<artifactId>querydsl-apt</artifactId>
			<scope>provided</scope>
		</dependency>
	</dependencies>

	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
				<configuration>
					<executable>true</executable>
					<includeSystemScope>true</includeSystemScope>
				</configuration>
			</plugin>
			<! QueryDsl code generation plugin -->
			<plugin>
				<groupId>com.mysema.maven</groupId>
				<artifactId>apt-maven-plugin</artifactId>
				<version>1.1.3</version>
				<executions>
					<execution>
						<goals>
							<goal>process</goal>
						</goals>
						<configuration>
							<! -- query object generation path -->
							<outputDirectory>target/generated-sources/java</outputDirectory>
							<! -- Generate query object handler, use JPA-->
							<processor>com.querydsl.apt.jpa.JPAAnnotationProcessor</processor>
						</configuration>
					</execution>
				</executions>
			</plugin>
		</plugins>
	</build>
</project>
Copy the code

Querydsl has only three components, with the exception of JPA and required dependencies (drivers, connection pools). Two dependencies, one plugin. What the plug-in does is generate query objects from entity classes when Maven is packaged.

The configuration file


server:
  port: 80

logging:
  level:
    root: DEBUG
    Enter SQL parameter binding information in log
    'org.hibernate.type.descriptor.sql.BasicBinder': TRACE

spring:
  datasource:
    type: com.zaxxer.hikari.HikariDataSource
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: JDBC: mysql: / / 127.0.0.1:3306 / querydsl? useUnicode=true&characterEncoding=UTF-8&serverTimezone=GMT%2b8&allowMultiQueries=true
    username: root
    password: root

  data:
    jpa:
      repositories:
        enabled: true
        bootstrap-mode: default
  jpa:
    # specify the dialect of the relational database
    database-platform: org.hibernate.dialect.MySQL57Dialect
    Do not maintain connections at the view layer
    open-in-view: false
    Output SQL in log
    show-sql: false
    properties:
    Format the SQL output in the log
      hibernate.format_sql: false
    hibernate:
      SQL > create table UPDATE
      ddl-auto: update
Copy the code

This is basically all spring-data-jPA related configuration and, in particular, comments. It’s easy to understand.

JPAQueryFactoryConfiguration

JPA integrates QueryDsl, and that’s really it

package io.springboot.querydsl.configuration;

import javax.persistence.EntityManager;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import com.querydsl.jpa.impl.JPAQueryFactory;

@Configuration
public class JPAQueryFactoryConfiguration {
	
	@Bean
	public JPAQueryFactory jpaQueryFactory(@Autowired EntityManager entityManager) {
		return newJPAQueryFactory(entityManager); }}Copy the code

Entity class

Modeling, where four entity classes are defined that describe common one-to-many, many-to-many relationships.

  • BaseEntityAbstract out the common fields
  • UserThe user
  • EmailOne-to-many association of user email addresses
  • Rolerole
  • UserRoleMany-to-many association of user roles

The Getter/Setter method is omitted

BaseEntity

package io.springboot.querydsl.entity;

import java.io.Serializable;
import java.time.LocalDateTime;

import javax.persistence.Column;
import javax.persistence.MappedSuperclass;

@MappedSuperclass
public abstract class BaseEntity implements Serializable {

	/ * * * * /
	private static final long serialVersionUID = 7054150882445633369L;

	// Create time
	@column (columnDefinition = "timestamp DEFAULT CURRENT_TIMESTAMP COMMENT 'create time', nullable = false)
	private LocalDateTime createdDate;

	// Change the last time
	@column (columnDefinition = "timestamp NULL DEFAULT NULL COMMENT 'last modified '")
	private LocalDateTime lastModifiedDate;
}

Copy the code

User

package io.springboot.querydsl.entity;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Index;
import javax.persistence.Table;

@Entity
@Table(name = "user", indexes = { @Index(name = "name", columnList = "name", unique = true), })
@org.hibernate.annotations.Table(appliesTo = "user", comment = "User")
public class User extends BaseEntity {

	/ * * * * /
	private static final long serialVersionUID = -5342379801159855228L;

	@Id
	@Column(columnDefinition = "INT(11) UNSIGNED COMMENT 'id'")
	@GeneratedValue(strategy = GenerationType.IDENTITY)
	private Integer id;

	/ / nickname
	@column (columnDefinition = "VARCHAR(20) COMMENT ", nullable = false)
	private String name;

	/ / gender
	@column (columnDefinition = "TINYINT(1) unsigned COMMENT 'Gender. 0: female, 1: male, 2: unknown ", nullable = false)
	private Gender gender;

	// Whether the account has been authenticated
	@column (columnDefinition = "TINYINT(1) unsigned COMMENT ", nullable = false)
	private Boolean validated;

	// Gender enumeration
	public static enum Gender {
		GIRL, BOY, UNKNOWN
	}
}

Copy the code

Email

package io.springboot.querydsl.entity;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Index;
import javax.persistence.Table;

@Entity
@Table(name = "email", indexes = { @Index(name = "userEmailAccount", columnList = "user_id,account", unique = true), @Index(name = "account", columnList = "account") })
@org.hibernate.annotations.Table(appliesTo = "email", comment = "User email")
public class Email extends BaseEntity {

	/ * * * * /
	private static final long serialVersionUID = -730436482990380359L;

	@Id
	@Column(columnDefinition = "INT(11) UNSIGNED COMMENT 'id'")
	@GeneratedValue(strategy = GenerationType.IDENTITY)
	private Integer id;

	/ / user id
	@column (name = "user_id", columnDefinition = "INT(11) UNSIGNED COMMENT 'user_id '")
	private Integer userId;

	// Email account
	@column (name = "account", columnDefinition = "VARCHAR(20) COMMENT ", nullable = false)
	private String account;
}

Copy the code

Role

package io.springboot.querydsl.entity;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Index;
import javax.persistence.Table;

@Entity
@Table(name = "role", indexes = { @Index(name = "name", columnList = "name", unique = true), })
@org.hibernate.annotations.Table(appliesTo = "role", comment = "Role")
public class Role extends BaseEntity {

	/ * * * * /
	private static final long serialVersionUID = 1749885146919803064L;

	@Id
	@Column(columnDefinition = "INT(11) UNSIGNED COMMENT 'id'")
	@GeneratedValue(strategy = GenerationType.IDENTITY)
	private Integer id;

	/ / name
	@Column(columnDefinition = "VARCHAR(20) COMMENT '名称'", nullable = false)
	private String name;
}
Copy the code

UserRole

package io.springboot.querydsl.entity;

import java.io.Serializable;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.IdClass;
import javax.persistence.Index;
import javax.persistence.Table;

@Entity
@Table(name = "user_role", indexes = { @Index(name = "roleId", columnList = "role_id"), })
@org.hibernate.annotations.Table(appliesTo = "user_role", comment = "User role association")
@IdClass(UserRole.Id.class)
public class UserRole extends BaseEntity {
	
	/ * * * * /
	private static final long serialVersionUID = 1782979029236838525L;

	@column (name = "user_id", columnDefinition = "INT(11) UNSIGNED COMMENT 'userid '", nullable = false)
	@javax.persistence.Id
	private Integer userId;
	
	@javax.persistence.Id
	@column (name = "role_id", columnDefinition = "INT(11) UNSIGNED COMMENT 'ID'", nullable = false)
	private Integer roleId;
	
	public static class Id implements Serializable {
		private static final long serialVersionUID = 2751217704686895162L;
		private Integer userId;
		private Integer roleId;
		public Id(a) {}public Id(Integer userId, Integer roleId) {
			super(a);this.userId = userId;
			this.roleId = roleId;
		}
		@Override
		public int hashCode(a) {
			final int prime = 31;
			int result = 1;
			result = prime * result + ((roleId == null)?0 : roleId.hashCode());
			result = prime * result + ((userId == null)?0 : userId.hashCode());
			return result;
		}
		@Override
		public boolean equals(Object obj) {
			if (this == obj)
				return true;
			if (obj == null)
				return false;
			if(getClass() ! = obj.getClass())return false;
			Id other = (Id) obj;
			if (roleId == null) {
				if(other.roleId ! =null)
					return false;
			} else if(! roleId.equals(other.roleId))return false;
			if (userId == null) {
				if(other.userId ! =null)
					return false;
			} else if(! userId.equals(other.userId))return false;
			return true; }}}Copy the code

Repository

BaseRepository

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.data.querydsl.QuerydslPredicateExecutor;
import org.springframework.data.repository.NoRepositoryBean;

@NoRepositoryBean
public interface BaseRepository<T.ID> extends JpaRepository<T.ID>, JpaSpecificationExecutor<T>, QuerydslPredicateExecutor<T> {}Copy the code

Several other repositories

package io.springboot.querydsl.repository;

import io.springboot.querydsl.entity.User;

public interface UserRepository extends BaseRepository<User.Integer>{}Copy the code
package io.springboot.querydsl.repository;

import io.springboot.querydsl.entity.Email;

public interface EmailRepository extends BaseRepository<Email.Integer> {}Copy the code
package io.springboot.querydsl.repository;

import io.springboot.querydsl.entity.Role;

public interface RoleRepository extends BaseRepository<Role.Integer> {}Copy the code
package io.springboot.querydsl.repository;

import io.springboot.querydsl.entity.UserRole;

public interface UserRoleRepository extends BaseRepository<UserRole.UserRole.Id> {}Copy the code

Service

BaseService

package io.springboot.querydsl.service;

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.data.querydsl.QuerydslPredicateExecutor;

public interface BaseService <T.ID> extends JpaRepository<T.ID>, JpaSpecificationExecutor <T>, QuerydslPredicateExecutor<T> {}Copy the code

AbstractService

package io.springboot.querydsl.service;

import java.util.List;
import java.util.Optional;
import java.util.function.Function;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Example;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.transaction.annotation.Transactional;

import com.querydsl.core.types.OrderSpecifier;
import com.querydsl.core.types.Predicate;
import com.querydsl.jpa.impl.JPAQueryFactory;

import io.springboot.querydsl.repository.BaseRepository;

public class AbstractService<T.ID>  implements BaseService <T.ID>{
	
	@Autowired
	protected BaseRepository<T,ID> baseRepository;
	
	@Autowired
	protected JPAQueryFactory jpaQueryFactory;
	
	@Override
	@Transactional(readOnly = true, rollbackFor = Throwable.class)
	public List<T> findAll(a) {
		return this.baseRepository.findAll();
	}

	@Override
	@Transactional(readOnly = true, rollbackFor = Throwable.class)
	public List<T> findAll(Sort sort) {
		return this.baseRepository.findAll(sort);
	}

	@Override
	@Transactional(readOnly = true, rollbackFor = Throwable.class)
	public List<T> findAllById(Iterable<ID> ids) {
		return this.baseRepository.findAllById(ids);
	}

	@Override
	@Transactional(rollbackFor = Throwable.class)
	public <S extends T> List<S> saveAll(Iterable<S> entities) {
		return this.baseRepository.saveAll(entities);
	}

	@Override
	@Transactional(rollbackFor = Throwable.class)
	public void flush(a) {
		this.baseRepository.flush();
	}

	@Transactional(rollbackFor = Throwable.class)
	public <S extends T> S saveAndFlush(S entity) {
		return this.baseRepository.saveAndFlush(entity);
	}

	@Override
	@Transactional(rollbackFor = Throwable.class)
	public void deleteInBatch(Iterable<T> entities) {
		this.baseRepository.deleteInBatch(entities);
	}

	@Override
	@Transactional(rollbackFor = Throwable.class)
	public void deleteAllInBatch(a) {
		this.baseRepository.deleteAllInBatch();
	}

	@Override
	@Transactional(readOnly = true, rollbackFor = Throwable.class)
	public T getOne(ID id) {
		return this.baseRepository.getOne(id);
	}

	@Override
	@Transactional(readOnly = true, rollbackFor = Throwable.class)
	public <S extends T> List<S> findAll(Example<S> example) {
		return this.baseRepository.findAll(example);
	}

	@Override
	@Transactional(readOnly = true, rollbackFor = Throwable.class)
	public <S extends T> List<S> findAll(Example<S> example, Sort sort) {
		return this.baseRepository.findAll(example, sort);
	}

	@Override
	@Transactional(readOnly = true, rollbackFor = Throwable.class)
	public Page<T> findAll(Pageable pageable) {
		return this.baseRepository.findAll(pageable);
	}

	@Override
	@Transactional(rollbackFor = Throwable.class)
	public <S extends T> S save(S entity) {
		return this.baseRepository.save(entity);
	}

	@Override
	@Transactional(readOnly = true, rollbackFor = Throwable.class)
	public Optional<T> findById(ID id) {
		return this.baseRepository.findById(id);
	}

	@Override
	@Transactional(readOnly = true, rollbackFor = Throwable.class)
	public boolean existsById(ID id) {
		return this.baseRepository.existsById(id);
	}

	@Override
	@Transactional(readOnly = true, rollbackFor = Throwable.class)
	public long count(a) {
		return this.baseRepository.count();
	}

	@Override
	@Transactional(rollbackFor = Throwable.class)
	public void deleteById(ID id) {
		this.baseRepository.deleteById(id);		
	}

	@Override
	@Transactional(rollbackFor = Throwable.class)
	public void delete(T entity) {
		this.baseRepository.delete(entity);		
	}

	@Override
	@Transactional(rollbackFor = Throwable.class)
	public void deleteAll(Iterable<? extends T> entities) {
		this.baseRepository.deleteAll(entities);
	}

	@Override
	@Transactional(rollbackFor = Throwable.class)
	public void deleteAll(a) {
		this.baseRepository.deleteAll();
	}
	
	@Override
	@Transactional(readOnly = true, rollbackFor = Throwable.class)
	public <S extends T> Optional<S> findOne(Example<S> example) {
		return this.baseRepository.findOne(example);
	}
	
	@Override
	@Transactional(readOnly = true, rollbackFor = Throwable.class)
	public <S extends T> Page<S> findAll(Example<S> example, Pageable pageable) {
		return this.baseRepository.findAll(example, pageable);
	}
	
	@Override
	@Transactional(readOnly = true, rollbackFor = Throwable.class)
	public <S extends T> long count(Example<S> example) {
		return this.baseRepository.count(example);
	}
	
	@Override
	@Transactional(readOnly = true, rollbackFor = Throwable.class)
	public <S extends T> boolean exists(Example<S> example) {
		return this.baseRepository.exists(example);
	}

	@Override
	@Transactional(readOnly = true, rollbackFor = Throwable.class)
	public Optional<T> findOne(Specification<T> spec) {
		return this.baseRepository.findOne(spec);
	}

	@Override
	@Transactional(readOnly = true, rollbackFor = Throwable.class)
	public List<T> findAll(Specification<T> spec) {
		return this.baseRepository.findAll(spec);
	}
	
	@Override
	@Transactional(readOnly = true, rollbackFor = Throwable.class)
	public Page<T> findAll(Specification<T> spec, Pageable pageable) {
		return this.baseRepository.findAll(spec, pageable);
	}
	
	@Override
	@Transactional(readOnly = true, rollbackFor = Throwable.class)
	public List<T> findAll(Specification<T> spec, Sort sort) {
		return this.baseRepository.findAll(spec, sort);
	}

	@Override
	@Transactional(readOnly = true, rollbackFor = Throwable.class)
	public long count(Specification<T> spec) {
		return this.baseRepository.count(spec);
	}

	@Override
	@Transactional(readOnly = true, rollbackFor = Throwable.class)
	public Optional<T> findOne(Predicate predicate) {
		return this.baseRepository.findOne(predicate);
	}

	@Override
	@Transactional(readOnly = true, rollbackFor = Throwable.class)
	public Iterable<T> findAll(Predicate predicate) {
		return this.baseRepository.findAll(predicate);
	}

	@Override
	@Transactional(readOnly = true, rollbackFor = Throwable.class)
	public Iterable<T> findAll(Predicate predicate, Sort sort) {
		return this.baseRepository.findAll(predicate, sort);
	}

	@Override
	@Transactional(readOnly = true, rollbackFor = Throwable.class)
	public Iterable<T> findAll(Predicate predicate, OrderSpecifier
       ... orders) {
		return this.baseRepository.findAll(predicate, orders);
	}

	@Override
	@Transactional(readOnly = true, rollbackFor = Throwable.class)
	public Iterable<T> findAll(OrderSpecifier
       ... orders) {
		return this.baseRepository.findAll(orders);
	}

	@Override
	@Transactional(readOnly = true, rollbackFor = Throwable.class)
	public Page<T> findAll(Predicate predicate, Pageable pageable) {
		return this.baseRepository.findAll(predicate, pageable);
	}

	@Override
	@Transactional(readOnly = true, rollbackFor = Throwable.class)
	public long count(Predicate predicate) {
		return this.baseRepository.count(predicate);
	}

	@Override
	@Transactional(readOnly = true, rollbackFor = Throwable.class)
	public boolean exists(Predicate predicate) {
		return this.baseRepository.exists(predicate);
	}

	
	// Two custom methods to get a JPAQueryFactory in a transaction and execute custom query logic
	
	@Transactional(rollbackFor = Throwable.class)
	public <R> R apply(Function<JPAQueryFactory, R> function) {
		return function.apply(this.jpaQueryFactory);
	}
	
	@Transactional(readOnly = true, rollbackFor = Throwable.class)
	public <R> R applyReadOnly(Function<JPAQueryFactory, R> function) {
		return function.apply(this.jpaQueryFactory); }}Copy the code

Other services

package io.springboot.querydsl.service;

import org.springframework.stereotype.Service;

import io.springboot.querydsl.entity.User;

@Service
public class UserService extends AbstractService<User.Integer> {}Copy the code
package io.springboot.querydsl.service;

import org.springframework.stereotype.Service;

import io.springboot.querydsl.entity.Email;

@Service
public class EmailService extends AbstractService<Email.Integer> {}Copy the code
package io.springboot.querydsl.service;

import org.springframework.stereotype.Service;

import io.springboot.querydsl.entity.Role;

@Service
public class RoleService extends AbstractService<Role.Integer>{}Copy the code
package io.springboot.querydsl.service;

import org.springframework.stereotype.Service;

import io.springboot.querydsl.entity.UserRole;

@Service
public class UserRoleService extends AbstractService<UserRole.UserRole.Id> {}Copy the code

Application to start the class

package io.springboot.querydsl;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.domain.EntityScan;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;

@SpringBootApplication
@EnableJpaRepositories(basePackages = { "io.springboot.querydsl.repository" })
@EntityScan(basePackages = { "io.springboot.querydsl.entity" })
public class QueryDslAppliccation {
	
	public static void main(String[] args) { SpringApplication.run(QueryDslAppliccation.class, args); }}Copy the code

Maven packaging

When MAVEN packaging is performed, the plug-in generates query objects in the specified directory, starting with Q.

Start the project to create data tables automatically

If the startup process is normal, the tables are automatically created in the database based on the entity class (because the automatic table building policy is configured).

CREATE TABLE `email` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT 'id',
  `created_date` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT 'Creation time',
  `last_modified_date` timestamp NULL DEFAULT NULL COMMENT 'Last modified time',
  `account` varchar(20) NOT NULL COMMENT 'nickname',
  `user_id` int(11) unsigned DEFAULT NULL COMMENT 'user id'.PRIMARY KEY (`id`),
  UNIQUE KEY `userEmailAccount` (`user_id`,`account`),
  KEY `account` (`account`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='User mailbox';

CREATE TABLE `role` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT 'id',
  `created_date` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT 'Creation time',
  `last_modified_date` timestamp NULL DEFAULT NULL COMMENT 'Last modified time',
  `name` varchar(20) NOT NULL COMMENT 'name'.PRIMARY KEY (`id`),
  UNIQUE KEY `name` (`name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT=The 'role';

CREATE TABLE `user` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT 'id',
  `created_date` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT 'Creation time',
  `last_modified_date` timestamp NULL DEFAULT NULL COMMENT 'Last modified time',
  `gender` tinyint(1) unsigned NOT NULL COMMENT 'gender. 0: female, 1: male, 2: unknown ',
  `name` varchar(20) NOT NULL COMMENT 'nickname',
  `validated` tinyint(1) unsigned NOT NULL COMMENT 'Is the account verified?'.PRIMARY KEY (`id`),
  UNIQUE KEY `name` (`name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='users';

CREATE TABLE `user_role` (
  `role_id` int(11) unsigned NOT NULL COMMENT 'character ID',
  `user_id` int(11) unsigned NOT NULL COMMENT 'user ID',
  `created_date` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT 'Creation time',
  `last_modified_date` timestamp NULL DEFAULT NULL COMMENT 'Last modified time'.PRIMARY KEY (`role_id`,`user_id`),
  KEY `roleId` (`role_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='User role association';
Copy the code

This paper summarizes

A lot of things here and here are spring-data-JPA related, and the QueryDsl integration is really just a few things

  • Importing dependent dependencies
  • theJPAQueryFactoryAdd inverse IOC (learn QueryDsl, essentially learn how to use it)

Complete project source code

Github.com/springboot-…