Java 休眠中的 PreInsert 和 PreUpdate 事件侦听器
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/20368551/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
PreInsert and PreUpdate Event Listener in hibernate
提问by Yagnesh Agola
I have used PreInsertEventListener
and PreUpdateEventListener
Event Listener to insert created date and updated date in table.
The problem i am facing is that when i save entity in database created date could not be inserted in table same as with insert updated date at the time of update record it will not insert updated date also.
我已经使用PreInsertEventListener
和PreUpdateEventListener
事件监听器插入创建日期和表更新的日期。
我面临的问题是,当我将实体保存在数据库中时,创建日期无法插入到表中,就像在更新记录时插入更新日期一样,它也不会插入更新日期。
My code sample is show as below :
我的代码示例如下所示:
Listener Class :
监听器类:
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 class :
休眠连接类:
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;
}
}
Entity save and Update method in DAO :
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();
}
}
My Test Class :
我的测试班:
public class Main
{
public static void main(String[] args) {
CityDAO cityDAO = new CityDAO();
long cityId1 = cityDAO.saveCity("New York");
cityDAO.updateCity(cityId1, "Paris");
}
}
If i used session.flush()
than it will insert both date created and updated but updated query is executed every time i call flush method. currently i commented code to call session.flush()
method as show in code.
如果我使用session.flush()
它,它将插入创建和更新的日期,但每次调用刷新方法时都会执行更新的查询。目前我注释了调用session.flush()
方法的代码,如代码所示。
What is the solution to this problem ?
这个问题的解决方案是什么?
采纳答案by Yagnesh Agola
I had created Interceptor extend it with Hibernate EmptyInterceptor.
Override method onSave()
which will be Called when you save an object, the object is not save into database yet and onFlushDirty()
Called when you update an object, the object is not update into database yet.
In this function i have check my method by its name in which i have to set date at the time of created or updated.
Here is sample code of onFlushDirty() method.
我用 Hibernate EmptyInterceptor 创建了 Interceptor 扩展它。
Override 方法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;
}
Here lastUpdatedOn
is my method name which set updated date of record.
这lastUpdatedOn
是我的方法名称,它设置了记录的更新日期。
onSave() method :
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;
}
Here createdOn
is method to set created date for record.
这createdOn
是设置记录创建日期的方法。
Extend your POJO class with this interceptor class.
使用此拦截器类扩展您的 POJO 类。
回答by Prabhakaran Ramaswamy
Do like this
这样做
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;
}
}
回答by Yeager
I recently get same problem when I integrate Spring4 and Hibernate5. This is my BaseEntity class.
我最近在集成 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;
}
}
First of all, you need to define EntityListener class.
首先,您需要定义 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;
}
}
Then, you should register entity event listener.
然后,您应该注册实体事件侦听器。
@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);
}
}
It worked very well, I hope it's helpful for you.
效果很好,希望对你有帮助。