4

を持つエンティティがあり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());
            }
        }
    }
...
4

2 に答える 2

3

JPA 2.0が期待する標準的な場所ではないため、明らかに無視されていると思います。JPA 2.0 最終仕様によると、エンティティ リスナーは、エンティティ、マップされたスーパークラス、またはそれらのいずれかに関連付けられたリスナーの場合があります (仕様のセクション 3.5 を参照)。

メソッドは、エンティティ ライフサイクル イベントの通知を受け取るライフサイクル コールバック メソッドとして指定できます。ライフサイクル コールバック メソッドは、エンティティ クラス、マップされたスーパークラス、またはエンティティまたはマップされたスーパークラスに関連付けられたエンティティ リスナー クラスで定義できます。

于 2012-11-15T13:28:57.160 に答える
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;
        }
    }
}
于 2012-11-15T15:16:47.303 に答える