Spring 表达式语言 (SpEL) 不适用于 JPA/hibernate 实体

标签 spring hibernate jpa spring-data-jpa spring-el

我正在尝试使用 SpEL 模板从实体生成文件名。
我有两个与这些类似的实体:

@Entity
public class Invoice implements Serializable {
    private String invoicenumber;
    private Customer customer;

    @Column(name = "invoicenumber", nullable = false, length = 20)
    public String getInvoicenumber() {
        return this.invoicenumber;
    }

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "fk_customer", nullable = false)
    public Customer getCustomer() {
        return this.customer;
    }
}

@Entity
public class Customer implements Serializable {
    private String firstname;
    private String lastname;

    @Column(name = "firstname", nullable = false, length = 20)
    public String getFirstname() {
        return this.firstname;
    }

    @Column(name = "lastname", nullable = false, length = 20)
    public String getLastname() {
        return this.lastname;
    }
}

和一个类似于这个的 SpEL 模板:
String template = "invoicenumber + '-' + customer.firstname + ' ' + customer.lastname";

然后我使用 SpEL 从带有发票对象的模板生成文件名
public String generateFilename(String filenameTemplate, Object dataObject) {
    ExpressionParser parser = new SpelExpressionParser();
    Expression expression = parser.parseExpression(filenameTemplate);
    return expression.getValue(dataObject, String.class);
}

此测试有效:
String testTemplate = "invoicenumber + '-' + customer.firstname + ' ' + customer.lastname";
Invoice invoice = new Invoice();
invoice.setInvoicenumber("BF2016-06-ABCDEF");
invoice.setCustomer(new Customer());
invoice.getCustomer().setFirstname("Hans");
invoice.getCustomer().setLastname("Hansen");
assertEquals("BF2016-06-ABCDEF-Hans Hansen", generator.generateFilename(testTemplate, invoice));

此测试不会:
Invoice invoice = invoiceRepository.findOne(4);

String template = "invoicenumber + '-' + customer.firstname + ' ' + customer.lastname";
String filename = filenameGenerator.generateFilename(template, invoice);
assertEquals("12344-201601-Heinrich Jahnke", filename);

这个测试实际上导致“12344-201601-”,这让我假设,用于延迟加载客户对象的 hibernate 代理是问题所在。 firstname 和 lastname 字段在从数据库加载之前为空,这将解释呈现的文件名。

有想法该怎么解决这个吗?我已经尝试过的一些事情:
Hibernate.initialize(invoice);
Hibernate.initialize(invoice.getCustomer());
System.out.println(invoice.getCustomer().getFirstname());
  • 在表达式
  • 中使用“customer.getFirstname()”而不是“customer.firstname”
  • 将@Transactional 添加到我的 FilenameGenerator 类
  • 最佳答案

    问题出在其他地方,SpEL 和 JPA/Hibernate 一起工作得很好。对不起!

    我的实际表情是这样的:

    "invoicenumber + '-' + (customer.company == null ? customer.fname + ' ' + customer.sname : customer.company)"
    

    可悲的是,从数据库加载的客户确实有一家公司,一家空公司......
    使用以下表达式,一切正常:
    "invoicenumber + '-' + (customer.company == null or customer.company.isEmpty() ? customer.fname + ' ' + customer.sname : customer.company)"
    

    关于Spring 表达式语言 (SpEL) 不适用于 JPA/hibernate 实体,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38146622/

    相关文章:

    hibernate - 在 Grails 中使用 Firebird 数据库的步骤

    java - jpa 中使用 fetch 关系对查询进行计数

    mysql - 从与父表具有外键约束的子表中删除记录的成本是多少

    java - spring restdocs 能否像 swagger 一样生成实时文档?

    java - 将变量传递给@Value注释以从属性文件中读取特定属性

    Hibernate - 如何使关联渴望(全局)?

    java - 在 JPA @OneToMany 关系中更新 Set 元素的正确方法?

    spring - JPA @Entity 中的 Bean 注入(inject)

    java - Spring boot + Spring security with AspectJ 不工作

    spring - 覆盖 SpringMVC 应用程序中的默认重定向 URL