Hibernate/JPA 单向 OneToMany,连接条件为源中的常量值 table
Hibernate/JPA unidirectional OneToMany with join condition on constant value in source table
我想使用 Hibernate 注释来表示使用连接的单向一对多关系。我想在连接上添加一个条件,因此只有当 source table("one")中的列等于常数值时才会发生。例如.
SELECT *
FROM buildings b
LEFT JOIN building_floors bf on bf.building_id = b.id AND b.type = 'OFFICE'
我想表示该查询的 b.type = 'OFFICE'
部分。
我的问题与这个问题非常相似,只是我对来源有条件 table。
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
}
我已经尝试了一些有占位符评论的东西:
@Where注解
这不起作用,因为它适用于目标实体。
@JoinColumns 注解
@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 注释
@JoinColumns({
@JoinColumn(name = "building_id", referencedColumnName = "id"),
@JoinColumn(name = "buildings.type", referencedColumnName = "'OFFICE'")
})
这不起作用,因为在使用单向 OneToMany 关系时,referencedColumnName 来自源 table。所以我得到错误:org.hibernate.MappingException: Unable to find column with logical name: 'OFFICE' in buildings
提前致谢!
在我看来,您应该创建一个特定的查询来实现您的目标,而不是使用常量参数放置特定的注释。我没有看到你提到除 Hibernate 之外的其他框架,所以我会举一些 Hibernate 的例子。在您的 Building
class 中,您的 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 来执行此操作。希望这可以帮助你实现你的目标。
为什么不使用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;
}
使用以下 select 创建数据库视图:
SELECT bf.* FROM building_floors bf JOIN buildings b on bf.building_id = b.id AND b.type = 'OFFICE'
将其映射到 class OfficeBuildingFloors
作为普通实体,然后在 Building
class.
中使用 @OneToMany
当然,您将无法修改此类集合,为避免任何异常,您可以在 OfficeBuildingFloors
上使用 @Immutable
。
如果你想要过滤源 table 你可以使用 @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
在数据库中使用视图的方法会更好、更清晰,如果它也可以在数据库中使用。否则将 Building 重命名为明确表示过滤的名称。
提及的另一种方法:@Filter、@FilterDef。
我想使用 Hibernate 注释来表示使用连接的单向一对多关系。我想在连接上添加一个条件,因此只有当 source table("one")中的列等于常数值时才会发生。例如.
SELECT *
FROM buildings b
LEFT JOIN building_floors bf on bf.building_id = b.id AND b.type = 'OFFICE'
我想表示该查询的 b.type = 'OFFICE'
部分。
我的问题与这个问题非常相似,只是我对来源有条件 table。
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
}
我已经尝试了一些有占位符评论的东西:
@Where注解
这不起作用,因为它适用于目标实体。
@JoinColumns 注解
@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 注释
@JoinColumns({
@JoinColumn(name = "building_id", referencedColumnName = "id"),
@JoinColumn(name = "buildings.type", referencedColumnName = "'OFFICE'")
})
这不起作用,因为在使用单向 OneToMany 关系时,referencedColumnName 来自源 table。所以我得到错误:org.hibernate.MappingException: Unable to find column with logical name: 'OFFICE' in buildings
提前致谢!
在我看来,您应该创建一个特定的查询来实现您的目标,而不是使用常量参数放置特定的注释。我没有看到你提到除 Hibernate 之外的其他框架,所以我会举一些 Hibernate 的例子。在您的 Building
class 中,您的 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 来执行此操作。希望这可以帮助你实现你的目标。
为什么不使用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;
}
使用以下 select 创建数据库视图:
SELECT bf.* FROM building_floors bf JOIN buildings b on bf.building_id = b.id AND b.type = 'OFFICE'
将其映射到 class OfficeBuildingFloors
作为普通实体,然后在 Building
class.
@OneToMany
当然,您将无法修改此类集合,为避免任何异常,您可以在 OfficeBuildingFloors
上使用 @Immutable
。
如果你想要过滤源 table 你可以使用 @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
在数据库中使用视图的方法会更好、更清晰,如果它也可以在数据库中使用。否则将 Building 重命名为明确表示过滤的名称。
提及的另一种方法:@Filter、@FilterDef。