未能延迟初始化角色集合:无法初始化代理 - Hibernate 中的 @ManyToMany 映射注释中没有会话错误? [复制]
Posted
技术标签:
【中文标题】未能延迟初始化角色集合:无法初始化代理 - Hibernate 中的 @ManyToMany 映射注释中没有会话错误? [复制]【英文标题】:failed to lazily initialize a collection of role: could not initialize proxy - no Session error in @ManyToMany mappin annotation in Hibernate? [duplicate] 【发布时间】:2015-06-14 12:19:51 【问题描述】:您好,我是 java 服务器端创建 JSON API 的新手,我在 hibernate 中使用 ManytoMany
映射来连接两个表。我有两个类,一个是 Product.class
和 Offers.class
。
Product.class
@Entity
@Table(name = "products")
public class Product
@Column(name = "merchant_code")
private String merchant_code;
@Column(name = "branch_code")
private String branch_code;
@Column(name = "product_category_code")
private String product_category_code;
@Id @GeneratedValue
@Column(name = "product_code")
private String product_code;
@Column(name = "product_short_desc")
private String product_short_desc;
@Column(name = "product_long_desc")
private String product_long_desc;
@Column(name = "image")
private String image;
@Column(name = "price")
private String price;
@Column(name = "Active_Inactive")
private String Active_Inactive;
@ManyToMany(mappedBy = "offer_relation_code", fetch = FetchType.EAGER)
@Where(clause = "offer_type_code = 1")
private List<Offers> offer;
//here my getter setter
Offers.class
@Entity
@Table(name = "offers")
public class Offers
@Id @GeneratedValue
@Column(name = "offer_code")
private int offer_code;
@Column(name = "offer_type_code")
private int offer_type_code;
@Column(name = "offer_relation_code")
private int offer_relation_code;
@Column(name = "branch_code")
private int branch_code;
@Column(name = "valid_from")
private String valid_from;
@Column(name = "valid_until")
private String valid_until;
@Column(name = "offer_value")
private int offer_value;
@Column(name = "offer_desc")
private String offer_desc;
//here my getter setter
获取数据
factory = cfg.configure().addAnnotatedClass(Product.class).buildSessionFactory(registry);
Session session = factory.openSession();
Transaction tx = null;
try
tx = session.beginTransaction();
Criteria criteria = session.createCriteria(Product.class);
criteria.setFetchMode("product",FetchMode.JOIN);
Criterion merchant_code_Criterion = Restrictions.eq("merchant_code", new String(merchant_code));
Criterion branch_code_Criterion = Restrictions.eq("branch_code", new String(branch_code));
LogicalExpression andExp = Restrictions.and(merchant_code_Criterion,branch_code_Criterion);
criteria.add(andExp);
search_products = (ArrayList<Product>) criteria.list();
tx.commit();
catch (HibernateException e)
// TODO: handle exception
if (tx != null)
tx.rollback();
e.printStackTrace();
finally
session.close();
我加入offer
表和product
表就像@ManyToMany(mappedBy = "offer_relation_code", fetch = FetchType.EAGER)
我在Google 中搜索它,其中许多人说不要使用EAGER,这会导致一些问题,但是当我正在使用@ManyToMany(mappedBy = "offer_relation_code", fetch = FetchType.LAZY)
显示类似failed to lazily initialize a collection of role: could not initialize proxy - no Session
的错误。当我使用 EAGER 时,它工作正常,没有错误。使用 EAGER 是好是坏。谁能解释一下。
【问题讨论】:
我敢肯定,你可以在课堂上提供更少的字段来展示你的问题的想法。建议您在主题代码中减少源代码。 @Andremoniy 好吧,我会减少它。 【参考方案1】:EAGER
和 LAZY
在有用时都有用例,一般来说它们不是好或坏。
当某个关系被标记为EAGER
时,这意味着当获取父实体时,该关系中的所有数据都将从数据库中获取。一个 SQL 将用于所有数据。
使用LAZY
关系,最初只获取父实体的数据。惰性关系被 Hibernate 的代理类替换,该类将在第一次访问其任何属性时使用单独的 SQL 语句获取子实体的数据。但是,必须有一个活动的 Hibernate 会话才能使其工作。在活动会话之外调用时,您会收到异常 failed to lazily initialize a collection
。
对于@nToMany
映射,LAZY
是默认值,这是非常有意义的,因为Many
确实可以表示很多,而且很有可能您不需要所有映射数据。因此,将其留在LAZY
并在需要的服务中获取数据通常是一个好主意。 Hibernate 有一个用于初始化惰性关系的实用方法,Hibernate.initialize(parent.getLazyChild())
。
但是,正如我在开头所说的,这完全取决于用例,最好知道EAGER
和LAZY
的所有含义,这样您就可以做出自己的决定。
【讨论】:
【参考方案2】:先说一下你有的两个POJO。
Offer 类代表一张桌子。换句话说,它只代表一个表中的所有列,不引用任何其他表。
Product 类也只代表一个表,但是你有一个对 Offer 类的引用。
现在,如果您想获取产品代码“abc”的记录
EAGER:使用它时,您要求 JPA 使用来自产品的数据以及来自报价表的相应数据填充 POJO。
LAZY:使用它时,您要求 JPA 仅使用产品表中的数据填充 POJO。只有当您调用 getOffers() 时,才应进行另一个数据库调用以填充报价表中的相应数据。
当不经常需要引用表中的数据时,您可以使用 LAZY。优惠数据可能永远不会显示的可能性很大 (>25%)。
当引用表中的数据几乎总是需要时,您应该使用 EAGER。
对于您的错误,在您的最后一个块中,您正在调用 session.close()。当您使用 LAZY 时,事务在初始提取后关闭。当您调用 getOffers() 时,JPA 会尝试建立数据库连接 - 但由于它使用已关闭的连接/会话而失败。
【讨论】:
【参考方案3】:EAGER 告诉 hibernate 始终获取 Many 关系上的所有组件(您问题中的所有 Offer),即使在您不需要它们的情况下也是如此。 使用 LAZY,您有责任在您真正需要的时候在交易中获取这些 Offer。
【讨论】:
以上是关于未能延迟初始化角色集合:无法初始化代理 - Hibernate 中的 @ManyToMany 映射注释中没有会话错误? [复制]的主要内容,如果未能解决你的问题,请参考以下文章
休眠延迟加载不适用于 Spring Boot => 无法延迟初始化角色集合无法初始化代理 - 无会话
LazyInitializationException: 延迟初始化角色集合失败 无法初始化代理 - 没有会话
org.hibernate.LazyInitializationException:无法延迟初始化角色集合:FQPropretyName,无法初始化代理 - 无会话
无法延迟初始化角色集合:myapp.myapp.models.Contact.messages,无法初始化代理 - 没有会话