【发布时间】:2014-08-19 20:51:52
【问题描述】:
我将 Java EE 战争网站从 GlassFish 4 迁移到 WildFly。
Glassfish 使用 EclipseLink,WildFly 使用 Hibernate。我正在使用带有 CDI 命名 bean 的 Java Server Faces。我的一个 bean 直接调用 dao 类方法来检索 Category 对象。 Category 类有一些属性,其中之一是 List 商品。默认情况下,这是延迟初始化的(商品是另一个表)。检索到 Category 对象,但在尝试使用延迟初始化的 List 商品时,持久性包为空并引发以下错误:
javax.servlet.ServletException: failed to lazily initialize a collection of role: cz.pscheidl.velkoobchod.domain.Category.merchandise, could not initialize proxy - no Session
我想我知道这是什么问题。调用此对象时,名为 EshopBean 的 @Named bean 不提供任何事务。这在 Glassfish 中不应该起作用,但不知何故它确实起作用了。在 Category 对象中设置 List 商品的 EAGER 初始化后,一切正常。相关命名查询中的 JOIN FETCH 也是如此。
EshopBean 对象如下所示:
@Named
@ViewScoped
public class EshopBean implements Serializable {
@Inject private CategoryDao categoryDao;
@Inject private MerchandiseDao merchandiseDao;
@Inject private ActiveSession activeSession;
@Inject private OrderDao orderDao;
@Inject private Logger logger;
private List<Category> categoryList;
private List<OrderItem> offeredMerchandise;
@PostConstruct
@TransactionAttribute(TransactionAttributeType.REQUIRED)
public void updateOfferedMerchandise() {
List<Category> allCateogries = categoryDao.findByOffered(true);
offeredMerchandise = new ArrayList<>();
categoryList = new ArrayList<>();
allCateogries.parallelStream().filter(e -> {
return !e.getMerchandise().isEmpty();
}).forEach(e -> {
categoryList.add(e);
e.getMerchandise().parallelStream().filter(m -> {
return m.isOffered();}).forEach(m -> {
offeredMerchandise.add(createOrderItem(m));
});
});
}
}
类别对象如下(省略方法):
@Entity
@NamedQueries(
{
@NamedQuery(name = "findCategoryByName", query = "SELECT c FROM Category c WHERE c.name = :name"),
@NamedQuery(name = "findAllCategories", query = "SELECT c FROM Category c"),
@NamedQuery(name = "categoryHasMerchandise", query = "SELECT COUNT(m) FROM Merchandise m WHERE m.category = :categoryId"),
@NamedQuery(name = "findCategoryByOffered", query = "SELECT c FROM Category c WHERE c.offered = :offered")
}
)
public class Category implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
@Column(unique = true)
@Size(min = 1, max = 255)
private String name;
@Column(nullable = false)
private boolean offered;
@OneToMany(fetch = FetchType.LAZY, cascade = CascadeType.REMOVE)
@JoinColumn(name = "CATEGORY_ID")
public List<Merchandise> merchandise;
}
CategoryDaoImpl(部分方法省略):
@Stateless
public class CategoryDaoImpl implements CategoryDao {
@PersistenceContext
private EntityManager entityManager;
@Override
@TransactionAttribute(TransactionAttributeType.REQUIRED)
public List<Category> findByOffered(boolean activity) {
Query findByOfferedQuery = entityManager.createNamedQuery("findCategoryByOffered", Category.class);
findByOfferedQuery.setParameter("offered", true);
return findByOfferedQuery.getResultList();
}
}
方法调用链是这样的:EshopBean.updateOfferedMerchandise() -> CategoryDaoImpl.findByOffered() -> 返回EshopBean.updateOfferedMerchandise()。我猜两者都被注释为事务性的,findByOffered 方法被注释为必需的。然而 WildFly 中的 Hibernate 说没有会话(我认为它需要相同的事务上下文)。
问题总结: 我想保持merchnadise 延迟初始化并纠正session 问题,所以在EshopBean.updateOfferedMerchandise() 方法中延迟初始化带有商品的包。我真的需要 JOIN FETCH 或将延迟初始化设置为 false 吗?如何设置正确的事务以使此代码开始工作?
【问题讨论】:
-
JOIN FETCH 将是正确的过程。
-
关于你的第二个问题,我没有得到你想问的问题?
标签: hibernate jakarta-ee eclipselink wildfly