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.
BaseEntity
Abstract out the common fieldsUser
The userEmail
One-to-many association of user email addressesRole
roleUserRole
Many-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
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
- the
JPAQueryFactory
Add inverse IOC (learn QueryDsl, essentially learn how to use it)
Complete project source code
Github.com/springboot-…