feat: 优化查询方法
This commit is contained in:
52
pom.xml
52
pom.xml
@@ -15,7 +15,7 @@
|
|||||||
|
|
||||||
<spring-boot.version>3.4.3</spring-boot.version>
|
<spring-boot.version>3.4.3</spring-boot.version>
|
||||||
<spring-cloud.version>2024.0.1</spring-cloud.version>
|
<spring-cloud.version>2024.0.1</spring-cloud.version>
|
||||||
<eclipse-collections.version>11.1.0</eclipse-collections.version>
|
<querydsl.version>5.1.0</querydsl.version>
|
||||||
</properties>
|
</properties>
|
||||||
|
|
||||||
<dependencies>
|
<dependencies>
|
||||||
@@ -30,7 +30,21 @@
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.blinkfox</groupId>
|
<groupId>com.blinkfox</groupId>
|
||||||
<artifactId>fenix-spring-boot-starter</artifactId>
|
<artifactId>fenix-spring-boot-starter</artifactId>
|
||||||
<version>3.0.0</version>
|
<version>3.1.0</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.querydsl</groupId>
|
||||||
|
<artifactId>querydsl-apt</artifactId>
|
||||||
|
<version>${querydsl.version}</version>
|
||||||
|
<scope>provided</scope>
|
||||||
|
<classifier>jakarta</classifier>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.querydsl</groupId>
|
||||||
|
<artifactId>querydsl-jpa</artifactId>
|
||||||
|
<version>${querydsl.version}</version>
|
||||||
|
<classifier>jakarta</classifier>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
@@ -60,6 +74,40 @@
|
|||||||
</dependencies>
|
</dependencies>
|
||||||
</dependencyManagement>
|
</dependencyManagement>
|
||||||
|
|
||||||
|
<build>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>com.mysema.maven</groupId>
|
||||||
|
<artifactId>apt-maven-plugin</artifactId>
|
||||||
|
<version>1.1.3</version>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<id>compile-dsl</id>
|
||||||
|
<phase>compile</phase>
|
||||||
|
<goals>
|
||||||
|
<goal>process</goal>
|
||||||
|
</goals>
|
||||||
|
<configuration>
|
||||||
|
<processor>com.querydsl.apt.jpa.JPAAnnotationProcessor</processor>
|
||||||
|
<outputDirectory>target/generated-sources/java</outputDirectory>
|
||||||
|
</configuration>
|
||||||
|
</execution>
|
||||||
|
<execution>
|
||||||
|
<id>test-compile-dsl</id>
|
||||||
|
<phase>test-compile</phase>
|
||||||
|
<goals>
|
||||||
|
<goal>test-process</goal>
|
||||||
|
</goals>
|
||||||
|
<configuration>
|
||||||
|
<processor>com.querydsl.apt.jpa.JPAAnnotationProcessor</processor>
|
||||||
|
<outputDirectory>target/generated-test-sources/java</outputDirectory>
|
||||||
|
</configuration>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
|
||||||
<distributionManagement>
|
<distributionManagement>
|
||||||
<repository>
|
<repository>
|
||||||
<id>${releases.id}</id>
|
<id>${releases.id}</id>
|
||||||
|
|||||||
@@ -210,22 +210,22 @@ public class Query {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static class Between {
|
public static class Between {
|
||||||
private String start;
|
private Object start;
|
||||||
private String end;
|
private Object end;
|
||||||
|
|
||||||
public String getStart() {
|
public Object getStart() {
|
||||||
return start;
|
return start;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setStart(String start) {
|
public void setStart(Object start) {
|
||||||
this.start = start;
|
this.start = start;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getEnd() {
|
public Object getEnd() {
|
||||||
return end;
|
return end;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setEnd(String end) {
|
public void setEnd(Object end) {
|
||||||
this.end = end;
|
this.end = end;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -5,19 +5,44 @@ import java.util.Map;
|
|||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
|
||||||
public class ObjectHelper {
|
public class ObjectHelper {
|
||||||
|
/**
|
||||||
|
* 判断对象是否为null
|
||||||
|
*
|
||||||
|
* @param obj 待检查的对象
|
||||||
|
* @return 如果对象为null返回true,否则返回false
|
||||||
|
*/
|
||||||
public static boolean isNull(Object obj) {
|
public static boolean isNull(Object obj) {
|
||||||
return obj == null;
|
return obj == null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 判断对象是否不为null
|
||||||
|
*
|
||||||
|
* @param obj 待判断的对象
|
||||||
|
* @return 如果对象不为null则返回true,否则返回false
|
||||||
|
*/
|
||||||
public static boolean isNotNull(Object obj) {
|
public static boolean isNotNull(Object obj) {
|
||||||
return !isNull(obj);
|
return !isNull(obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 判断对象是否为空
|
||||||
|
*
|
||||||
|
* @param obj 待判断的对象
|
||||||
|
* @return 如果对象为null或为空则返回true,否则返回false
|
||||||
|
*/
|
||||||
public static boolean isEmpty(Object obj) {
|
public static boolean isEmpty(Object obj) {
|
||||||
|
// 首先判断对象是否为null
|
||||||
if (isNull(obj)) return true;
|
if (isNull(obj)) return true;
|
||||||
|
// 判断是否为集合类型
|
||||||
else if (obj instanceof Collection<?> collection) return collection.isEmpty();
|
else if (obj instanceof Collection<?> collection) return collection.isEmpty();
|
||||||
|
// 判断是否为Map类型
|
||||||
else if (obj instanceof Map<?, ?> map) return map.isEmpty();
|
else if (obj instanceof Map<?, ?> map) return map.isEmpty();
|
||||||
|
// 判断是否为字符序列类型
|
||||||
else if (obj instanceof CharSequence sequence) return sequence.isEmpty();
|
else if (obj instanceof CharSequence sequence) return sequence.isEmpty();
|
||||||
|
// 判断是否为各种基本类型数组
|
||||||
else if (obj instanceof Object[] array) return array.length == 0;
|
else if (obj instanceof Object[] array) return array.length == 0;
|
||||||
else if (obj instanceof byte[] array) return array.length == 0;
|
else if (obj instanceof byte[] array) return array.length == 0;
|
||||||
else if (obj instanceof short[] array) return array.length == 0;
|
else if (obj instanceof short[] array) return array.length == 0;
|
||||||
@@ -27,10 +52,13 @@ public class ObjectHelper {
|
|||||||
else if (obj instanceof double[] array) return array.length == 0;
|
else if (obj instanceof double[] array) return array.length == 0;
|
||||||
else if (obj instanceof char[] array) return array.length == 0;
|
else if (obj instanceof char[] array) return array.length == 0;
|
||||||
else if (obj instanceof boolean[] array) return array.length == 0;
|
else if (obj instanceof boolean[] array) return array.length == 0;
|
||||||
|
// 判断是否为Optional类型
|
||||||
else if (obj instanceof Optional<?> optional) return optional.isEmpty();
|
else if (obj instanceof Optional<?> optional) return optional.isEmpty();
|
||||||
|
// 其他情况认为对象不为空
|
||||||
else return false;
|
else return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public static boolean isNotEmpty(Object obj) {
|
public static boolean isNotEmpty(Object obj) {
|
||||||
return !isEmpty(obj);
|
return !isEmpty(obj);
|
||||||
}
|
}
|
||||||
@@ -38,4 +66,44 @@ public class ObjectHelper {
|
|||||||
public static <T> T defaultIfNull(final T object, final T defaultValue) {
|
public static <T> T defaultIfNull(final T object, final T defaultValue) {
|
||||||
return isNull(object) ? defaultValue : object;
|
return isNull(object) ? defaultValue : object;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 判断给定的类是否可比较
|
||||||
|
*
|
||||||
|
* @param clazz 待判断的类对象
|
||||||
|
* @return 如果类是枚举、字符序列、可比较接口的实现类或基本数据类型则返回true,否则返回false
|
||||||
|
*/
|
||||||
|
public static boolean isComparable(Class<?> clazz) {
|
||||||
|
if (isNull(clazz)) return false;
|
||||||
|
// 判断类是否为可比较类型:枚举、字符序列、可比较接口实现类或基本数据类型
|
||||||
|
return clazz.isEnum() ||
|
||||||
|
CharSequence.class.isAssignableFrom(clazz) ||
|
||||||
|
Comparable.class.isAssignableFrom(clazz) ||
|
||||||
|
clazz.isPrimitive();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean isComparable(Object obj) {
|
||||||
|
if (isNull(obj)) return false;
|
||||||
|
return isComparable(obj.getClass());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean isCollection(Class<?> clazz) {
|
||||||
|
if (isNull(clazz)) return false;
|
||||||
|
return Collection.class.isAssignableFrom(clazz);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean isCollection(Object obj) {
|
||||||
|
if (isNull(obj)) return false;
|
||||||
|
return isCollection(obj.getClass());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean isString(Class<?> clazz) {
|
||||||
|
if (isNull(clazz)) return false;
|
||||||
|
return String.class.isAssignableFrom(clazz);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean isString(Object obj) {
|
||||||
|
if (isNull(obj)) return false;
|
||||||
|
return isString(obj.getClass());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -2,9 +2,10 @@ package com.lanyuanxiaoyao.service.template.repository;
|
|||||||
|
|
||||||
import com.blinkfox.fenix.jpa.FenixJpaRepository;
|
import com.blinkfox.fenix.jpa.FenixJpaRepository;
|
||||||
import com.blinkfox.fenix.specification.FenixJpaSpecificationExecutor;
|
import com.blinkfox.fenix.specification.FenixJpaSpecificationExecutor;
|
||||||
|
import org.springframework.data.querydsl.QuerydslPredicateExecutor;
|
||||||
import org.springframework.data.repository.NoRepositoryBean;
|
import org.springframework.data.repository.NoRepositoryBean;
|
||||||
import org.springframework.data.repository.query.QueryByExampleExecutor;
|
import org.springframework.data.repository.query.QueryByExampleExecutor;
|
||||||
|
|
||||||
@NoRepositoryBean
|
@NoRepositoryBean
|
||||||
public interface SimpleRepository<E, ID> extends FenixJpaRepository<E, ID>, FenixJpaSpecificationExecutor<E>, QueryByExampleExecutor<E> {
|
public interface SimpleRepository<E, ID> extends FenixJpaRepository<E, ID>, FenixJpaSpecificationExecutor<E>, QueryByExampleExecutor<E>, QuerydslPredicateExecutor<E> {
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ import jakarta.persistence.criteria.Predicate;
|
|||||||
import jakarta.persistence.criteria.Root;
|
import jakarta.persistence.criteria.Root;
|
||||||
import jakarta.transaction.Transactional;
|
import jakarta.transaction.Transactional;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
@@ -120,10 +121,18 @@ public abstract class SimpleServiceSupport<ENTITY extends SimpleEntity> implemen
|
|||||||
queryable.getNotNullEqual().forEach(column -> predicates.add(builder.isNotNull(column(root, column))));
|
queryable.getNotNullEqual().forEach(column -> predicates.add(builder.isNotNull(column(root, column))));
|
||||||
}
|
}
|
||||||
if (ObjectHelper.isNotEmpty(queryable.getEmpty())) {
|
if (ObjectHelper.isNotEmpty(queryable.getEmpty())) {
|
||||||
queryable.getEmpty().forEach(column -> predicates.add(builder.isEmpty(column(root, column))));
|
queryable.getEmpty().forEach(column -> {
|
||||||
|
var path = this.<Collection<Object>>column(root, column);
|
||||||
|
checkCollection(path, column);
|
||||||
|
predicates.add(builder.isEmpty(path));
|
||||||
|
});
|
||||||
}
|
}
|
||||||
if (ObjectHelper.isNotEmpty(queryable.getNotEmpty())) {
|
if (ObjectHelper.isNotEmpty(queryable.getNotEmpty())) {
|
||||||
queryable.getNotEmpty().forEach(column -> predicates.add(builder.isNotEmpty(column(root, column))));
|
queryable.getNotEmpty().forEach(column -> {
|
||||||
|
var path = this.<Collection<Object>>column(root, column);
|
||||||
|
checkCollection(path, column);
|
||||||
|
predicates.add(builder.isNotEmpty(path));
|
||||||
|
});
|
||||||
}
|
}
|
||||||
if (ObjectHelper.isNotEmpty(queryable.getEqual())) {
|
if (ObjectHelper.isNotEmpty(queryable.getEqual())) {
|
||||||
queryable.getEqual().forEach((column, value) -> {
|
queryable.getEqual().forEach((column, value) -> {
|
||||||
@@ -138,22 +147,52 @@ public abstract class SimpleServiceSupport<ENTITY extends SimpleEntity> implemen
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (ObjectHelper.isNotEmpty(queryable.getLike())) {
|
if (ObjectHelper.isNotEmpty(queryable.getLike())) {
|
||||||
queryable.getLike().forEach((column, value) -> predicates.add(builder.like(column(root, column), value)));
|
queryable.getLike().forEach((column, value) -> {
|
||||||
|
var path = column(root, column);
|
||||||
|
checkString(path, column);
|
||||||
|
checkString(value, column);
|
||||||
|
predicates.add(builder.like(column(root, column), value));
|
||||||
|
});
|
||||||
}
|
}
|
||||||
if (ObjectHelper.isNotEmpty(queryable.getNotLike())) {
|
if (ObjectHelper.isNotEmpty(queryable.getNotLike())) {
|
||||||
queryable.getNotLike().forEach((column, value) -> predicates.add(builder.notLike(column(root, column), value)));
|
queryable.getNotLike().forEach((column, value) -> {
|
||||||
|
var path = column(root, column);
|
||||||
|
checkString(path, column);
|
||||||
|
checkString(value, column);
|
||||||
|
predicates.add(builder.notLike(column(root, column), value));
|
||||||
|
});
|
||||||
}
|
}
|
||||||
if (ObjectHelper.isNotEmpty(queryable.getGreat())) {
|
if (ObjectHelper.isNotEmpty(queryable.getGreat())) {
|
||||||
queryable.getGreat().forEach((column, value) -> predicates.add(builder.greaterThan(column(root, column), (Comparable<Object>) value)));
|
queryable.getGreat().forEach((column, value) -> {
|
||||||
|
var path = this.<Comparable<Object>>column(root, column);
|
||||||
|
checkComparable(path, column);
|
||||||
|
checkComparable(value, column);
|
||||||
|
predicates.add(builder.greaterThan(path, (Comparable<Object>) value));
|
||||||
|
});
|
||||||
}
|
}
|
||||||
if (ObjectHelper.isNotEmpty(queryable.getLess())) {
|
if (ObjectHelper.isNotEmpty(queryable.getLess())) {
|
||||||
queryable.getLess().forEach((column, value) -> predicates.add(builder.lessThan(column(root, column), (Comparable<Object>) value)));
|
queryable.getLess().forEach((column, value) -> {
|
||||||
|
var path = this.<Comparable<Object>>column(root, column);
|
||||||
|
checkComparable(path, column);
|
||||||
|
checkComparable(value, column);
|
||||||
|
predicates.add(builder.lessThan(path, (Comparable<Object>) value));
|
||||||
|
});
|
||||||
}
|
}
|
||||||
if (ObjectHelper.isNotEmpty(queryable.getGreatEqual())) {
|
if (ObjectHelper.isNotEmpty(queryable.getGreatEqual())) {
|
||||||
queryable.getGreatEqual().forEach((column, value) -> predicates.add(builder.greaterThanOrEqualTo(column(root, column), (Comparable<Object>) value)));
|
queryable.getGreatEqual().forEach((column, value) -> {
|
||||||
|
var path = this.<Comparable<Object>>column(root, column);
|
||||||
|
checkComparable(path, column);
|
||||||
|
checkComparable(value, column);
|
||||||
|
predicates.add(builder.greaterThanOrEqualTo(path, (Comparable<Object>) value));
|
||||||
|
});
|
||||||
}
|
}
|
||||||
if (ObjectHelper.isNotEmpty(queryable.getLessEqual())) {
|
if (ObjectHelper.isNotEmpty(queryable.getLessEqual())) {
|
||||||
queryable.getLessEqual().forEach((column, value) -> predicates.add(builder.lessThanOrEqualTo(column(root, column), (Comparable<Object>) value)));
|
queryable.getLessEqual().forEach((column, value) -> {
|
||||||
|
var path = this.<Comparable<Object>>column(root, column);
|
||||||
|
checkComparable(path, column);
|
||||||
|
checkComparable(value, column);
|
||||||
|
predicates.add(builder.lessThanOrEqualTo(path, (Comparable<Object>) value));
|
||||||
|
});
|
||||||
}
|
}
|
||||||
if (ObjectHelper.isNotEmpty(queryable.getIn())) {
|
if (ObjectHelper.isNotEmpty(queryable.getIn())) {
|
||||||
queryable.getIn().forEach((column, value) -> predicates.add(builder.in(column(root, column)).value(value)));
|
queryable.getIn().forEach((column, value) -> predicates.add(builder.in(column(root, column)).value(value)));
|
||||||
@@ -162,14 +201,65 @@ public abstract class SimpleServiceSupport<ENTITY extends SimpleEntity> implemen
|
|||||||
queryable.getNotIn().forEach((column, value) -> predicates.add(builder.in(column(root, column)).value(value).not()));
|
queryable.getNotIn().forEach((column, value) -> predicates.add(builder.in(column(root, column)).value(value).not()));
|
||||||
}
|
}
|
||||||
if (ObjectHelper.isNotEmpty(queryable.getBetween())) {
|
if (ObjectHelper.isNotEmpty(queryable.getBetween())) {
|
||||||
queryable.getBetween().forEach((column, value) -> predicates.add(builder.between(column(root, column), value.getStart(), value.getEnd())));
|
queryable.getBetween().forEach((column, value) -> {
|
||||||
|
var path = this.<Comparable<Object>>column(root, column);
|
||||||
|
checkComparable(path, column);
|
||||||
|
checkComparable(value, column);
|
||||||
|
predicates.add(builder.between(column(root, column), (Comparable<Object>) value.getStart(), (Comparable<Object>) value.getEnd()));
|
||||||
|
});
|
||||||
}
|
}
|
||||||
if (ObjectHelper.isNotEmpty(queryable.getNotBetween())) {
|
if (ObjectHelper.isNotEmpty(queryable.getNotBetween())) {
|
||||||
queryable.getNotBetween().forEach((column, value) -> predicates.add(builder.between(column(root, column), value.getStart(), value.getEnd())));
|
queryable.getNotBetween().forEach((column, value) -> {
|
||||||
|
var path = this.<Comparable<Object>>column(root, column);
|
||||||
|
checkComparable(path, column);
|
||||||
|
checkComparable(value, column);
|
||||||
|
predicates.add(builder.between(column(root, column), (Comparable<Object>) value.getStart(), (Comparable<Object>) value.getEnd()).not());
|
||||||
|
});
|
||||||
}
|
}
|
||||||
return predicates;
|
return predicates;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void checkComparable(Path<?> path, String column) {
|
||||||
|
if (!ObjectHelper.isComparable(path.getJavaType())) {
|
||||||
|
throw new NotComparableException(column);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void checkComparable(Object value, String column) {
|
||||||
|
if (!ObjectHelper.isComparable(value)) {
|
||||||
|
throw new NotComparableException(column);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void checkComparable(Query.Queryable.Between value, String column) {
|
||||||
|
checkComparable(value.getStart(), column);
|
||||||
|
checkComparable(value.getEnd(), column);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void checkCollection(Path<?> path, String column) {
|
||||||
|
if (!ObjectHelper.isCollection(path.getJavaType())) {
|
||||||
|
throw new NotCollectionException(column);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void checkCollection(Object value, String column) {
|
||||||
|
if (!ObjectHelper.isCollection(value)) {
|
||||||
|
throw new NotCollectionException(column);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void checkString(Path<?> path, String column) {
|
||||||
|
if (!ObjectHelper.isString(path.getJavaType())) {
|
||||||
|
throw new NotStringException(column);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void checkString(Object value, String column) {
|
||||||
|
if (!ObjectHelper.isString(value)) {
|
||||||
|
throw new NotStringException(column);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
protected List<Predicate> listPredicate(Root<ENTITY> root, CriteriaQuery<?> query, CriteriaBuilder builder) {
|
protected List<Predicate> listPredicate(Root<ENTITY> root, CriteriaQuery<?> query, CriteriaBuilder builder) {
|
||||||
return new ArrayList<>(0);
|
return new ArrayList<>(0);
|
||||||
}
|
}
|
||||||
@@ -240,4 +330,22 @@ public abstract class SimpleServiceSupport<ENTITY extends SimpleEntity> implemen
|
|||||||
super("ID为 %d 的资源不存在".formatted(id));
|
super("ID为 %d 的资源不存在".formatted(id));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static final class NotComparableException extends RuntimeException {
|
||||||
|
public NotComparableException(String variable) {
|
||||||
|
super("变量 %s 不能比较".formatted(variable));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final class NotCollectionException extends RuntimeException {
|
||||||
|
public NotCollectionException(String variable) {
|
||||||
|
super("变量 %s 不是集合".formatted(variable));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final class NotStringException extends RuntimeException {
|
||||||
|
public NotStringException(String variable) {
|
||||||
|
super("变量 %s 不是字符串".formatted(variable));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ import org.hibernate.annotations.Comment;
|
|||||||
import org.hibernate.annotations.DynamicUpdate;
|
import org.hibernate.annotations.DynamicUpdate;
|
||||||
import org.springframework.data.jpa.domain.support.AuditingEntityListener;
|
import org.springframework.data.jpa.domain.support.AuditingEntityListener;
|
||||||
|
|
||||||
|
|
||||||
@Entity
|
@Entity
|
||||||
@DynamicUpdate
|
@DynamicUpdate
|
||||||
@EntityListeners(AuditingEntityListener.class)
|
@EntityListeners(AuditingEntityListener.class)
|
||||||
|
|||||||
Reference in New Issue
Block a user