![](/img/trans.png)
[英]Hibernate Envers how to get revision by property of EmbeddedId
[英]How to use Hibernate's @Filter annotation in an @EmbeddedId property
無法使用嵌入的 id 屬性使 Hibernate 過濾器工作。
在此處重現問題的示例項目
我在這個查詢上掙扎了很長一段時間。
假設以下實體映射示例:
@Entity
class Client {
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "client_id")
@Basic(optional = false)
private Integer id;
@Basic(optional = false)
private String name;
@OneToMany(mappedBy = "client")
private List<CarRent> rentHistory;
// ... getters and setters
}
@Entity
class Car {
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "car_id")
@Basic(optional = false)
private Integer id;
@Basic(optional = false)
private String foo;
// ... getters and setters
}
@Entity
class CarRent {
@EmbeddedId
private CarRentKey carRentKey;
@MapsId("clientId")
@ManyToOne()
@JoinColumn(name = "client_id", nullable = false, insertable = false, updatable = false)
private Client client;
@MapsId("carId")
@ManyToOne()
@JoinColumn(name = "car_id", nullable = false, insertable = false, updatable = false)
private Car car;
@Basic(optional = false)
private String bar;
// ... getters and setters
}
@Embeddable
class CarRentKey {
private int clientId;
private int carId;
@Column(name = "date_due")
private Date dateDue;
// ... getters and setters
}
我需要從某個日期獲取所有使用 CarRents 填充的rentHistory 的客戶。 以下查詢對我來說非常適合:
from Client cl
left outer join fetch c.rentHistory as rent with rent.car = c and rent.dateDue = :date
但是 Hibernate 一直告訴我在獲取異常中的連接時使用過濾器。
我試過了
@Entity
@FilterDef(name="dateDueFilter", parameters= {
@ParamDef( name="dateDue", type="date" ),
})
@Filters( {
@Filter(name="dateDueFilter", condition="dateDue = :dateDue"),
})
class CarRent {
// ...
}
但是當我運行我的查詢時:
EntityManager em;
// ...
Session hibernateSession = em.unwrap(Session.class);
hibernateSession.enableFilter("dateDueFilter").setParameter("dateDue", dateDue);
em.createQuery("from Client cl"
+ "left outer join fetch c.rentHistory");
List<Client> clientList = q.getResultList();
// clientList contains CarRent of all dates
過濾器被忽略。 與condition="carRentKey.dateDue = :dateDue"
和condition="date_due = :dateDue"
。
我對同一個查詢的其他左外連接使用過濾器,它們工作得很好。 但是這種演化嵌入參數的關系我找不到讓它起作用的方法。
是否可以? 有替代品嗎?
PS:在 where 部分過濾,例如from Client cl left outer join fetch c.rentHistory as rent where rent.dateDue is null or rent.dateDue = :date
不是一個選項,因為我的真實查詢有其他連接,結果被過濾並得到當我這樣做時真的很慢。
我不知道,如果我理解正確,但是:
em.createQuery("from Client cl"
+ "left outer join fetch c.rentHistory");
不使用應該被過濾的@Embeddable
。
編輯:
您需要使用您設置的Session
。 用它打開交易並查詢結果:
hibernateSession.openTransaction();
results = hibernateSession.createQuery(...).list();
hibernateSession.close();
原來我在這種情況下濫用了@Filter 注釋。
Vlad Mihalcea 幫助我解決了我在 Hibernate 論壇上的帖子中的問題
根據他的方向,我設法使用沒有獲取和結果轉換器的連接查詢解決了沒有過濾器的問題。
該示例的解決方案是:
org.hibernate.query.Query<Client> q = em.createQuery("select cl, cr " +
"from Client cl " +
"join CarRent cr on cr.client = cl and cr.carRentKey.dateDue = :date")
.setParameter("date", exampleDate)
.unwrap(org.hibernate.query.Query.class).setResultTransformer(new BasicTransformerAdapter() {
@Override
public List transformList(List list) {
Map<Serializable, Client> clientMap =
new LinkedHashMap<>(list.size());
for (Object entityArray: list) {
if (Object[].class.isAssignableFrom(entityArray.getClass())) {
Client client = null;
CarRent carRent = null;
Object[] tuples = (Object[]) entityArray;
for (Object tuple : tuples) {
em.detach(tuple);
if (tuple instanceof Client) {
client = (Client) tuple;
}
else if (tuple instanceof CarRent) {
carRent = (CarRent) tuple;
}
else {
throw new UnsupportedOperationException(
"Tuple " + tuple.getClass() + " is not supported!"
);
}
}
if (client != null) {
if (!clientMap.containsKey(client.getId())) {
clientMap.put(client.getId(), client);
client.setRentHistory(new ArrayList<>());;
}
if (carRent != null) {
client.getRentHistory().add(carRent);
}
}
}
}
return new ArrayList<>(clientMap.values());
}
});
List<Client> clientList = q.getResultList();
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.