通过休眠加入外键
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看完你的评论。看起来你从来没有在那里设置条件,当然,无论它们属于哪个商店,你最终都会得到所有的产品。没有惊喜。您在哪里指定标准?
你可以这样做,
// One liner
List<Product> list = session.createQuery("from Product p where p.store.store_id = "
+" :storeId").setInteger("storeId", storeId).list();
或者您可以获取Store
,然后获取Product
s 的列表,如下所示,
// 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。不过感谢您的链接,我不知道性能差异!以上是关于通过休眠加入外键的主要内容,如果未能解决你的问题,请参考以下文章