2011-08-23 14 views
5

Sto migrando un'app dalla configurazione hibernate xml alle annotazioni, non sono sicuro di come adattare la mia classe BusinessObjectInterceptor al nuovo formato basato su annotazioni.Hibernate Interceptor with Annotations

Stiamo cambiando la nostra classe HibernateUtil dalla creazione di SessionFactory

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

a creare EntityManagerFactory

  entityManagerFactory = Persistence.createEntityManagerFactory("primary"); 

Stiamo cambiando la nostra classe HibernateUtil usare sessionFactory.openSession() per la creazione di una sessione da un EntityManager

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

Il problema i s Non so come iniettare BusinessObjectInterceptor in una nuova Hibernate Session, o il modo corretto per annotare le mie classi in modo che possano usare l'Interceptor

Sto provando a impostare l'Interceptor come una proprietà in persistenza. xml. Non sono sicuro se questo è corretto

<?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> 

I nostri corsi sono stati precedentemente configurato tramite file 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> 

le classi annotate assomigliano

@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; 

Abbiamo una classe BusinessObjectInterceptor e una classe BusinessObject. Li posterò sotto per riferimento. Penso che ciò che deve accadere è che la classe BusinessObject deve essere annotata, non sono sicuro di come ciò avvenga poiché BusinessObject non esegue il mapping alle colonne in una tabella specifica, ma piuttosto le colonne che sono comuni a tutte le tabelle nel nostro database. Incollerò queste due classi qui sotto. Sarebbe gradito qualsiasi consiglio su come impostare il mio Interceptor con annotazioni. Grazie.

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

possibile duplicato del [annotazioni Usa primavera per applicare automaticamente Hibernate Interceptor?] (http://stackoverflow.com/questions/2132151/use-spring-annotations-to-automatically-apply-hibernate-interceptor) –

+0

ci potrebbe essere alcune informazioni in questo q la cosa che può aiutarmi, ma non sto usando Spring, quindi non è del tutto applicabile. – user619804

+0

Ok.Non posso ritirare il mio voto ravvicinato, ma se si chiude, voterò per la restituzione. –

risposta

2

In JPA è possibile utilizzare @PrePersist e @PreUpdate annotazione per annotare un metodo nel modello (classe @Entity) che verrà chiamato prima persistente (INSERT) o aggiornamento (UPDATE).

È possibile creare un listener entità, e aggiungere @EntityListeners annotazioni ai modelli, come:

public class BusinessListener { 
    @PrePersist 
    public void businessUpdate(BusinessObject obj) { 
     obj.setCreatedDate(new Date()); 
     .... 
    } 
    @PreUpdate 
    public void businessUpdate(BusinessObject obj) { 
     obj.setChangedDate(new Date()); 
     .... 
    } 
} 

@EntityListeners(class=...BusinessListener) 
public class BusinessObject { 
} 

Oppure si potrebbe mettere i metodi in una classe di entità di base ed estendere tutte le entità da esso, come:

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

Non è esattamente lo stesso. Cioè in 'EmptyInterceptor # onDirtyFlush' puoi passare lo stato dell'entità precedente/corrente. Ma '@ PreUpdate' o' @ EntityListener' potrebbero dirti solo lo stato corrente. Voglio dire che gli intercettori sono ancora più potenti dei loro amici annotati –

Problemi correlati