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

sma*_*ufo 9 spring hibernate dependency-injection jpa

我的问题非常类似于:通过Spring将字段注入Hibernate加载的实体

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

我的春季版是3.0.4.

eventListenersJPA的世界中有什么相应的?

原帖的示例代码:

class Student {
   int id; //loaded from DB
   String name; //loaded from DB
   int injectedProperty; //Inject via Spring
   transient Service serviceImpl; //Inject via Spring
}
Run Code Online (Sandbox Code Playgroud)

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

Pas*_*ent 8

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

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

3.5实体监听器和回调方法

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

(......)

实体侦听器类必须具有公共的无参数构造函数.

实体听众是无国籍的.未指定实体侦听器的生命周期.

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

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

(......)

3.5.1生命周期回调方法

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

生命周期回调方法使用注释进行注释,注释指定调用它们的回调事件或使用XML描述符映射到回调事件.

用于实体类或映射的超类上的回调方法以及实体侦听器类上的回调方法的注释是相同的.然而,各个方法的签名不同.

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

void <METHOD>()
Run Code Online (Sandbox Code Playgroud)

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

void <METHOD>(Object)
Run Code Online (Sandbox Code Playgroud)

该Object参数是被调用回调方法的实体实例.它可以声明为实际的实体类型.

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

(......)

这是一个例子(来自规范):

@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());
    }
}
Run Code Online (Sandbox Code Playgroud)

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

另请参阅Hibernate Entity Manager文档中的第6章实体监听器和回调方法.

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

参考

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

  • @smallufo为了以防万一,还可以看看http://www.jblewitt.com/blog/?p=129.但简单地说,你想做的事情并不容易用JPA做. (2认同)