我正在使用Spring Boot 2.0RC2,在我阅读的文档中,您可以在调用存储库时返回实体的投影,而不是整个实体的投影。如果我在我的实体中使用String但在使用嵌入值对象时不能使用,这样可以正常工作。
我们说我有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
只保留id
,created
和updated
属性。
我的投影界面名为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而不是使用String来表示name
实体中的Product
属性,我想使用一个名为Name
的值对象:< / p>
@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
我可以完成这项工作,还是我错过了一些不允许这样做的限制?
答案 0 :(得分:1)
如果您希望获得完整的Name字段(而不是Name类中的特定字段),那么您需要创建另一个类似ProductSummary的接口。
interface ProductSummary {
NameSummary getName();
interface NameSummary {
String getValue();
}
}
无需更改存储库中的任何内容。
非常清楚地记录here
并确保您的界面和方法是公开的。