首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >JPA实体侦听器和@embeddable

JPA实体侦听器和@embeddable
EN

Stack Overflow用户
提问于 2010-06-01 09:28:29
回答 2查看 4.9K关注 0票数 3

我有一个JPA实体的类层次结构,所有这些实体都是从BaseEntity类继承的:

代码语言:javascript
复制
@MappedSuperclass
@EntityListeners( { ValidatorListener.class })
public abstract class BaseEntity implements Serializable {
    // other stuff
}

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

我的ValidatorListener:

代码语言:javascript
复制
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接口(外部接口只是一个标记,内部包含方法):

代码语言:javascript
复制
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(){ //首先//验证我自己的属性: myEmbeddable.persistOrUpdate();//这是可行的,但是我希望不需要手动调用}

  • 使用反射,检查所有属性是否属于它们的接口类型。这是可行的,但不漂亮。有更优雅的解决方案吗?
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2010-06-01 19:17:30

考虑基于注释的方法。它将产生更少的代码(似乎),而且几乎总是更容易理解。

引入新的注释:

代码语言:javascript
复制
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE, ElementType.METHOD})
public @interface Validators {
  String[] values();
}

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

代码语言:javascript
复制
@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接口:

代码语言:javascript
复制
public interface Validateable {
  void validate(Type type);
}

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

如果实体被@Validators;

  • if注释,如果实体实现了Validateable;

  • if而不是迭代,那么
  1. 检查实体是否迭代,如果实体实现了Validateable
  2. if而不是迭代嵌入元素(可能会为实体发出警告:‘实体标记为Validators,但没有实现Validatable interface')
  3. if --是的,那么如果适用类型,运行validate对应于侦听器;
  4. 以与上面相同的逻辑迭代嵌入元素。

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

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

票数 1
EN

Stack Overflow用户

发布于 2010-06-01 10:18:58

好吧,这是我自己的解决方案:

http://pastebin.com/YPmt7ifm

我使用spring BeanUtils来迭代属性。还有:有人有一个更优雅的解决方案吗?

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/2948578

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档