2013-03-21 6 views
0

이것은 JPA2 (EclipseLink) 및 JSF2에 있습니다.왜 entityManager.contains가 다른 결과를 반환합니까?

@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 

} 

세션 빈 StudentFacade AbstractFacade 상속 :

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가 관리하는 빈 :

@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에서 isContains는 false입니다. 그러나 StudentFacade의 testContains()가 호출되면 isContains가 true입니다. 왜 이런거야?

+0

StudentFacade.contains()의 구현을 표시 할 수 있습니까? StudentFacade.containsStudent()는 포함하지만 contains()는 표시되지 않습니다. 잘못 되었습니까? –

+0

예. 오타가 있습니다. – Cam

답변

1

StudentFacade는 SSB (Stateless Session Bean)입니다. 인스턴스 변수의 내용은 메서드 호출 (reference)에서 보존되지 않을 수도 있습니다. 그것은 각각의 메소드 호출을 위해 생성 된 EntityManager의 다른 인스턴스를 가지는 것과 같습니다.

관리 빈에서 테스트를 실행하면 SSB에서 두 개의 다른 메소드를 호출하므로 각 호출에 대해 다른 EntityManager 인스턴스가 작성되고로드되지 않았으므로 두 번째 인스턴스에는 Student 인스턴스가 포함되지 않습니다. 아직.

그러나 SSB 자체의 메서드 내에서 테스트를 실행하면 동일한 EntityManager가 전체 메서드의 범위에 사용되므로 contains()를 호출하면 true가 반환됩니다.

+0

어노테이션 @PersistenceUnit을 통한 주입 때문에 다른 EntityManager 인스턴스가 반환되었는지 궁금합니다. 필자가 한 또 다른 테스트가있다. EntityManager를 JSF 관리 빈에 노출하고 entityManager.persist를 호출하면 TransactionRequiredException이 발생한다. 이것은 인젝션이 SSB 컨텍스트와 JSF 관리 빈 컨텍스트에서 다르게 해결되었음을 보여줍니다. – Cam

+0

JSF @ManagedBean이 관리되지 않습니다. 1. ManagedBean을 @Starteless와 같은 EJB로 만든 경우에만 @PersistenceContext EntityManager를 삽입 할 수 있습니다. 2. @Resource UserTransaction과 함께 @PersistenceUnit EntityManagerFactory를 삽입 할 수 있습니다. –

관련 문제