hibernate中的PreInsert和PreUpdate事件监听器
我使用了PreInsertEventListener
和PreInsertEventListener
事件侦听器在表中插入创建日期和更新日期。
我面临的问题是,当我在数据库中保存实体时创建的日期无法插入表中,与更新记录时插入更新日期相同,它也不会插入更新日期。
我的代码示例如下所示:
听众课程:
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()
方法在代码中显示。
这个问题的解决方案是什么?
这样做
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; } }
我创建了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
这里createdOn
是设置记录创建日期的方法。
使用此拦截器类扩展您的POJO类。
我最近在集成Spring4和Hibernate5时遇到了同样的问题。 这是我的BaseEntity类。
@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; } }
首先,您需要定义EntityListener类。
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; } }
然后,您应该注册实体事件侦听器。
@SuppressWarnings("unchecked") @Component public class EntityEventListenerRegistry { @Autowired private SessionFactory sessionFactory; /** * EventListenerRegistry:http://docs.jboss.org/hibernate/orm/5.2/userguide/html_single/Hibernate_User_Guide.html#annotations-jpa-entitylisteners */ @PostConstruct public void registerListeners(){ EventListenerRegistry eventListenerRegistry = ((SessionFactoryImplementor) sessionFactory).getServiceRegistry().getService(EventListenerRegistry.class); eventListenerRegistry.prependListeners(EventType.PRE_INSERT, EntityListener.class); eventListenerRegistry.prependListeners(EventType.PRE_UPDATE, EntityListener.class); } }
它工作得很好,我希望它对你有所帮助。