Max*_*Max 6 hibernate jpa one-to-one composite-key one-to-many
我正在使用 JPA 为具有复合键的数据库定义数据模型。我无法更改数据库。
我有一个Car带有复合键(carType 和 carId)的实体。第二个(可选)PorscheInfo实体包含保时捷汽车的附加信息。不幸的是,相应的“porsche_info”表不包含包含 carType 信息的列,因为其条目专门引用CarType = 'Porsche'。
此操作的 SQL 很简单:
SELECT *
FROM cars
LEFT JOIN porsche_info
ON cars.CarId = porsche_info.CarId
AND cars.CarType = 'Porsche'
Run Code Online (Sandbox Code Playgroud)
如何将其转换为正确的 JPA 设置?
到目前为止,我有以下实体类:
@Embeddable
public class CarKey {
private String carType;
private String carId;
}
@Entity(name = "cars")
public class Car {
@EmbeddedId
private CarKey key;
// car information
@OneToOne
@JoinColumn(name = "CarId", referencedColumnName = "CarId")
private PorscheInfo porscheInfo;
// or
@OneToMany
@JoinColumn(name = "CarId", referencedColumnName = "CarId")
private Set<PorscheInfo> porscheInfo;
}
@Embeddable
public class PorscheInfoKey {
private String carId;
}
@Entity (name = "porsche_info")
public class PorscheInfo {
@EmbeddedId
private PorscheInfoKey key;
// porsche info
}
Run Code Online (Sandbox Code Playgroud)
一个@OneToOne解决方案是首选,但一个@OneToMany解决方案(由于不同的关键类)也是可行的。
CriteriaQuery 看起来像:
CriteriaBuilder cb = entityManager.getCriteriaBuilder();
CriteriaQuery<Car> carQuery = cb.createQuery(Car.class).distinct(true);
Root<Car> carRoot = carQuery.from(Car.class);
carQuery.select(carRoot);
carRoot.fetch("porscheInfo", JoinType.LEFT);
Run Code Online (Sandbox Code Playgroud)
@OneToOne方法中,我得到: org.hibernate.MappingException: Repeated column in mapping for entity: Car column: CarId (should be mapping with insert="false" update="false")@OneToMany方法中,我得到: org.hibernate.AnnotationException: referencedColumnNames(CarId) of PorscheInfo.porscheInfo 引用 Car 未映射到单个属性正确的 JPA 设置应该是什么样的?我不知道如何告诉 Hibernate 必须加入哪些列。我想过.multiselect()或Join<Car, PorscheInfo> ... .on()接近,但没有让它起作用。
编辑:
我得到了@OneToOne一个警告的方法:
@OneToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "CarId", referencedColumnName = "CarId", insertable = false, updatable = false)
private PorscheInfo porscheInfo;
Run Code Online (Sandbox Code Playgroud)
奇怪的行为是:porscheInfo由于carRoot.fetch("porscheInfo", JoinType.LEFT);. 但是,当我尝试访问它们的porscheInfo属性时,所有非保时捷汽车都会抛出 LazyInitializationException 。Eager fetching 是不可取的,因为它会导致对每辆车进行额外的不必要的查询(1+N 次查询)。
| 归档时间: |
|
| 查看次数: |
746 次 |
| 最近记录: |