我有一个类似以下的实体,我使用@Formula
从其他表中填充clientId
。
@Entity
public class Failure {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
public int id;
public String name;
@ManyToOne(cascade = {CascadeType.MERGE, CascadeType.REFRESH} )
public PVPlant pvPlant;
@Formula("(SELECT cl.id from failure f " +
"INNER JOIN pvplant p ON f.pv_plant_id = p.id " +
"INNER JOIN company co ON p.company_id = co.id "+
"INNER JOIN client cl ON co.client_id = cl.id "+
"WHERE f.id = id) ")
public Integer clientId;
}
虽然CrudRepository<Failure,Integer>
JPA方法getByClientId
工作正常但我正在尝试使用Map
和Specification
CriteriaBuilder
的{{1}}密钥进行过滤。 }。
public MySpecifications {
public static Specification<Failure> equalToEachColumn(HashMap<String,Object> map) {
return new Specification<Failure>() {
@Override
public Predicate toPredicate(Root<Failure> root, CriteriaQuery<?> cq, CriteriaBuilder builder) {
return builder.and(root.getModel().getAttributes().stream().map(a ->
{
if (map.containsKey(a.getName())) {
Object val = map.get(a.getName());
return builder.equal(root.<Integer>get(a.getName()), Integer.parseInt(val.toString()));
}
return builder.disjunction();
}
).toArray(Predicate[]::new)
);
}
};
}
}
当我在id
中传递HashMap
时,它工作正常,但当我clientId
时,它不会发回任何内容。有趣的是getAttributes()
实际上返回clientId
但似乎builder.equal(root.<Integer>get(a.getName()), Integer.parseInt(val.toString()))
是假的而不是真的
这就是我使用规范的方式:
failureRepository.findAll(Specifications.where(MySpecifications.equalToEachColumn(map)));
我错过了什么吗?
提前致谢!
答案 0 :(得分:1)
我不希望这会起作用,但是你可以通过使用数据库视图作为@Formula
的替代方法并使用@SecondaryTable
在表和视图中映射实体来使其工作。
//failures_client_vw is a 2 column db view: failure_id, client_id
@Table(name = "failures")
@SecondaryTable(name = "failures_client_vw",
pkJoinColumns = @PrimaryKeyJoinColumn(name = "failure_id"))
@Entity
public class Failure {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
public int id;
public String name;
@ManyToOne(cascade = {CascadeType.MERGE, CascadeType.REFRESH} )
public PVPlant pvPlant;
@Column(name = "client_id", table = "failures_client_vw")
public Integer clientId;
}
然后,您可以像查询任何其他属性一样查询clientId。
https://en.wikibooks.org/wiki/Java_Persistence/Tables#Multiple_tables
答案 1 :(得分:0)
实际问题是我正在使用
builder.disjunction()
and()
中创建0 = 1个错误谓词的。
当我用
替换它时 builder.conjunction()
(创建1 = 1个真实谓词)
在我的代码中它工作正常。因此,@Formula
属性的行为与表格中的属性相同,似乎不需要SecondaryTable
和新的View
。显然在我之前的测试中,我使用的是一个在类中只有id的实体,当我添加clientId
时,它误导我相信@Formula
属性不起作用,而它是分离的来自破坏clientId的id