如何将spring的服务bean注入JPA实体?

时间:2010-09-19 20:10:44

标签: hibernate spring jpa dependency-injection

我的问题与此问题非常相似:Injecting fields via Spring into entities loaded by Hibernate

不同之处在于,我使用的是JPA2实体,而不是hibernate。虽然底层仍然处于休眠状态(3.5.5)。

我的春季版本是3.0.4。

JPA世界中相应的eventListeners是什么?

原帖中的示例代码:

class Student {
   int id; //loaded from DB
   String name; //loaded from DB
   int injectedProperty; //Inject via Spring
   transient Service serviceImpl; //Inject via Spring
}

我知道可能有aspectJ的解决方案,但我更喜欢纯java解决方案。 感谢。

1 个答案:

答案 0 :(得分:8)

  

JPA世界中相应的eventListeners是什么?

JPA有实体监听器(和回调方法)。从JPA 2.0规范:

  

3.5实体监听器和回调方法

     

可以将方法指定为a   生命周期回调方法接收   实体生命周期的通知   事件。生命周期回调方法   可以在实体类上定义,a   映射的超类或实体   与一个关联的监听器类   实体或映射的超类。一个实体   listener类是一个类   调用方法以响应   实体上的生命周期事件。任何   实体监听器类的数量可以   为实体类定义或   映射的超类。

     

(...)

     

实体监听器类必须具有   public no-arg constructor。

     

实体监听器是无状态的。该   实体监听器的生命周期是   未指定的。

     

以下规则适用于生命周期   回调:

     
      
  • 生命周期回调方法可能会抛出未经检查/运行时异常。一个   回调抛出的运行时异常   在a中执行的方法   事务导致该事务   标记为回滚。
  •   
  • 生命周期回调可以调用JNDI,JDBC,JMS和企业bean。
  •   
  • 通常,便携式应用程序的生命周期方法不应该   调用EntityManger或Query   操作,访问其他实体   实例,或修改关系   在相同的持久化上下文中。一个   生命周期回调方法可能会修改   非关系状态   调用它的实体。
  •   
     

(...)

     

3.5.1生命周期回调方法

     

实体生命周期回调方法可以   在实体监听器类上定义   和/或直接在实体类或   映射的超类。

     

生命周期回调方法是   用注释指定注释   它们所属的回调事件   调用或映射到回调   使用XML描述符的事件。

     

用于回调的注释   实体类或映射的方法   超类和回调方法   实体监听器类是   相同。个人的签名   但是,方法不同。

     

在实体上定义的回调方法   class或映射的超类都有   签名如下:

void <METHOD>()
     

在实体上定义的回调方法   监听器类有以下内容   签名:

void <METHOD>(Object)
     

Object参数是实体   回调方法的实例   被调用。它可能被宣布为   实际实体类型。

     

回调方法可以具有公共,私有,受保护或包级访问权限,但不能是staticfinal

     

(...)

以下是一个示例(来自规范):

@Entity
@EntityListeners(com.acme.AlertMonitor.class)
    public class Account {
    Long accountId;
    Integer balance;
    boolean preferred;
    @Id
    public Long getAccountId() { ... }
    ...
    public Integer getBalance() { ... }
    ...
    @Transient // because status depends upon non-persistent context
    public boolean isPreferred() { ... }
    ...
    public void deposit(Integer amount) { ... }
    public Integer withdraw(Integer amount) throws NSFException {... }

    @PrePersist
    protected void validateCreate() {
        if (getBalance() < MIN_REQUIRED_BALANCE)
            throw new AccountException("Insufficient balance to open an account");
    }

    @PostLoad
    protected void adjustPreferredStatus() {
        preferred = (getBalance() >= AccountManager.getPreferredStatusLevel());
    }
}

public class AlertMonitor {
    @PostPersist
    public void newAccountAlert(Account acct) {
        Alerts.sendMarketingInfo(acct.getAccountId(), acct.getBalance());
    }
}

在您的情况下,您可能需要PostLoad回调方法。

另请参阅Hibernate Entity Manager文档中的Chapter 6. Entity listeners and Callback methods

但简单来说,你想要做的就是使用JPA并不是那么简单,使用带有@Configurable注释的AspectJ类编织可能是最好的选择。

参考

  • JPA 2.0规范
    • 第3.5节“实体监听器和回调方法”