开发者

Hibernate Interceptors with Annotations

I'm migrating an app from hibernate xml configuration to annotations, I'm not sure how to adapt my BusinessObjectInterceptor class to the new annotations based format.

We are changing our HibernateUtil class from creating SessionFactory

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

to creating EntityManagerFactory

            entityManagerFactory = Persistence.createEntityManagerFactory("primary");

We are changing our HibernateUtil class from using sessionFactory.openSession() to creating a Session from an EntityManager

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

The problem is I'm not sure how to inject a BusinessObjectInterceptor into a new Hibernate Session, or the proper way to annotate my classes so that they can use the Interceptor

I'm trying to set the Interceptor as a property in persistence.xml. I'm not sure if this is correct

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

Our classes were previously configured via hbm.xml files

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

the annotated classes look like

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

We have a BusinessObjectInterceptor class and a BusinessObject class. I will post them below for reference. I think what needs to happen is that BusinessObject class needs to be annotated, I'm not sure how that's done since BusinessObject doesn't map to columns in a specific table, but rather columns that are common to all tables in our database. I'll paste these two classes below. Any advice on how to set up my Interceptor with annotations would be appreciated. Thanks.

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 bu开发者_如何学Csiness 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;
}


In JPA you can use @PrePersist and @PreUpdate annotation to annotate a method in your model (@Entity class) that will be called before persisting (INSERT) or updating (UPDATE).

You can create an entity listener, and add @EntityListeners annotation to your models, like:

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 {
}

Or you could put methods in a base entity class and extend all your entities from it, like:

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

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜