【问题标题】:Automatically updating created/updated date field on the entity in dropwizard hibernate在 dropwizard hibernate 中自动更新实体上的创建/更新日期字段
【发布时间】:2015-02-03 23:41:11
【问题描述】:

我正在使用 Dropwizard Hibernate ( hibernate 4) 来持久化一些简单的实体。

我的实体有一些属性,例如“created_date”、“modified_date”和“deleted_date”。
我希望这些属性在保存/更新时间自动填充/更新。
而且我想在 ORM 级别而不是 DB 上拥有该逻辑。此外,另一方面,出于某些充分的原因,我们正在管理自己的会话。

现在的问题是dropwizard不支持hibernate 4的全部功能。它忽略了@PrePersist@PreUpdate
所以我决定编写自己的自定义SaveOrUpdateEventListener,并将其注册到 sessionFactry 的 EventListener Registry 中。然后我意识到 Dropwizard 确实提供了对 EventListener Registry 的访问。因此进入 dropwizard SessionFactoryFactory 类并对其进行修改以访问 EventListener 注册表。 然后使用以下代码我正在尝试注册我的事件侦听器:

SessionFactory sessionFactory = hibernate.getSessionFactory();
EventListenerRegistry listenerRegistry = sessionFactory.getSessionFactoryOptions().getServiceRegistry().getService(EventListenerRegistry.class);
EventListenerGroup<SaveOrUpdateEventListener> evlg = listenerRegistry.getEventListenerGroup(EventType.SAVE_UPDATE);
evlg.appendListener(new SaveOrUpdateDateListener());

这是我的事件监听器:

public class SaveOrUpdateDateListener extends DefaultSaveOrUpdateEventListener{

    private static final Logger logger = LoggerFactory.getLogger(SaveOrUpdateDateListener.class);

    @Override
    public void onSaveOrUpdate(SaveOrUpdateEvent event) throws HibernateException{
        logger.info("onSaveOrUpdate is being called");
        if (event.getObject() instanceof LastModifiable) {
            LastModifiable record = (LastModifiable) event.getObject();
            record.setCreatedDate(Instant.now());
        }
        super.onSaveOrUpdate(event);
     }
}

这是我的实体类:

@Entity
@EntityListeners(value = { SaveOrUpdateDateListener.class })
@Table (name = "portfolio")
public class PortfolioBusiness implements LastModifiable, Serializable{

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id", nullable = false)
    private long id; 

    @Column(name = "org_id", nullable = false)
    private long orgId; 

    @Column(name = "subscription_id", nullable = false)
    private String subscriptionId;

    @Column(name="duns", nullable = false)
    private int duns; 

    @Column(name="created_by", nullable = false)
    private long createdBy;

    @Column(name="created_date", nullable = false)
    @Convert(converter = InstantPersistenceConverter.class)
    private Instant createdDate; 

    .
    .
    .
}

这是我的实体类的超类:

@MappedSuperclass
@EntityListeners(value = { SaveOrUpdateDateListener.class })
public interface LastModifiable{
    public void setCreatedDate(Instant instant);
}

当我打印出已注册事件侦听器的列表时,我会在那里看到我的事件侦听器。然而,当我尝试保存或更新实体时,我的事件监听器根本没有被调用。它只调用默认事件侦听器。 我已经看过了 https://jira.spring.io/browse/SPR-9381

所以我也想知道是否有人在上述链接中提出的解决方案示例与 Dropwizard 一起使用。

【问题讨论】:

    标签: hibernate event-listener dropwizard


    【解决方案1】:

    我们能够使用拦截器让@PrePersist@PostPersist 工作:

    public class DateTimeInterceptor {
    
        @PrePersist
        public void onPrePersist(Object entity) {
        }
    
        @PreUpdate
        public void onPreUpdate(Object entity) {
        }
    }
    

    在实体中注册拦截器:

    @EntityListeners(value = {DateTimeInterceptor.class, PostInterceptor.class})
    

    但最重要的部分是您需要添加自定义配置文件:

    /src/main/resources/META-INF/services/org.hibernate.integrator.spi.Integrator
    

    其中包含一行:

    org.hibernate.jpa.event.spi.JpaIntegrator
    

    Dropwizard 版本是 0.8.1。试试看,希望对你有帮助

    【讨论】:

    • Audience: 要使上述更改生效,请在您的 pom 或 gradle 中添加 hibernate-entitymanager。
    【解决方案2】:

    使用 Hibernate 5.3 (Dropwizard 1.1) 我不得不对yunspace's answer 进行相当大的调整,但这是一个很好的起点。主要问题是 JpaIntegrator 似乎已被删除,所以我不得不实现自己的集成器:

    public class EntityIntegrator implements Integrator {
        @Override
        public void integrate(final Metadata metadata,
                              final SessionFactoryImplementor sessionFactory,
                              final SessionFactoryServiceRegistry serviceRegistry) {
            final EventListenerRegistry eventListenerRegistry = serviceRegistry.getService(EventListenerRegistry.class);
    
            eventListenerRegistry.appendListeners(EventType.PRE_UPDATE, EventListener.class);
            eventListenerRegistry.appendListeners(EventType.PRE_INSERT, EventListener.class);
        }
    
        @Override
        public void disintegrate(final SessionFactoryImplementor sessionFactory,
                                 final SessionFactoryServiceRegistry serviceRegistry) {
            // no-op
        }
    }
    

    然后在/src/main/resources/META-INF/services/org.hibernate.integrator.spi.Integrator:

    your.package.here.EntityIntegrator
    

    最后,实现集成器中引用的EventListener 类:

    public class EventListener implements PreUpdateEventListener, PreInsertEventListener {
        @Override
        public boolean onPreInsert(final PreInsertEvent event) {
            // your logic here
        }
        
        @Override
        public boolean onPreUpdate(final PreUpdateEvent event) {
            // your logic here
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-02-22
      • 1970-01-01
      • 2010-09-23
      • 2017-07-31
      • 1970-01-01
      相关资源
      最近更新 更多