我想使用Hibernate注释来表示使用连接的单向一对多关系。我想在连接上添加一个条件,因此只有在 source 表中的列(" one")等于常量值时才会发生这种情况。例如。
SELECT *
FROM buildings b
LEFT JOIN building_floors bf on bf.building_id = b.id AND b.type = 'OFFICE'
我想代表该查询的b.type = 'OFFICE'
部分。
我的问题与此问题非常相似,只是我在源表上有条件。 JPA/Hibernate Join On Constant Value
Java实体如下所示:
@Entity
@Table(name = "buildings")
public class Building {
@Id
@Column(name = "id")
private int id;
@Column(name = "type")
private String type;
@OneToMany(mappedBy = "buildingId",
fetch = FetchType.EAGER,
cascade = {CascadeType.ALL},
orphanRemoval = true)
@Fetch(FetchMode.JOIN)
// buildings.type = 'OFFICE' ????
private Set<BuildingFloors> buildingFloors;
// getters/setters
}
@Entity
@Table(name = "building_floors")
public class BuildingFloor {
@Id
@Column(name = "building_id")
private int buildingId;
@Id
@Column(name = "floor_id")
private int floorId;
@Column(name = "description")
private String description;
// getters/setters
}
我已尝试过一些我有占位符评论的事情:
这不起作用,因为它适用于目标实体。
@JoinColumns({
@JoinColumn(name = "building_id", referencedColumnName = "id"),
@JoinColumn(name = "'OFFICE'", referencedColumnName = "type")
})
这不起作用,因为我收到以下错误(为简洁起见而简化):Syntax error in SQL statement "SELECT * FROM buildings b JOIN building_floors bf on bf.building_id = b.id AND bf.'OFFICE' = b.type"
@JoinColumns({
@JoinColumn(name = "building_id", referencedColumnName = "id"),
@JoinColumn(name = "buildings.type", referencedColumnName = "'OFFICE'")
})
这不起作用,因为在使用单向OneToMany关系时,referencedColumnName来自源表。所以我收到错误:org.hibernate.MappingException: Unable to find column with logical name: 'OFFICE' in buildings
提前致谢!
答案 0 :(得分:9)
为什么不使用inheritance ? (我在JPA中使用它,我从不直接使用hibernate)
@Entity
@Inheritance
@Table(name = "buildings")
@DiscriminatorColumn(name="type")
public class Building {
@Id
@Column(name = "id")
private int id;
@Column(name = "type")
private String type;
}
并且:
@Entity
@DiscriminatorValue("OFFICE")
public class Office extends Building {
@OneToMany(mappedBy = "buildingId",
fetch = FetchType.EAGER,
cascade = {CascadeType.ALL},
orphanRemoval = true)
private Set<BuildingFloors> buildingFloors;
}
答案 1 :(得分:4)
使用以下选择创建数据库视图:
SELECT bf.* FROM building_floors bf JOIN buildings b on bf.building_id = b.id AND b.type = 'OFFICE'
将其作为普通实体映射到类OfficeBuildingFloors
,然后在@OneToMany
类中使用Building
。
当然,您无法修改此类集合,并且可以避免在@Immutable
上使用OfficeBuildingFloors
时出现的任何异常。
答案 2 :(得分:1)
在我看来,您应该创建一个特定的查询来实现您的目标,而不是使用常量参数来设置特定的注释。我没有看到你提到除了Hibernate之外的其他框架所以我会举一些Hibernate的例子。在Building
课程中,您的unidirectional
映射如下所示:
@OneToMany(fetch = FetchType.Lazy, cascade = {CascadeType.ALL}, orphanRemoval = true)
@JoinTable(name = "building_floors", joinColumns = @JoinColumn(name = "id"), inverseJoinColumns = @JoinColumn(name = "building_id")
private Set<BuildingFloor> buildingFloors;
然后,您可以使用TypedQuery
这样的方式获取数据。
TypedQuery<Customer> query = getEntityManager().createNamedQuery("select b from building b inner join fetch b.buildingFloors where b.type = 'OFFICE'", Building.class);
List<Building> result = query.getResultList();
我的解决方案不是特定于Hibernate的,实际上你可以用简单的JPA来执行它。希望这可以帮助您实现目标。
答案 3 :(得分:1)
如果您想要过滤器源表,可以使用@Loader注释
@Entity
@Table(name = "buildings")
@Loader(namedQuery = "building")
@NamedNativeQuery(name="building",
query="SELECT * FROM buildings b"
+ " LEFT JOIN building_floors bf on bf.building_id = b.id"
+ " WHERE b.type = 'OFFICE' AND b.id = ?",
resultClass = Building.class)
class Building
如果可以在DB内部使用,那么使用DB中的视图方法会更好更清晰。否则,将Building重命名为明确表示过滤的内容。
另一种方法:@Filter,@ FilterDef。