通过休眠加入外键

Posted

技术标签:

【中文标题】通过休眠加入外键【英文标题】:join on foreign key with hibernate 【发布时间】:2011-04-21 17:25:27 【问题描述】:

我是 hibernate 初学者,在尝试使用 hibernate 加入 2 个表时遇到问题。我要做的是根据商店 ID 获取某个商店的产品列表,但我得到的是每个商店下列出的数据库中所有可用产品的列表。

这是Product.java 的代码:

@Entity
@Table (name = "products")
public class Product implements Serializable

/**
 * 
 */
private static final long serialVersionUID = -1001086120280322279L;

@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
@Column (name = "product_id")
private int product_id;

@Column(name = "product_name", unique=true)
private String product_name;

@JoinColumn(name = "store", referencedColumnName="store_id")
@ManyToOne(cascade=CascadeType.ALL)
private Store store;

等等。

这是Store.java 的代码:

@Entity
@Table(name = "stores")
public class Store implements Serializable
/**
 * 
 */
private static final long serialVersionUID = 4497252090404342019L;

@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
@Column (name = "store_id")
private int store_id;

@Column(name = "store_name", unique=true)
private String store_name;

@JoinColumn(name="store", referencedColumnName= "store_id")
@OneToMany(cascade=CascadeType.ALL, fetch=FetchType.EAGER)
private List<Product> productList;

等等。

这是输出:(产品 A 应该在 Butik A 下,产品 B 在 Butik B 下)

Butik: Butik A
Produkt: Banana A
Produkt: Morot A
Produkt: Banana B
Produkt: Apple B

Butik: Butik B
Produkt: Banana A
Produkt: Morot A
Produkt: Banana B
Produkt: Spple B

我有 2 个额外的类,ProductDAO 和 StoreDAO 负责查询,除了表名/类名之外,这两个类中的代码都相似。

public class ProductDAO  
   public static List<Product> getStoreProductsList()  
     Session hibernateSession = HibernateUtil.getSession(); 
     hibernateSession.beginTransaction();    
     Query query = hibernateSession.createQuery("from Product");
     hibernateSession.getTransaction().commit();     
     List<Product> storeProducts = query.list(); 
     return storeProducts;   
   

有没有办法只用hibernate解决这个问题?

谢谢

【问题讨论】:

如何检索产品列表?你用什么?加载?得到?休眠标准?高品质? SQL? 我有 2 个额外的类,ProductDAO 和 StoreDAO 负责查询,除了表名之外,这两个类中的代码都相似。 public class ProductDAO public static List getStoreProductsList() Session hibernateSession = HibernateUtil.getSession(); hibernateSession.beginTransaction();查询查询 = hibernateSession.createQuery("来自 se.kyh.stores.entities.Product"); hibernateSession.getTransaction().commit();列表 storeProducts = query.list();退货商店产品; 您应该将此评论添加到原始问题中。只需尝试编辑问题。 【参考方案1】:

看完你的评论。看起来你从来没有在那里设置条件,当然,无论它们属于哪个商店,你最终都会得到所有的产品。没有惊喜。您在哪里指定标准?

你可以这样做,

// One liner
List<Product> list = session.createQuery("from Product p where p.store.store_id = "
          +" :storeId").setInteger("storeId", storeId).list();

或者您可以获取Store,然后获取Products 的列表,如下所示,

// Another one liner
List<Product> list = session.createCriteria(Store.class)
             .add(Restrictions.eq("store_id", storeId)).list().getProductList();

另一种更简单的方法,我们知道store_id是主键,(感谢Pakore提醒我)

// And another. Changed to use load() instead of get() here. 
// Assuming non-existance is an error.
List<Product> list = (Store) session.load(Store.class,storeId).getProductList();

[已编辑]

...添加一些有用的指针(感谢Pascal)

14.3 Associations and joins

14.4 Forms of join syntax

【讨论】:

+1 表示 HQL 方法。我只想在文档的14.3. Associations and joins 和14.4. Forms of join syntax 部分添加一些链接。 +1 以 3 种方法和学分获得完整答案:) 感谢你们的慷慨。【参考方案2】:

问题在于您的查询,它只是选择系统中的所有产品,而不考虑商店。

尝试使用休眠条件。为数据库创建查询更容易,您始终可以从 Java“端”而不是 DB“端”工作。

int storeid = 1 //whatever you want here.
Criteria criteria = session.createCriteria(Product.class);
criteria.add(Restrictions.eq("store_id",storeid));
List<Product> list = criteria.list();

list 将包含属于Store 的产品列表,其中storeid 等于您提供的storeid

但是对于这个简单的查询,如果您使用session.get()session.load(),它甚至更更容易(它们之间的区别在这个answer 或更多关于它们的信息在documentation)

int storeid = 1; //Whatever you want
Store store = (Store) session.get(Store.class,storeid);
List<Product> list = store.getProductList();

如您所见,Hibernate 会为您完成连接 :)。

【讨论】:

您的第二个 sn-p 很适合进行小修复,您忘记了 list 的变量名称。为此+1。但是您的查询,在第一个 sn-p 中,将返回商店列表而不是产品。所以,我希望你不介意解决这个问题。 :) Criteria API “更容易”是主观的 IMO。我个人更喜欢HQL。从性能的角度来看,HQL 也更好。见Hibernate: Criteria vs. HQL 和Hibernate Query vs Criteria Performance。 @Adeel 已修复,该死的迷你重构:D。 @Pascal 好吧,确实是主观的。我认为对于初学者和简单的查询更容易使用Criteria,它更面向 Java。 HQL 更面向 QL。不过感谢您的链接,我不知道性能差异!

以上是关于通过休眠加入外键的主要内容,如果未能解决你的问题,请参考以下文章

休眠:外键的列数错误

休眠一对多注释外键空

据我所知,postgres 中的外键约束违规不应该发生。 (带休眠)

在休眠 ORM 中使用一个强制外键和一个可选外键中的列

JPA休眠两个外键到同一个表

休眠多对一注释外键 javax.el.E​​LException