在Hibernate中的@ManyToMany映射注释中,出现了“无法初始化代理 - 无会话错误:无法懒加载角色的集合”。

10 浏览
0 Comments

在Hibernate中的@ManyToMany映射注释中,出现了“无法初始化代理 - 无会话错误:无法懒加载角色的集合”。

我是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 offer;

//这里是我的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;

//这里是我的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) 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好还是坏,有人可以解释一下吗?

0
0 Comments

这个问题的出现是因为在Hibernate的@ManyToMany映射注解中,出现了"failed to lazily initialize a collection of role: could not initialize proxy - no Session"错误。这个错误的原因是在使用LAZY加载模式时,事务在初始获取数据后被关闭,而当调用getOffers()方法时,Hibernate试图建立数据库连接,但由于连接/会话已关闭,所以导致了错误的发生。

解决这个问题的方法是可以将加载模式从LAZY改为EAGER。当使用EAGER加载模式时,JPA会在获取数据时同时从关联表中获取对应的数据,避免了在调用getOffers()时再次建立数据库连接的问题。这样可以确保数据的完整性,并避免了"failed to lazily initialize a collection of role: could not initialize proxy - no Session"错误的发生。

下面是一段示例代码,演示了如何使用EAGER加载模式解决这个问题:

@Entity
@Table(name = "product")
public class Product {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    
    private String code;
    
    // 使用EAGER加载模式
    @ManyToMany(fetch = FetchType.EAGER)
    @JoinTable(name = "product_offer",
               joinColumns = @JoinColumn(name = "product_id"),
               inverseJoinColumns = @JoinColumn(name = "offer_id"))
    private Set offers;
    
    // 省略其他属性和方法
}
@Entity
@Table(name = "offer")
public class Offer {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    
    private String name;
    
    // 省略其他属性和方法
}

在上面的示例代码中,我们将Product类中的加载模式从LAZY改为了EAGER。这样在获取Product对象时,它的offers属性会立即从关联表中获取对应的数据,避免了在调用getOffers()时再次建立数据库连接的问题。

总结起来,当出现"failed to lazily initialize a collection of role: could not initialize proxy - no Session"错误时,可以考虑将加载模式从LAZY改为EAGER,以确保数据的完整性并避免错误的发生。

0
0 Comments

原因:当使用@ManyToMany注解进行映射时,在Hibernate中出现"failed to lazily initialize a collection of role: could not initialize proxy - no Session"错误是因为默认情况下,Hibernate使用的是延迟加载(Lazy Loading)策略。这意味着在访问关联的集合属性时,Hibernate将尝试延迟加载(只在需要时加载)该集合,并且在加载该集合之前已经关闭了与数据库的会话(Session),因此无法初始化代理对象。

解决方法:可以采用以下两种方法来解决这个问题:

1. 使用EAGER加载策略:将@ManyToMany注解上的fetch属性设置为FetchType.EAGER,这将告诉Hibernate始终在加载实体时立即获取关联的集合属性。这样可以避免延迟加载的问题,但可能会导致性能问题,特别是当关联的集合非常大时。

@ManyToMany(fetch = FetchType.EAGER)

2. 在需要访问关联的集合属性时,手动加载该集合:在访问关联的集合属性时,使用Hibernate的initialize()方法手动加载该集合。这将强制Hibernate初始化代理对象并加载关联的集合。在使用该方法之前,确保会话(Session)仍然处于打开状态。

Hibernate.initialize(entity.getCollectionProperty());

通过以上两种方法,可以解决"failed to lazily initialize a collection of role: could not initialize proxy - no Session"错误,并正确加载关联的集合属性。

0
0 Comments

failed to lazily initialize a collection of role: could not initialize proxy - no Session错误的出现原因是调用了一个懒加载的集合属性,但是没有激活Hibernate会话。而解决方法是通过调用Hibernate.initialize()方法来手动初始化懒加载的关系。

在Hibernate中,关系可以使用EAGERLAZY来进行标记。当关系被标记为EAGER时,意味着在获取父实体时,所有的关联数据都会从数据库中一次性获取。而LAZY关系,只会在最初获取父实体的数据时进行加载,关联的子实体数据会在第一次访问它的属性时,使用单独的SQL语句进行获取。但是,这需要在Hibernate会话处于活动状态时才能正常工作。否则,就会出现failed to lazily initialize a collection的异常。

对于@ManyToMany映射,LAZY是默认值,这是有道理的,因为Many可能意味着很多的数据,你可能并不需要全部获取。因此,通常最好将其保持为LAZY,在需要的时候在服务中获取数据。Hibernate提供了一个初始化懒加载关系的工具方法Hibernate.initialize(),可以手动初始化懒加载的关系。

但是,正如开头所说,具体使用哪种加载方式取决于具体的使用场景,最好了解EAGERLAZY的所有影响,以便可以做出适当的决策。

0