2011-08-23 130 views
5

我正在將應用程序從hibernate xml配置遷移到註釋,我不知道如何使我的BusinessObjectInterceptor類適應新的基於註釋的格式。帶註釋的Hibernate攔截器

我們從創建SessionFactory的

  InitialContext ctx  = new InitialContext(); 
     sessionFactory = (SessionFactory)ctx.lookup("java:/hibernate/SessionFactory"); 

改變我們的HibernateUtil類創建EntityManagerFactory的

  entityManagerFactory = Persistence.createEntityManagerFactory("primary"); 

我們使用sessionFactory.openSession()改變我們的HibernateUtil類從一個EntityManager創建會話

  //s = sessionFactory.openSession(new BusinessObjectInterceptor()); 
     EntityManager entityManager = entityManagerFactory.createEntityManager(); 
     s = entityManager.unwrap(Session.class); 

問題我我不知道如何注入一個BusinessObjectInterceptor到一個新的休眠會話,或正確的方式來註釋我的類,以便他們可以使用攔截器我試圖將攔截器設置爲持久性屬性。 XML。我不知道這是否是正確的

<?xml version="1.0" encoding="UTF-8"?> 
<persistence version="2.0" 
xmlns="http://java.sun.com/xml/ns/persistence" 

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
xsi:schemaLocation=" 
    http://java.sun.com/xml/ns/persistence 
    http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd"> 
    <persistence-unit name="primary"><jta-data-source>java:jboss/datasources/MySqlDS</jta-data-source> 

    <properties> 
    <property name="hibernate.dialect" value="org.hibernate.dialect.MySQLDialect"/> 
    <property name="hibernate.ejb.interceptor.session_scoped" value="com.mycompany.common.persistence.BusinessObjectInterceptor"/> 
      </properties> 

我們的課程通過hbm.xml文件中被預先配置

<?xml version="1.0"?> 
<!DOCTYPE hibernate-mapping PUBLIC 
    "-//Hibernate/Hibernate Mapping DTD 3.0//EN" 
    "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> 

<hibernate-mapping> 
    <class name="com.mycompany.liveexpert.common.businessobjects.ServerSettings" table="server_settings"> 
      <id name="serverSettingsID" type="integer" column="server_settings_id"> 
        <generator class="identity" /> 
      </id> 
      <version name="updateCounter" column="update_counter"/> 
      <property name="changedDate" type="timestamp" column="changed_date"/> 
      <property name="changedBy" type="string" column="changed_by"/> 
      <property name="createdDate" type="timestamp" column="created_date"/> 
      <property name="createdBy" type="string" column="created_by"/> 
      <property name="status" type="string" column="status"/> 

      <property name="emailServer" type="string" column="email_server" /> 
      <property name="emailFromAddress" type="string" column="email_from_address" /> 
      <property name="emailUser" type="string" column="email_user" /> 
      <property name="emailPassword" type="string" column="email_password" /> 

</class> 

類中的註解樣子

@Entity 
@Table(name="server_settings") 
public class ServerSettings extends BusinessObject 
{ 
    @Id @GeneratedValue(strategy=GenerationType.IDENTITY) 
    private Integer serverSettingsID; 
    @Column(name = "email_server") 
    private String emailServer; 
    @Column(name = "email_from_address") 
private String emailFromAddress; 
    @Column(name = "email_user") 
private String emailUser; 
    @Column(name = "email_password") 
private String emailPassword; 

我們有一個BusinessObjectInterceptor類和一個BusinessObject類。我會在下面發表以供參考。我認爲需要發生的是BusinessObject類需要註釋,我不確定這是如何完成的,因爲BusinessObject沒有映射到特定表中的列,而是我們數據庫中所有表共用的列。我將在下面粘貼這兩個類。任何意見,如何設置我的攔截器與註釋將不勝感激。謝謝。

BusinessObjectInterceptor

public class BusinessObjectInterceptor extends EmptyInterceptor 
{ 
private int updates; 
private int creates; 

private static final String defaultDesignation = "system"; 

private String getUserDesignation() 
{ 
    UserContextI theContext = PersistenceContext.getUserContext(); 
    if (theContext == null) return defaultDesignation; 
    String uid = theContext.getUserDesignation(); 
    if (uid == null) return defaultDesignation; 
    return uid; 
} 
public boolean onFlushDirty(Object entity, 
          Serializable id, 
          Object[] currentState, 
          Object[] previousState, 
          String[] propertyNames, 
          Type[] types) 
{ 
    boolean theReturn = false; 
    if (entity instanceof BusinessObject) 
    { 
     updates++; 
     for (int i=0; i<propertyNames.length; i++) 
     { 
      if ("changedDate".equals(propertyNames[i])) 
      { 
       currentState[i] = new Date(); 
       theReturn = true; 
      } 
      if ("changedBy".equals(propertyNames[i])) 
      { 
       currentState[i] = getUserDesignation(); 
       theReturn = true; 
      } 
     } 
    } 
    return theReturn; 
} 
public boolean onSave(Object entity, 
     Serializable id, 
     Object[] state, 
     String[] propertyNames, 
     Type[] types) 
{ 
    boolean theReturn = false; 
    if (entity instanceof BusinessObject) 
    { 
     creates++; 
     for (int i=0; i<propertyNames.length; i++) 
     { 
      if ("createdDate".equals(propertyNames[i])) 
      { 
       state[i] = new Date(); 
       theReturn = true; 
      } 
      if ("createdBy".equals(propertyNames[i])) 
      { 
       state[i] = getUserDesignation(); 
       theReturn = true; 
      } 
      if ("changedDate".equals(propertyNames[i])) 
      { 
       state[i] = new Date(); 
       theReturn = true; 
      } 
      if ("changedBy".equals(propertyNames[i])) 
      { 
       state[i] = getUserDesignation(); 
       theReturn = true; 
      } 
     } 
    } 
    return theReturn; 
} 
public void preFlush(Iterator entities) 
{ 
    updates = 0; 
    creates = 0; 
} 

BusinessObject的

public abstract class BusinessObject 
{ 
private String status; 
private String createdBy; 
private Date createdDate; 
private String changedBy; 
private Date changedDate; 
private int updateCounter; 

/** 
* Generic save method to be used for persisting a business object. 
* 
* @return a copy of this business object in its saved state. 
* 
* @throws Exception 
*/ 
public BusinessObject save() throws Exception 
{ 
    Session  hsession = null; 
    Transaction tx = null; 
    BusinessObject theObject = null; 

    validate(); // throws ValidationException 

    try { 
     hsession = HibernateUtil.currentSession(); 
     tx = hsession.beginTransaction(); 

     if (getStatus() == null || getStatus().length() < 1) 
     { 
      setStatus("OK"); 
     } 

     //theObject = (BusinessObject) hsession.saveOrUpdateCopy(this); 
     theObject = (BusinessObject) hsession.merge(this); 
     if (tx != null && tx.isActive() && !tx.wasCommitted()) 
      tx.commit(); 
    } catch (Exception e){ 
     try 
     { 
     if (tx!=null) tx.rollback(); 
     } catch (Exception e3) 
     {} 
     try 
     { 
     hsession.close(); 
     } catch (Exception e2) 
     {} 
     throw e; 
    } finally 
    { 
     HibernateUtil.closeSession(); 
    } 
    return theObject; 
} 
+0

可能重複[使用Spring註解自動應用Hibernate的攔截器?(http://stackoverflow.com/questions/2132151/use-spring-annotations-to-automatically-apply-hibernate-interceptor) –

+0

有可能在那個問題上是一些信息可以幫助我的問題,但我不使用Spring,因此它不完全適用。 – user619804

+0

好的。我無法收回我的近距離投票,但如果它關閉,我會投票repoen。 –

回答

2

在JPA可以使用@PrePersist@PreUpdate註釋在模型(@Entity類),將堅持之前被調用來註釋的方法(INSERT)或更新(UPDATE)。

您可以創建一個實體監聽器,並添加@EntityListeners註釋到你的模型,如:

​​

或者你可以把方法的基礎實體類和所有的實體從其擴展,如:

public class BusinessObject { 
    @PrePersist 
    public void businessUpdate() { 
     createdDate = new Date(); 
     .... 
    } 
    @PreUpdate 
    public void businessUpdate() { 
     changedDate = new Date(); 
     .... 
    } 
} 
+1

這不完全相同。即到'EmptyInterceptor#onDirtyFlush'你可以傳遞前一個/當前的實體狀態。但'@ PreUpdate'或'@ EntityListener'只能告訴你當前的狀態。我的意思是攔截者仍然比他們註釋的朋友強大 –