0

これはJPA2(EclipseLink)とJSF2にあります。

エンティティクラスStudentがあります:

@Entity
public class Student implements Serializable {

private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String firstname;
private String lastname;
private int age;

public Student(String firstname, String lastname, int age) {
    this.firstname = firstname;
    this.lastname = lastname;
    this.age = age;
}

public Student() {
}

// accessors and mutators here

}

AbstractFacadeを継承するセッションBeanStudentFacade:

public abstract class AbstractFacade<T> {

private Class<T> entityClass;

public AbstractFacade(Class<T> entityClass) {
    this.entityClass = entityClass;
}

protected abstract EntityManager getEntityManager();

public void create(T entity) {
    getEntityManager().persist(entity);
}

public T edit(T entity) {
    return getEntityManager().merge(entity);
}

public void remove(T entity) {
    getEntityManager().remove(getEntityManager().merge(entity));
}

public T find(Object id) {
    return getEntityManager().find(entityClass, id);
}

// other methods: findAll, findRange, count

}

@Stateless
public class StudentFacade extends AbstractFacade<Student> {

@PersistenceContext(unitName = "jpa2testsPU")
private EntityManager em;

@Override
protected EntityManager getEntityManager() {
    return em;
}

public StudentFacade() {
    super(Student.class);
}

public boolean contains(Student s) {
    return getEntityManager().contains(s);
}

public void testContains() {
    Student s = find(1L);
    boolean isContains = getEntityManager().contains(s);
}

}

これは私のJSFマネージドBeanです:

@ManagedBean
@RequestScoped
public class IndexController {

@EJB
private StudentFacade studentFacade;

/**
 * Creates a new instance of IndexController
 */
public IndexController() {
}

public String test() {
    Student s = new Student("John", "Doe", 20);
    studentFacade.create(s);

    Student s1 = studentFacade.find(1L); // This works because table only has 1 record
    boolean isContains = studentFacade.contains(s);

    return null;
}
}

管理対象Beanからtest()を実行すると、isContainsはfalseになります。ただし、StudentFacadeのtestContains()が呼び出されると、isContainsはtrueになります。どうしてこれなの?

4

1 に答える 1

1

StudentFacade はステートレス セッション Bean (SSB) です。そのインスタンス変数の内容は、メソッド呼び出し間で保持される保証はありません (参照)。これは、メソッド呼び出しごとに EntityManager の異なるインスタンスを作成するようなものです。

マネージド Bean からテストを実行すると、SSB で 2 つの異なるメソッドが呼び出されます。したがって、呼び出しごとに異なる EntityManager インスタンスが作成されます。2 つ目のインスタンスには、まだロードされていないので Student インスタンスが含まれていません。

しかし、SSB 自体のメソッド内でテストを実行すると、同じ EntityManager がメソッド全体のスコープに使用されるため、contains() の呼び出しは true を返します。

于 2013-03-21T02:26:00.617 に答える