java - 在 spring data jpa 投影中使用嵌入值对象

标签 java spring-data-jpa

我正在使用 Spring Boot 2.0RC2,在我读到的文档中,您可以在调用存储库时返回实体的投影而不是整个实体。如果我在实体中使用字符串,则效果很好,但当我使用嵌入值对象时,则效果不佳。

假设我有 Product 实体:

@Entity
@Table(name = "t_product")
public class Product extends BaseEntity {

    @Column(nullable = false)
    private String name;

    private Product() {}

    private Product(final String name) {
        this.name = name;
    }

    public static Result<Product> create(@NonNull final String name) {
        return Result.ok(new Product(name));
    }

    public String getName() {
        return name;
    }

    public void setName(@NonNull final String name) {
        this.name = name;
    }
}

BaseEntity 仅保存 idcreatedupdated 属性。

我的投影界面名为 ProductSummary:

interface ProductSummary {
    String getName();
    Long getNameLength();
}

在我的 ProductRepository 中,我有以下方法返回 ProductSummary:

public interface ProductRepository extends JpaRepository<Product, Long> {
    @Query(value = "SELECT p.name as name, LENGTH(p.name) as nameLength FROM Product p WHERE p.id = :id")
    ProductSummary findSummaryById(@Param("id") Long id);
}

这工作得很好。现在,假设我正在执行 DDD,而不是使用字符串来表示 Product 实体中的 name 属性,我想使用名为 Name< 的值对象:

@Embeddable
public class Name implements Serializable {

    public static final int MAX_NAME_LENGTH = 100;

    @Column(nullable = false, length = Name.MAX_NAME_LENGTH)
    private String value;

    private Name() {}

    private Name(final String value) {
        this.value = value;
    }

    public static Result<Name> create(@NonNull final String name) {
        if (name.isEmpty()) {
            return Result.fail("Name cannot be empty");
        }

        if (name.length() > MAX_NAME_LENGTH) {
            return Result.fail("Name cannot be longer than " + MAX_NAME_LENGTH + " characters");
        }

        return Result.ok(new Name(name));
    }

    public String getValue() {
        return value;
    }
}

我将我的 Product 实体更改为:

@Entity
@Table(name = "t_product")
public class Product extends BaseEntity {

    @Embedded
    private Name name;

    private Product() {}

    private Product(final Name name) {
        this.name = name;
    }

    public static Result<Product> create(@NonNull final Name name) {
        return Result.ok(new Product(name));
    }

    public Name getName() {
        return name;
    }

    public void setName(final Name name) {
        this.name = name;
    }
}

ProductSummary 中,我将返回类型从 String 更改为 Name

当我运行时,我总是遇到异常:

Caused by: java.lang.IllegalAccessError: tried to access class com.acme.core.product.ProductSummary from class com.sun.proxy.$Proxy112

我可以完成这项工作吗?还是我缺少一些不允许这样做的限制?

最佳答案

如果您希望获取完整的Name字段(而不是Name类中的特定字段),那么您需要创建另一个接口(interface),例如ProductSummary。

interface ProductSummary {
    NameSummary getName();

    interface NameSummary {
      String getValue();
    }
}

无需更改存储库中的任何内容。

记录得很清楚here

并确保您的接口(interface)和方法是公共(public)的。

关于java - 在 spring data jpa 投影中使用嵌入值对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49010287/

相关文章:

java - 服务器重置新连接,但 cpu/网络负载较低

java - 如何防止 Spring JPA 实体在保存到 CRUDRepository 时变为可选?

java - 如何在 Spring Boot 中更新子实体和父实体?

mysql - 如何使用 JPA 注释将 DateTime(3) 表示为数据库中 MySQL 列中的数据类型

hibernate - 如何在Spring Data的findAll()方法中过滤软删除项?

java - 如何创建搜索嵌入值的存储库方法?

Java 正则表达式字符串 : Check if ip:port string contains a valid IPv4 or DNS address

java - FacesMessages 和 rich :effect?

java - 将带有 `sort` 的 Java `? super T` 签名转换为 Scala(泛型)

java - 为什么 JSoup 中可能缺少某些方法?