hibernate中的PreInsert和PreUpdate事件监听器

时间:2013-12-04 06:28:38

标签: java hibernate orm event-listener

我使用PreInsertEventListenerPreInsertEventListener事件侦听器在表格中插入创建日期和更新日期。
我面临的问题是,当我在数据库中保存实体时创建的日期无法插入表中,与更新记录时插入更新日期相同,它也不会插入更新日期。

我的代码示例显示如下:

听众类:

public class PreInsertListener implements PreInsertEventListener,  
                                          PreUpdateEventListener 
{
    @Override
    public boolean onPreInsert(PreInsertEvent arg0) {
        City.class.cast(arg0.getEntity()).setCreated_date(new Date());
        return false;
    }

    @Override
    public boolean onPreUpdate(PreUpdateEvent arg0) {
        System.out.println("Update event......");
        City.class.cast(arg0.getEntity()).setUpdated_date(new Date());
        return false;
    }
}

Hibernate Connection类:

public class HibernateUtil 

{

private static final SessionFactory sessionFactory;

static {
    try {
        AnnotationConfiguration config = new AnnotationConfiguration();
        config.setListener("pre-insert", new PreInsertListener());
        config.setListener("pre-update", new PreInsertListener());
        sessionFactory = config.configure().buildSessionFactory();;

    } catch (Throwable ex) {
        System.err.println("Initial SessionFactory creation failed." + ex);
        throw new ExceptionInInitializerError(ex);
    }
}

   public static SessionFactory getSessionFactory() {
        return sessionFactory;
   }
}

DAO中的实体保存和更新方法:

public Long saveCity(String cityName)
{
    Session session = HibernateUtil.getSessionFactory().openSession();
    Transaction transaction = null;
    Long cityId = null;
    try {
        transaction = session.beginTransaction();
        City city = new City();
        city.setName(cityName);
        cityId = (Long) session.save(city);
        //session.flush();
        transaction.commit();
    } catch (HibernateException e) {
        transaction.rollback();
        e.printStackTrace();
    } finally {
        session.close();
    }
    return cityId;
}

public void updateCity(Long cityId, String cityName)
{
    Session session = HibernateUtil.getSessionFactory().openSession();
    Transaction transaction = null;
    try {
        transaction = session.beginTransaction();
        City city = (City) session.get(City.class, cityId);
        city.setName(cityName);
        session.update(city);
        //session.flush();
        transaction.commit();
    } catch (HibernateException e) {
        transaction.rollback();
        e.printStackTrace();
    } finally {
        session.close();
    }
}

我的测试班:

public class Main 
{
    public static void main(String[] args) {

        CityDAO cityDAO = new CityDAO();

        long cityId1 = cityDAO.saveCity("New York");

        cityDAO.updateCity(cityId1, "Paris");
    }
 }

如果我使用session.flush(),它将插入创建和更新的日期,但每次调用flush方法时都会执行更新的查询。目前我评论了代码来调用代码中显示的session.flush()方法。

这个问题的解决方案是什么?

3 个答案:

答案 0 :(得分:3)

这样做

public class PreInsertListener implements PreInsertEventListener,  
                                          PreUpdateEventListener 
{
    @Override
    public boolean onPreInsert(PreInsertEvent arg0) {
        if(arg0.getEntity() instanceof City){
            City city = (City)arg0.getEntity();
            city.setCreated_date(new Date());               
        }
        return false;
    }

    @Override
    public boolean onPreUpdate(PreUpdateEvent arg0) {
         if(arg0.getEntity() instanceof City){
            City city = (City)arg0.getEntity();
            city.setCreated_date(new Date());                
        }
        return false;
    }
}

答案 1 :(得分:2)

我创建了Interceptor,用Hibernate EmptyInterceptor扩展它 覆盖方法onSave()将在保存对象时调用,该对象尚未保存到数据库中,onFlushDirty()在更新对象时调用该对象,该对象尚未更新到数据库中。
在这个函数中,我通过其名称检查我的方法,我必须在创建或更新时设置日期 这是onFlushDirty()方法的示例代码。

public boolean onFlushDirty(Object entity,Serializable id,Object[] currentState, 
                  Object[] previousState,String[] propertyNames, Type[] types) 
{

    if ( entity instanceof City ) {

        for ( int i=0; i < propertyNames.length; i++ ) {
            if ( "lastUpdatedOn".equals( propertyNames[i] ) ) {
                currentState[i] = new Date();
                return true;
            }
        }
    }
    return false;
}  

此处lastUpdatedOn是我的方法名称,用于设置更新的记录日期。

onSave()方法:

public boolean onSave(Object entity, Serializable id, Object[] state,   
                     String[] propertyNames, Type[] types)   
{
    if ( entity instanceof City) {

        for ( int i=0; i<propertyNames.length; i++ ) {
            if ( "createdOn".equals( propertyNames[i] ) ) {
                state[i] = new Date();
                return true;
            }
        }
    }
    return false;
}

此处createdOn是设置记录创建日期的方法。

使用此拦截器类扩展您的POJO类。

答案 2 :(得分:0)

当我集成Spring4和Hibernate5时,我最近遇到了同样的问题。 这是我的BaseEntity类。

List<IMessage> Messages = new List<IMessage>(){new SmsMessage("SomeText"), 
EmailMessage("Hi!", "To Brad Pitt")};

首先,您需要定义EntityListener类。

@MappedSuperclass
public class BaseEntity implements Serializable {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

    @Column(nullable = false, updatable = false)
    private Date createDate;

    @Column(nullable = false)
    private Date modifyDate;

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public Date getCreateDate() {
        return createDate;
    }

    public void setCreateDate(Date createDate) {
        this.createDate = createDate;
    }

    public Date getModifyDate() {
        return modifyDate;
    }

    public void setModifyDate(Date modifyDate) {
        this.modifyDate = modifyDate;
    }
}

然后,您应该注册实体事件监听器。

public class EntityListener implements PreInsertEventListener, PreUpdateEventListener {

    private static final String CREATE_DATE_PROPERTY = "createDate";

    private static final String MODIFY_DATE_PROPERTY = "modifyDate";

    @Override
    public boolean onPreInsert(PreInsertEvent event) {

        if (event.getEntity() instanceof BaseEntity){
            //property name of entity
            String[] propertyNames = event.getPersister().getEntityMetamodel().getPropertyNames();
            //property value of entity
            Object[] state = event.getState();
            for (int i = 0; i < propertyNames.length ; i ++) {
                if (CREATE_DATE_PROPERTY.equals(propertyNames[i]) || MODIFY_DATE_PROPERTY.equals(propertyNames[i])){
                    state[i] = new Date();
                }
            }
        }

        return false;
    }

    @Override
    public boolean onPreUpdate(PreUpdateEvent event) {

        if (event.getEntity() instanceof BaseEntity){
            //property name of entity
            String[] propertyNames = event.getPersister().getEntityMetamodel().getPropertyNames();
            //property value of entity
            Object[] state = event.getState();
            for (int i = 0; i < propertyNames.length ; i ++) {
                if (MODIFY_DATE_PROPERTY.equals(propertyNames[i])){
                    state[i] = new Date();
                }
            }
        }

        return false;
    }
}

效果很好,我希望它对你有所帮助。