如何在Embeddable上触发EntityListener

时间:2012-11-15 12:43:50

标签: java java-ee jpa jpa-2.0

我有一个EmebeddedId的实体。正在按预期触发实体监听器(在加载时修剪Strings关闭空白)实体监听器,ID Embeddable上的同一监听器根本不会被触发。

我做错了吗?如何解决?

实体:

@Entity
@Table(name = "SUBMITTER_VIEW")
@EntityListeners(TrimListener.class)
public class Submitter implements Serializable {

    private static final long serialVersionUID = 1L;

    @EmbeddedId
    private SubmitterPK id;

    @Trim
    @Column(name = "DOC_NAME")
    private String name;
...

嵌入式:

@Embeddable
@EntityListeners(TrimListener.class)
public class SubmitterPK implements Serializable {

    private static final long serialVersionUID = 1L;

    @Column(name = "LSTORT")
    private String bsnr;

    @Trim
    @Column(name = "LOGIN")
    private String login;
...

监听器:

public class TrimListener {

    Logger log = LoggerFactory.getLogger("TrimListener");

    @PostLoad
    public void repairAfterLoad(final Object entity) throws IllegalAccessException {

        log.debug("trimlistener active");

        final Set<Field> trimProps = getTrimProperties(entity.getClass());

        for (final Field fieldToTrim : trimProps) {
            final String propertyValue = (String) fieldToTrim.get(entity);
            if (propertyValue != null) {
                fieldToTrim.set(entity, propertyValue.trim());
            }
        }
    }
...

2 个答案:

答案 0 :(得分:3)

我认为它显然被忽略了,因为它不是JPA 2.0所期望的标准场所。根据JPA 2.0最终规范,实体监听器可以是实体,映射的超类或与其中一个相关联的监听器(参见规范的第3.5节):

  

可以将方法指定为生命周期回调方法,以接收实体生命周期的通知   事件。可以在实体类,映射的超类或实体上定义生命周期回调方法   与实体或映射的超类相关联的侦听器类

答案 1 :(得分:2)

我已经调整了EntityListener,以递归方式跟随使用Embeddable注释的字段。现在,如果实体使用侦听器,则也会处理所有嵌入的类:

public class TrimListener {

    @PostLoad
    public void trimAfterLoad(final Object entity) throws IllegalAccessException {

        final Set<Trimmable> trimProps = getTrimProperties(entity);

        for (final Trimmable trimmable : trimProps) {
            final String propertyValue = (String) trimmable.field.get(trimmable.target);
            if (propertyValue != null) {
                trimmable.field.set(trimmable.target, propertyValue.trim());
            }
        }
    }

    private Set<Trimmable> getTrimProperties(final Object entity) throws IllegalAccessException {

        final Class<?> entityClass = entity.getClass();
        final Set<Trimmable> propertiesToTrim = new HashSet<Trimmable>();

        for (final Field field : entityClass.getDeclaredFields()) {
            if (field.getType().equals(String.class) && (field.getAnnotation(Trim.class) != null)) {
                field.setAccessible(true);
                propertiesToTrim.add(new Trimmable(entity, field));
                // if the entity contains embeddables, propagate the trimming
            } else if (field.getType().getAnnotation(Embeddable.class) != null) {
                field.setAccessible(true);
                propertiesToTrim.addAll(getTrimProperties(field.get(entity)));
            }
        }
        return propertiesToTrim;
    }

    private class Trimmable {

        final Object target;
        final Field field;

        public Trimmable(final Object target, final Field field) {
            this.target = target;
            this.field = field;
        }
    }
}