gpt4 book ai didi

java - merge如何避免LazyInitException?

转载 作者:行者123 更新时间:2023-12-01 09:20:23 27 4
gpt4 key购买 nike

这是我的 PersistenceUtil 类..

package biz.tugay.learningjpa.persistence;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;

public class PersistenceUtilImpl implements PersistenceUtil {

private EntityManagerFactory entityManagerFactory;

public PersistenceUtilImpl(final String persistenceUnit) {
entityManagerFactory = Persistence.createEntityManagerFactory(persistenceUnit);
}

public EntityManager getEntityManager() {
final EntityManager entityManager = entityManagerFactory.createEntityManager();
return entityManager;
}

public void closeFactory() {
entityManagerFactory.close();
}
}

这些是我的实体..

Actor.java

package biz.tugay.learningjpa.model;

import javax.persistence.*;
import java.util.List;

@Entity
public class Actor {

private Integer id;
private String firstname;
private String lastname;

private List<Film> films;

@Id
@Column(name = "actor_id")
@GeneratedValue(strategy = GenerationType.AUTO)
public Integer getId() {
return id;
}

public void setId(Integer actor_id) {
this.id = actor_id;
}

@Basic
@Column(name = "first_name")
public String getFirstname() {
return firstname;
}

public void setFirstname(String first_name) {
this.firstname = first_name;
}

@Basic
@Column(name = "last_name")
public String getLastname() {
return lastname;
}

public void setLastname(String last_name) {
this.lastname = last_name;
}

@ManyToMany
@JoinTable(name = "film_actor",
joinColumns = @JoinColumn(name = "actor_id"),
inverseJoinColumns = @JoinColumn(name = "film_id")
)
public List<Film> getFilms() {
return films;
}

public void setFilms(List<Film> films) {
this.films = films;
}
}

Film.java

package biz.tugay.learningjpa.model;

import javax.persistence.*;
import java.util.List;

@Entity
public class Film {

private Integer id;
private String title;

private List<Actor> actors;

@Id
@Column(name = "film_id")
@GeneratedValue(strategy = GenerationType.AUTO)
public Integer getId() {
return id;
}

public void setId(Integer id) {
this.id = id;
}

@Basic
public String getTitle() {
return title;
}

public void setTitle(String title) {
this.title = title;
}

@ManyToMany
@JoinTable(name = "film_actor",
joinColumns = @JoinColumn(name = "film_id"),
inverseJoinColumns = @JoinColumn(name = "actor_id"))
public List<Actor> getActors() {
return actors;
}

public void setActors(List<Actor> actors) {
this.actors = actors;
}
}

我为我的模特提供 2 项服务:

ActorServiceImpl.java

public final class ActorServiceImpl implements ActorService {

private final PersistenceUtil persistenceUtil;

public ActorServiceImpl(PersistenceUtil persistenceUtil) {
this.persistenceUtil = persistenceUtil;
}

@Override
public List<Actor> getActorsOfFilm(Film film) {
final EntityManager entityManager = persistenceUtil.getEntityManager();
final Film mergedFilm = entityManager.merge(film);
final ArrayList<Actor> actors = new ArrayList<Actor>();
actors.addAll(mergedFilm.getActors());
entityManager.close();
return actors;
}
}

FilmServiceImpl.java

public final class FilmServiceImpl implements FilmService {

private final PersistenceUtil persistenceUtil;

public FilmServiceImpl(final PersistenceUtil persistenceUtil) {
this.persistenceUtil = persistenceUtil;
}

@Override
public Film filmById(int filmId) {
final EntityManager entityManager = persistenceUtil.getEntityManager();
final Film film = entityManager.find(Film.class, filmId);
entityManager.close();
return film;
}
}

我有 2 个测试,如下所示:

public class ActorServiceImplTest {

private PersistenceUtilImpl persistenceUtil;
private ActorServiceImpl actorService;

@Before
public void init() {
persistenceUtil = new PersistenceUtilImpl("sakiladb");
actorService = new ActorServiceImpl(persistenceUtil);
}

@After
public void tearDown() {
persistenceUtil.closeFactory();
}

@Test(expected = LazyInitializationException.class)
public void testGetActorsOfFilmLazyInit() {
final FilmServiceImpl filmService = new FilmServiceImpl(persistenceUtil);
final Film film = filmService.filmById(1);
for (Actor actor : film.getActors()) {
System.out.println(actor.getFirstname());
}
}

@Test
public void testGetActorsOfFilm() {
final FilmServiceImpl filmService = new FilmServiceImpl(persistenceUtil);
final Film film = filmService.filmById(1);
final List<Actor> actorsOfFilm = actorService.getActorsOfFilm(film);
for (Actor actor : actorsOfFilm) {
System.out.println(actor.getFirstname());
}
}
}

所以第一个测试抛出了一个 LazyInitException,这很好。当我得到电影的 Actor 时,EntityManager 已经关闭了。

关于第二个测试,即名为“testGetActorsOfFilm”的测试。正如所见,它从数据库传递并打印控制台中的 Actor。这是通过 entityManager.merge(film);< 完成的据我了解。我们传递一个独立的电影对象,将其合并到 PersistenceContext 中,然后在实现中获取电影的 Actor 。

但是,我想问的是,为什么这个测试失败:

@Test
public void testGetActorsOfFilm() {
final Film film = new Film();
film.setId(1);
final List<Actor> actorsOfFilm = actorService.getActorsOfFilm(film);
for (Actor actor : actorsOfFilm) {
System.out.println(actor.getFirstname());
}
}

我的理解是,我正在创建一个 ID 为 1 的 Film 对象并将其传递给服务方法。那么entityManager.merge(film) 应该从数据库加载电影并将其同步到持久性上下文吗?然而我所看到的是:

java.lang.NullPointerException
at java.util.ArrayList.addAll(ArrayList.java:559)
at biz.tugay.learningjpa.service.ActorServiceImpl.getActorsOfFilm(ActorServiceImpl.java:57)

所以我很困惑,我在第一种情况和第二种情况下拥有的独立实体有什么区别?合并不只适用于 id 吗?

最佳答案

merge(film) 从数据库中获取具有给定影片 ID 的影片(我们称之为 managementFilm),从 film 复制所有状态code> 到 ManagedFilm,并返回 ManagedFim。

由于 actors 列表默认为 null,并且该 null 字段被复制到 managementFilm,因此对其进行迭代会引发 NullPointerException。

您不应该使用 merge(),除非您确实打算将分离胶片的状态复制到托管胶片(因此可能通过调用 getActorsOfFilm( ),这样它的名字就会非常糟糕,并且有两个截然不同的职责)。只需传递影片 ID 而不是影片,然后使用 EntityManager.find() 从数据库获取托管影片。

关于java - merge如何避免LazyInitException?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40203841/

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