java - 实体中的 Spring roo 服务 Autowiring 始终为空(使用带有 @RooJpaEntity 的 JPA 存储库)

标签 java spring jpa spring-roo autowired

我一直在寻找一种在保存实体时从服务调用某些方法的方法。

我的应用程序是使用 roo 1.2.4.RELEASE 创建的

我有一个名为 SaldoCliente 的 Balance 实体和一个名为 AuxCliente 的 ClientAction 实体。

每次持久保存新的 ClientAction 实体时,我都需要更新客户端余额。

这是我的代码:

@RooJavaBean
@RooToString
@RooJpaEntity(entityName = "AUX_CLIENTES")
public class AuxCliente {


    @Transient
    @Autowired
    static private SaldoClienteService saldoClienteService;


...


    @PostConstruct
    public void init() 
    {
        System.out.println("Initializing with dependency ["+ saldoClienteService + "]");
    }

    @PostPersist
    private void afectaSaldoCliente(/*Long idTrans, Cliente, Integer cargo, BigDecimal importe, Integer creditos*/) {
      if (saldoClienteService == null) {
          System.out.println("saldoClienteService FUE NULL");
      }
...

我不知道为什么 saldoClienteService 总是为 null。

(注意,我不希望 saldoClienteService 字段保存在我的数据库中,因此需要 @Transient 注释)

我一直在寻找解决方案,但没有成功。许多解释都是这样的:this其中说:You need <context:annotation-config/> (or <context:component-scan/>) to enable @PostConstruct handling.

我确实有<context:component-scan>在我的 applicationContext.xml (由 Roo 创建)中。

文档说:

By default, the Spring-provided @Component, @Repository, @Service, and @Controller stereotypes will be detected. Note: This tag implies the effects of the 'annotation-config' tag, activating @Required, @Autowired, @PostConstruct, @PreDestroy, @Resource, @PersistenceContext and @PersistenceUnit annotations in the component classes, which is usually desired for autodetected components (without external configuration).

至少是@Autowired注释在任何地方都有效,但在那里。

有人指点一下吗?

-----------------已编辑-----------------

首先:我要感谢@Sotirios 和@Ralph 花时间帮助我。

如果我从字段中删除“static”,结果是一样的。在我的实体中注入(inject)的字段始终为空。 (请参阅我在这个问题中的评论,我添加这一点是因为有一个“可能”的解决方案)。

我在需要注入(inject)的另一个类上也遇到了麻烦。我将其添加到与之前相同的类中(AuxClientes):

@Transient
@Autowired
private ConfigUser configUser;

并且 configUser 也始终为 null。

这是另一个类的开始,以防万一。

@RooJavaBean(settersByDefault=false)
public class ConfigUser {
...

当然,在 applicationContext.xml 中:

<bean class="com.i4b.adminctes.util.ConfigUser" id="appConfigUser" />

我在构造函数、服务和存储库中成功使用了 configUser。但不能在实体中使用它。

如果您认为我应该发布代码的任何其他部分,请告诉我。

--------------- 编辑 2 ------------------

我的所有实体都会发生同样的情况。

---------------编辑3.a ------------------

为了更好的问题,我更改了问题标题。之前:

Spring roo (service autowiring) Entity not calling @PostConstruct . (Using JPA Repository with @RooJpaEntity)

---------------编辑3.b ------------------

我刚刚创建了一个最小的测试项目。

// Spring Roo 1.2.4.RELEASE [rev 75337cf] log opened at 2013-11-13 11:36:27
project --topLevelPackage org.example --projectName TestAutowiredOnEntities --java 7 --packaging WAR
jpa setup --provider HIBERNATE --database HYPERSONIC_IN_MEMORY 
entity jpa --class ~.domain.MyEntity --testAutomatically --activeRecord false
field string --fieldName text 
repository jpa --interface ~.repository.MyEntityRepository --entity ~.domain.MyEntity
service type --interface ~.service.MyEntityService --entity ~.domain.MyEntity
web mvc setup 
web mvc all --package org.example.web

编辑服务:

package org.example.service;

public class MyEntityServiceImpl implements MyEntityService {

    @Override
    public String testAutowire() {
        return "Some data";
    }
}

编辑实体:

package org.example.domain;
import javax.persistence.PrePersist;
import javax.persistence.Transient;

import org.example.service.MyEntityService;
import org.example.service.MyEntityServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.roo.addon.javabean.RooJavaBean;
import org.springframework.roo.addon.jpa.entity.RooJpaEntity;
import org.springframework.roo.addon.tostring.RooToString;

@RooJavaBean
@RooToString
@RooJpaEntity
public class MyEntity {

    @Transient
    @Autowired
    MyEntityService myEntityService; 

    /**
     */
    private String text;

    @PrePersist
    public void prePersist() {
        if (myEntityService == null) {
            System.out.println("myEntityService IS NULL");
        } else {
            String data=myEntityService.testAutowire();
            System.out.println("it works: " + data);
            this.text = data;
        }
    } 
}

并编辑create.jspx以隐藏服务字段。否则它不会让你保存。

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<div xmlns:c="http://java.sun.com/jsp/jstl/core" xmlns:field="urn:jsptagdir:/WEB-INF/tags/form/fields" xmlns:form="urn:jsptagdir:/WEB-INF/tags/form" xmlns:jsp="http://java.sun.com/JSP/Page" xmlns:spring="http://www.springframework.org/tags" version="2.0">
    <jsp:directive.page contentType="text/html;charset=UTF-8"/>
    <jsp:output omit-xml-declaration="yes"/>
    <form:create id="fc_org_example_domain_MyEntity" modelAttribute="myEntity" path="/myentitys" render="${empty dependencies}" z="T0LoTr6PZAwfIQHkjOZMmPW7cO8=">
        <field:input field="myEntityService" id="c_org_example_domain_MyEntity_myEntityService" render="false" z="12sHnsW2dWYyuD+vDtbTve/jWuI="/>
        <field:input field="text" id="c_org_example_domain_MyEntity_text" z="jUCTnP7E3pYPcZcfGn1tyJ2VeFI="/>
    </form:create>
    <form:dependency dependencies="${dependencies}" id="d_org_example_domain_MyEntity" render="${not empty dependencies}" z="Un0bJ/PmWmczxoVTom9NowwIRWk="/>
</div>

然后执行应用程序并创建一个新的“我的实体”。将字段留空,我按下保存按钮。

日志显示:

INFO: Reloading Context with name [/testAutowiredOnEntities] is completed
nov 13, 2013 2:31:52 PM org.apache.jasper.compiler.TldLocationsCache tldScanJar
INFO: At least one JAR was scanned for TLDs yet contained no TLDs. Enable debug logging for this logger for a complete list of JARs that were scanned but no TLDs were found in them. Skipping unneeded JARs during scanning can improve startup time and JSP compilation time.
myEntityService IS NULL

实体有一个空文本字段。

为了确定,我将 @Component 添加到“MyEntity”类中:

...
@Component
@RooJavaBean
@RooToString
@RooJpaEntity
public class MyEntity {
...

什么都没有改变。该服务仍然为空。

我真的希望它能帮助比我更有知识的人帮助我找到解决方案。

谢谢大家。

同时,我将重新阅读 @Ralph 指出的文档部分。 我显然做错了什么。我不相信我是唯一需要这个的人。

再次感谢大家

最佳答案

Spring 不会注入(inject)静态字段。

@RooJavaBean
@RooToString
@RooJpaEntity(entityName = "AUX_CLIENTES")
public class AuxCliente {


    @Transient
    @Autowired
    private SaldoClienteService saldoClienteService;

    @PostPersist
    void afectaSaldoCliente() {
       this.saldoClienteService.doWhatYouWant();
    }

}
<小时/>

关于更新#2

看起来 ConfigUser 是一个 Hibernate/JPA/Whatever Entity,但不是 Spring Bean。但是你只能注入(inject)Spring Beans(比如Services、Dao等)(每一个有@Component@Controller@Service的东西>, @Repository 注释*。))

并且您只能注入(inject)带有 @Configurable 注解的 Spring Bean 或类(需要 AspectJ)See Spring Reference Chapter 7.8.1 Using AspectJ to dependency inject domain objects with Spring

使用@Configurable是Spring-Roo的做法(实体旁边必须有一个文件AuxCliente_Roo_Configurable.aj(在Eclipse中需要禁用“隐藏生成 Spring Roo ITD”-过滤器以在包资源管理器中显示此文件))。

<小时/>

* 还有一些方法可以使对象成为 spring bean,但这在这里并不重要

关于java - 实体中的 Spring roo 服务 Autowiring 始终为空(使用带有 @RooJpaEntity 的 JPA 存储库),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19913369/

相关文章:

java - 获取链表中以特定字符开头的所有元素

java - 返回 void 与返回 CompletionStage<Void> 之间有什么区别吗?

java - 如何使用 Hibernate 处理最大数据库连接数?

java - 将元数据添加到 java throwable 对象

javascript - 尝试将提交按钮的状态从禁用更改为启用

spring - 消息包键中的空格

java - jpa 2.1 和新的 Date APi : YearMonth to Date Converter, MySQL 异常

java - 批量处理10条记录java,JPA

java - 唯一查询没有匹配结果(错误 782)

来自匿名方法的java引用 "this"