gpt4 book ai didi

java - Hibernate:如何使用带有谓词的@SecondaryTable从连接表中获取字段

转载 作者:行者123 更新时间:2023-11-30 06:28:47 24 4
gpt4 key购买 nike

我有 3 个表,但我只感兴趣

  • 表A
  • A_Cat 中的“金额”字段(这是“A”和“类别”之间的联接表),用于明确定义的 cat_Id 值。此谓词使关系成为 OneToOne 而不是 OneToMany。

这是简化的结构:

CREATE TABLE A
(
a_id INT AUTO_INCREMENT PRIMARY KEY,
title VARCHAR(50) NOT NULL
);

CREATE TABLE Category
(
cat_id INT AUTO_INCREMENT PRIMARY KEY,
title VARCHAR(50) NOT NULL
);

CREATE TABLE A_Category
(
a_id INT PRIMARY KEY,
cat_id INT PRIMARY KEY,
amount INTEGER NOT NULL
);

Java代码:

@Entity
@Table(name = "A")
@SecondaryTable(name = "A_Category", pkJoinColumns = {@PrimaryKeyJoinColumn(name = "a_id")}))
public class ModelA {

@Id
@Column(name = "a_id")
private Long id;

@Column(name = "amount", table = "A_Category")
private Integer amount;
}

这会在 Hibernate 中为所有可能的值生成“A”和“A_Category”之间的连接。

所以,这是我的问题,如何向SecondaryTable 添加谓词(例如:cat_id = 1)。

可以用注解来完成吗?我用 @WhereJoinTable 尝试过,但没有成功。

PS:如果我使用@Formula,我可以获得我想要的东西,但是如果我想要来自A_Category的更多字段,那么生成的sql性能不那么好,并且喜欢避免在我的POJO中编写sql。

最佳答案

JPA 实体

JPA 实体必须反射(reflect)数据库结构,不应直接涉及业务逻辑。从您的简化结构来看,我假设您可以使用这些实体:

@Entity
@Table(name = "A")
public class A{

@Id
@Column(name = "a_id")
private Long id;

@Column(name = "title")
private String title;

@OneToMany(mappedBy = "a")
private List<ACategory> categoryList;

// no-arg constructor
public A(){
// initialise the list in the no-arg constructor to avoid bad surprises...
this.categoryList = new ArrayList<>();
}

// getters & setters
}

作为ManyToMany关系has an extra column ,您将需要 ACategory 实体:

@Entity
@Table(name = "A_Category")
public class ACategory{

// dedicated id column, see note(*) below
@Id
@Column(name = "id")
private Long id;

// foreign key to "A" table
@ManyToOne
@JoinColumn(name = "a_id")
private A a;

// foreign key to "Category" table
@ManyToOne
@JoinColumn(name = "cat_id")
private Category category;

@Column(name = "amount")
private Integer amount;

// no-arg constructor

// getters & setters
}

(*):请注意,ACategory 有一个专用的 id 列。它将避免一些问题,例如 this question .

为了完整起见,Category 实体看起来像

@Entity
@Table(name = "Category")
public class Category{

@Id
@Column(name = "cat_id")
private Long id;

@Column(name = "title")
private String title;

@OneToMany(mappedBy = "category")
private List<ACategory> aList;

// no-arg constructor
public Category(){
this.aList = new ArrayList<>();
}

// getters & setters
}

命名查询

那么解决您的问题的方法是使用 JPQL @NamedQuery您可以在其中拥有业务逻辑。一个例子可以是:

@Entity
@Table(name = "A")
@NamedQuery(
name="A.findAllByCategoryId"
query="SELECT a FROM A a "
+ "INNER JOIN a.categoryList relACat "
+ "INNER JOIN relACate.category c"
+ "WHERE c.id = :categoryId"
)
public class A{
// cf. above
}

我使用了命名参数,但您也可以使用 ordinal parameters .

查询

然后,在与 A 实体关联的服务中,您可以通过以下方式使用命名查询:

import javax.persistence.EntityManager;
import javax.persistence.TypedQuery;

@Stateless
public class AService{

// @PersistenceContext properly filled
private EntityManager em;

public List<A> fetchAEntities(){
TypedQuery<A> query = em.createNamedQuery("A.findAllByCategoryId", A.class);
// it seems you can afford hardcoding it
query.setParameter("categoryId", 1);

return query.getResultLis();
}
}

如果您希望拥有特定的 A 实体而不是 A 列表,只需在 WHERE 子句中创建另一个带有附加参数的 NamedQuery 即可。

<小时/>

作为非 Hibernate 用户,这是一个纯 JPA 解决方案

关于java - Hibernate:如何使用带有谓词的@SecondaryTable从连接表中获取字段,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46548392/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com