gpt4 book ai didi

java - JPA 实体监听器和@embeddable

转载 作者:塔克拉玛干 更新时间:2023-11-02 20:19:17 26 4
gpt4 key购买 nike

我有一个 JPA 实体的类层次结构,它们都继承自 BaseEntity 类:

@MappedSuperclass
@EntityListeners( { ValidatorListener.class })
public abstract class BaseEntity implements Serializable {
// other stuff
}

我希望所有实现给定接口(interface)的实体在持久化和/或更新时自动得到验证。这就是我得到的。

我的 validator 监听器:

public class ValidatorListener {

private enum Type {
PERSIST, UPDATE
}

@PrePersist
public void checkPersist(final Object entity) {
if (entity instanceof Validateable) {
this.check((Validateable) entity, Type.PERSIST);
}
}

@PreUpdate
public void checkUpdate(final Object entity) {
if (entity instanceof Validateable) {
this.check((Validateable) entity, Type.UPDATE);
}
}

private void check(final Validateable entity, final Type persist) {
switch (persist) {
case PERSIST:
if (entity instanceof Persist) {
((Persist) entity).persist();
}
if (entity instanceof PersistOrUpdate) {
((PersistOrUpdate) entity).persistOrUpdate();
}
break;
case UPDATE:
if (entity instanceof Update) {
((Update) entity).update();
}
if (entity instanceof PersistOrUpdate) {
((PersistOrUpdate) entity).persistOrUpdate();
}
break;

default:
break;
}
}

}

这是它检查的我的 Validateable 接口(interface)(外部接口(interface)只是一个标记,内部接口(interface)包含方法):

public interface Validateable {

interface Persist extends Validateable {
void persist();
}

interface PersistOrUpdate extends Validateable {
void persistOrUpdate();
}

interface Update extends Validateable {
void update();
}

}

所有这些都有效,但我想将此行为扩展到可嵌入类。我知道两种解决方案:

  1. 从实体验证方法中手动调用可嵌入对象的验证方法:

    public void persistOrUpdate(){
    // validate my own properties first
    // then manually validate the embeddable property:
    myEmbeddable.persistOrUpdate();
    // this works but I'd like something that I don't have to call manually
    }
  2. 使用反射,检查所有属性以查看它们的类型是否属于它们的接口(interface)类型之一。这会起作用,但它并不漂亮。有没有更优雅的方案?

最佳答案

考虑基于注解的方法。它会产生更少的代码(看起来)并且几乎总是更容易理解。

引入新注解:

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE, ElementType.METHOD})
public @interface Validators {
String[] values();
}

将此注解应用于每个需要验证的实体和可嵌入对象,例如:

@MappedSuperclass
@EntityListeners( { ValidatorListener.class })
@Validators({Type.PERSIST, Type.UPDATE})
public abstract class MyEntity extends BaseEntity implements Serializable, Validateable {
// other stuff
@Validators(Type.PERSIST)
@Embedded
public Address getAddress() {
return address;
}
}

当然,每个实体和可嵌入对象仍然应该实现更简单的 Validateable 接口(interface):

public interface Validateable {
void validate(Type type);
}

然后验证逻辑变得更简单:

  1. 检查实体是否用@Validators注解;
  2. 如果不是,则转到迭代嵌入元素;
  3. 检查实体是否实现Validateable
  4. 如果不是,则迭代嵌入式元素(可能对实体发出警告:“实体标记有 Validators 但未实现 Validatable 接口(interface)”)
  5. 如果两者都是,则运行validate 如果适用类型对应于监听器;
  6. 使用与上述相同的逻辑迭代嵌入元素。

此方法允许您将对实体及其可嵌入元素(注释)的声明验证与验证逻辑(Java 类 - 实体和可嵌入类)分开。例如,有时可嵌入对象可能会实现 Validateable 但不需要验证。似乎 listener 也变得更简单了。

但是,如果您不是在将验证声明与验证逻辑分开之后,那么您的解决方案就非常令人满意并且可能更简单。

关于java - JPA 实体监听器和@embeddable,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2948578/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com