gpt4 book ai didi

java - JPA递归延迟加载失败

转载 作者:太空宇宙 更新时间:2023-11-04 11:41:18 25 4
gpt4 key购买 nike

我有一个名为 Menu 的实体有一个 parent和多个children我使用 JPA 加载。一切正常,当 children设置为@OneToMany(mappedBy = "parent", fetch = FetchType.EAGER) ,但如果我将其设置为 FetchType.LAZY ,我收到错误:

org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: com.mydom.myapp.domain.Menu.children, could not initialize proxy - no Session

我使用Hibernate 4.3.1.Final、JPA、Wildfly 10.1.0作为服务器、MySQL作为数据库。

我已经尝试过 Hibernate.initialize(menu.getChildren()) 的技巧以及调用 size() 方法,如 menu.getChildren().size() 中所示,但在这两种情况下我都会导致相同的错误。

我也尝试设置 @Fetch(FetchMode.JOIN)这是有效的,但它非常类似于使用 FetchType.Eager ,因此没有用。两者@Fetch(FetchMode.SELECT)@Fetch(FetchMode.SUBSELECT)行不通。

我必须做什么才能延迟加载menu.getChildren()

所以,下面我有三个类来处理这个问题。方法MenuManagerController.buildNodeStructureFromMenu(TreeNode root, List<Menu> menus)执行递归工作。这是延迟加载发生的地方。

菜单.java:

@Entity
@NamedQueries({
@NamedQuery(name = Menu.FIND_MENU_ROOT,
query = "SELECT m FROM Menu m WHERE m.parent.id IS NULL")
})
public class Menu implements Serializable {
private static final String PREFIX = "Menu.";
public static final String FIND_MENU_ROOT = PREFIX + "findMenuRoot";

@Id
@GeneratedValue
private long id;
@ManyToOne
private Languages languageType;
@Column(length = 100)
private String nameDisplay;
private String nameAddress;
private int position;
@ManyToOne
private Menu parent;
@OneToMany(mappedBy = "parent", fetch = FetchType.LAZY)
private List<Menu> children;

// Getters, setters, etc.
}

MenuManagerController.java:

@Named
@ViewScoped
public class MenuManagerController implements Serializable {
@Inject
private MenuService menuService;
private Languages selectedLanguage;
private List<Languages> languages;
private String menuName;
private TreeNode rootMenu;
private TreeNode selectedMenu;

@PostConstruct
private void init() {
// Find root menu.
Menu menu = menuService.findRootMenu();
// Create root node.
this.rootMenu = new DefaultTreeNode(menu, null);
// Lazy load children.
Hibernate.initialize(menu.getChildren());
// Build Node from Menu.
buildNodeStructureFromMenu(this.rootMenu, menu.getChildren());
}

private void buildNodeStructureFromMenu(TreeNode root, List<Menu> menus) {
App.printWithTrace("Add all the " + menus.size() + " children to \"" + root.getData().toString() + "\".");

for(Menu menu : menus) {
App.printWithTrace("Create node for \"" + menu.getNameDisplay() + "\".");
// Create child node of root node.
TreeNode child = new DefaultTreeNode(menu, root);
// Lazy load children.
Hibernate.initialize(menu.getChildren());
// Create all children of this menu.
List<Menu> children = menu.getChildren();
// Recursion.
buildNodeStructureFromMenu(child, children);
}
}
}

MenuService.java:

@Stateless
public class MenuService {
@PersistenceContext(unitName = "MyappPU")
private EntityManager em;

public enum Layer {
All,
FirstOnly
}

public Menu findRootMenu() {
return this.em.createNamedQuery(Menu.FIND_MENU_ROOT, Menu.class)
.getSingleResult();
}

// More methods, etc.
}

最佳答案

异常表明您在事务关闭后尝试获取延迟加载的关系。

我建议你看看我的文章:https://arnoldgalovics.com/lazyinitializationexception-demystified/

但是,我的文章是针对基于 Spring 的配置编写的,您可以轻松地根据您的情况进行调整。

关于java - JPA递归延迟加载失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42744296/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com