休眠中的 PreInsert 和 PreUpdate 事件监听器

Yag*_*ola 5 java orm hibernate event-listener

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

我的代码示例如下所示:

听众类别:

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;
    }
}
Run Code Online (Sandbox Code Playgroud)

Hibernate连接类:

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;
    }
}
Run Code Online (Sandbox Code Playgroud)

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();
    }
}
Run Code Online (Sandbox Code Playgroud)

我的测试班:

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

        CityDAO cityDAO = new CityDAO();

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

        cityDAO.updateCity(cityId1, "Paris");
    }
 }
Run Code Online (Sandbox Code Playgroud)

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

这个问题的解决办法是什么?

Yag*_*ola 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;
}  
Run Code Online (Sandbox Code Playgroud)

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;
}
Run Code Online (Sandbox Code Playgroud)

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

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