Hibernate many-to-many 查询写法

本文介绍了在Grails中利用Hibernate进行多对多关系查询的方法,包括使用HQL及Criteria API的具体实现,并提供了查找特定标签博客文章的例子。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

« TTServer Java 客户端 Tyrond 用 HttpServletResponseWrapper 实现 Etag 过滤器 »

Hibernate many-to-many 查询写法

发表于: 2009年7月18日 | 分类: groovy & grails | 标签:  grailshibernatehqlmany-to-manyquery |  views(1,217)

版权信息: 可以任意转载, 转载时请务必以超链接形式标明文章原文出处, 即下面的声明.

 

原文出处:http://blog.chenlb.com/2009/07/hibernate-many-to-many-query-style.html

玩 Grails 的时候,遇到一个问题,卡在 many-to-many 查询上了。之前学 hibernate 不深,所以会卡。

先来看下例子:两个实体类 Blog、Tag,它们是多对多关系。

例如要查找 tag 为 j2ee 的所有博客文章。

1、用 HQL

  1. //记录数  
  2. def blogNum = Blog.executeQuery("select count(bs) from Blog as bs left join bs.tags as t where t.name=:tname",[tname:params.tag])  
  3. def blogs = Blog.executeQuery("select bs from Blog as bs left join bs.tags as t where t.name=:tname",[tname:params.tag], [max:params.max, offset:params.offset])  

hql 是比 sql 方便,sql 要多写一个 join。但要对 hql 熟悉才行。

2、用 Criteria

  1. //记录数  
  2. def c = Blog.createCriteria()  
  3. def blogNum = c {  
  4.     projections {//记数投影  
  5.         count('id')  
  6.     }  
  7.     tags {//join Tag  
  8.         eq('name', params.tag)  
  9.     }  
  10. }  
  11. //找内容  
  12. def blogC = Blog.createCriteria()  
  13. def blogs = blogC.list {  
  14.     tags {  
  15.         eq('name', params.tag)  
  16.     }  
  17.     firstResult(params.offset)  
  18.     maxResults(params.max)  
  19. }  

看了它们的输出 sql,基本没区别,Criteria 的方式是用 left outer join 的,其实与 left join 一样,用 hql 就可以自己控制 join 吧,还有就是可以节省两个匿名类。还是选择用 hql 方式吧。

可能还有其它方式……

hibernate 3.x 的 hql 中文手册:http://www.redsaga.com/hibernate-ref/3.x/zh-cn/html/queryhql.html

 

 

随机日志 »

相关日志 »

 

<think>嗯,用户现在问的是关于“'One To Many' attribute type should be a container”的问题。之前他们问过类似的Spring Data JPA的异常,所以可能是在使用JPA时遇到了映射配置的问题。需要先理解这个错误信息的具体含义。 首先,用户提到的错误信息是说在一对多关系中,属性类型应该是一个容器。这意味着在JPA中,@OneToMany注解标注的字段必须是一个集合类型,比如List、Set等,而不能是单个实体对象。这可能是因为用户错误地将@OneToMany用在了单个对象而不是集合上。 接下来,我需要回顾之前的回答,确保不重复同样的内容。之前已经解释了InvalidDataAccessApiUsageException,提到了关联关系配置错误的情况,特别是@OneToMany和@ManyToOne的使用。现在用户的新问题更具体,针对的是属性类型不是容器的情况。 我应该先解释这个错误的原因,然后给出示例代码的错误和正确版本,帮助用户理解问题所在。同时,可能需要提醒用户检查他们的实体类,确保一对多的那一端使用的是集合类型,并且正确配置了mappedBy属性。此外,级联操作和获取策略也可能影响,需要适当提及。 用户可能的误区是误将多的一方作为单个对象而不是集合,或者在使用@OneToMany时没有正确设置关联关系。需要举出具体的例子,说明错误的代码是怎样的,然后展示正确的写法。此外,可能还需要提到常见的解决方案,比如使用List或Set,初始化集合以避免空指针,以及正确维护双向关联的方法。 最后,总结关键点,帮助用户快速理解和修正他们的代码。可能还需要建议他们检查其他相关配置,比如是否缺少必要的注解,或者关联关系的维护方是否正确。如果有必要,可以提到如何启用Hibernate的日志来查看生成的SQL,帮助调试。</think>`'One To Many' attribute type should be a container` 是 **JPA/Hibernate 实体映射配置错误**的典型提示,意味着你在使用 `@OneToMany` 注解时,属性的类型不符合规范。以下是详细解释和解决方案: --- ### **错误本质** - **问题核心**:`@OneToMany` 注解必须标注在一个**集合类型**的字段上(如 `List`, `Set`, `Collection`),而你的代码中可能将字段声明为了**单个对象类型**(如直接使用 `Order` 而不是 `List<Order>`)。 - **JPA 规范**:`@OneToMany` 用于定义“一对多”关系,表示一个实体(如 `User`)关联多个子实体(如 `Order`),因此必须通过集合管理多个子实体。 --- ### **错误示例与修复** #### **错误场景** ```java @Entity public class User { @Id private Long id; // 错误!@OneToMany 标注在单个对象上,而非集合 @OneToMany private Order order; // ❌ 应该是 List<Order> orders } @Entity public class Order { @Id private Long id; } ``` #### **正确写法** ```java @Entity public class User { @Id private Long id; // 正确:使用集合类型 @OneToMany(mappedBy = "user", cascade = CascadeType.ALL) private List<Order> orders = new ArrayList<>(); // ✅ } @Entity public class Order { @Id private Long id; // 多的一方通过 @ManyToOne 维护外键 @ManyToOne @JoinColumn(name = "user_id") private User user; } ``` --- ### **关键注意事项** 1. **集合类型必选** `@OneToMany` 必须绑定到集合类型(如 `List<Order>`、`Set<Order>`),不可直接使用子实体类型(如 `Order`)。 2. **双向关联维护** - 在双向关联中,`@OneToMany` 通常需要与 `@ManyToOne` 配对使用。 - `mappedBy` 属性用于指定关联的维护方(通常是子实体的字段名)。例如:`mappedBy = "user"` 表示关联由 `Order.user` 字段管理。 3. **集合初始化** 建议在声明集合时直接初始化(如 `new ArrayList<>()`),避免 `null` 值导致空指针异常。 4. **级联操作** 通过 `cascade` 属性(如 `cascade = CascadeType.ALL`)控制级联操作,确保父实体保存/删除时自动处理子实体。 --- ### **常见陷阱** #### 陷阱1:忘记 `mappedBy` 若未指定 `mappedBy`,JPA 会默认创建**中间关联表**,导致不符合预期的表结构: ```java // 错误:未指定 mappedBy,会生成 user_orders 中间表 @OneToMany private List<Order> orders; ``` #### 陷阱2:直接操作数据库外键 避免手动管理外键字段,应通过对象关联实现: ```java // 错误:在 User 中直接定义外键字段 @Column(name = "order_id") private Long orderId; // ❌ 应通过关联关系自动管理 ``` --- ### **总结** - **根本原因**:`@OneToMany` 注解的字段类型必须是集合(如 `List`),不能是单个对象。 - **修复步骤**: 1. 检查实体类中 `@OneToMany` 标注的字段是否为集合类型。 2. 确认双向关联中正确使用 `mappedBy`。 3. 初始化集合字段,避免 `null` 值。 4. 按需配置级联操作(`cascade`)和加载策略(`fetch`)。 通过规范实体映射配置,可彻底解决此问题。若仍报错,建议检查 Hibernate 日志中的 SQL 语句,确认表结构和外键是否符合预期。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值