【问题标题】:Hibernate Interceptors with Annotations带有注解的 Hibernate 拦截器
【发布时间】:2011-08-23 23:09:49
【问题描述】:

我正在将应用程序从 hibernate xml 配置迁移到注释,我不确定如何使我的 BusinessObjectInterceptor 类适应新的基于注释的格式。

我们正在从创建 SessionFactory 更改 HibernateUtil 类

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

创建EntityManagerFactory

            entityManagerFactory = Persistence.createEntityManagerFactory("primary");

我们正在将 HibernateUtil 类从使用 sessionFactory.openSession() 更改为从 EntityManager 创建会话

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

问题是我不确定如何将 BusinessObjectInterceptor 注入到新的 Hibernate Session 中,或者不知道如何正确注释我的类以便它们可以使用 Interceptor

我正在尝试将拦截器设置为 persistence.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 不会映射到特定表中的列,而是映射到数据库中所有表共有的列。我将在下面粘贴这两个类。任何有关如何使用注释设置我的拦截器的建议将不胜感激。谢谢。

业务对象拦截器

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

业务对象

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

【问题讨论】:

标签: java hibernate


【解决方案1】:

在 JPA 中,您可以使用 @PrePersist@PreUpdate 注释来注释模型(@Entity 类)中将在持久化(INSERT)或更新(UPDATE)之前调用的方法。

您可以创建一个实体侦听器,并将@EntityListeners 注释添加到您的模型中,例如:

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

或者您可以将方法放在基实体类中并从中扩展您的所有实体,例如:

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

【讨论】:

  • 这不完全一样。 IE。进入EmptyInterceptor#onDirtyFlush,您可以传递先前/当前实体状态。但@PreUpdate@EntityListener 只能告诉你当前状态。我的意思是拦截器仍然比带注释的朋友更强大
  • 使用拦截器可以保持以前和当前的状态,这是休眠事件系统无法实现的
猜你喜欢
  • 1970-01-01
  • 2011-07-03
  • 1970-01-01
  • 1970-01-01
  • 2012-09-26
  • 1970-01-01
  • 2023-03-31
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多