2011-11-08 1 views
0

하나의 단위 테스트에 OpenEJB가 내장되어 있습니다. 테스트가 작동하지 않습니다. 내가 디버깅 할 때 게으른 가져온 필드가 특이하게 행동했음을 알았습니다.불러 오기 전에 지연된 가져온 필드를 수정할 수 있습니까?

정말 가능합니까? 필드가 이미로드 된 경우, 모든 일반적인 방법으로 진행됩니다

//field == "something from db" 
field = "ahoj"; 
//field == "ahoj" 

그러나 필드가로드되지 않은 경우 : 내가 본 호출 스택에서

//field == null 
field = "ahoj"; 
//field == null 

, 어떤 방법이 있었다는 것을 상단에있는 일부 겹쳐진 레이어, 가장 가능성있는 엔티티 하나를 관리하는 엔티티. Google을 사용해 보았지만 대답이 없습니다.

내 질문은 : 관리되는 엔티티의 가져온 필드를 할당 할 수 없다는 규칙이 있습니까? 비슷한 규칙이 있다면 데이터베이스에서 가져 오지 않고 필드의 값을 변경하는 방법은 무엇입니까?

+0

코드 또는 setters/getters에 표시된대로 필드 액세스를 사용하고 있습니까? –

+0

나는 물건, 현장 출입. 그러나이 필드는 엔티티 클래스의 한 메소드 내에서 수정됩니다. 나는 setter를 사용하고 있지만 다른 이름을 사용하고 있습니다. ('setField()'가 아니고'setSomeValue()'가 아니라 다른 것들 중에서 값을 업데이트해야하지만 그렇지 않습니다.) –

+0

질문을 업데이트하고 Entity 클래스 자체를 보여줄 수 있습니까? –

답변

0

물론 대답은 물론입니다. 하지만 어제 무슨 일이 있었습니까?

문제가 지속성 컨텍스트에 있었고 메서드 이름에있을 수도 있습니다. 입력란에서 입력란이 업데이트되지 않았습니다. 지속성 컨텍스트는 트랜잭션과 바인딩됩니다. 따라서 여러 필드를 업데이트하고 저장해야하는 경우 한 트랜잭션 내에서 모든 작업을 수행해야합니다. 트랜잭션을 시작하고 엔티티에서 setter를 호출하고 엔티티에 대한 액세스를 관리하는 세션 bean에서 update 메소드를 호출해야합니다.

@Basic(fetch=FetchType.LAZY) 
String field; 

@Override 
@TransactionAttribute(TransactionAttributeType.SUPPORTS) 
public String getFiled() { 
    return field; 
} 

@Override 
@TransactionAttribute(TransactionAttributeType.MANDATORY) 
public void setText(String text) { 
    //other code 
    this.field = text; 
    //other code 
} 

getter는 트랜잭션 내에서 호출 될 수도 있고 호출되지 않을 수도 있습니다. 그러나 setter는 기존 트랜잭션 내에서 호출되어야합니다. 동일한 트랜잭션 속성이 세션 빈의 업데이트 메소드에 적용됩니다. 또한 적절한 지속성 컨텍스트에서 객체와 함께 작업 할 수 있도록하기 위해 reattach() 메소드가 필요합니다.

@Stateless 
class AccessBean implements Accessor { 
    @PersistenceContext(unitName = "MyUnit") 
    private EntityManager manager; 

    @TransactionAttribute(TransactionAttributeType.MANDATORY) 
    public TheEntity update(TheEntity e) { 
     e = manager.merge(e); 
     manager.flush(); 

     return e; 
    } 

    @TransactionAttribute(TransactionAttributeType.MANDATORY) 
    public <T> T reattach(T object) { 
     return manager.merge(object); 
    } 
} 

모두 하나의 트랜잭션 내에서 수행되어야합니다.

Context context = new InitialContext(your properties); 
UserTransaction trans = (UserTransaction)context.lookup("java:comp/UserTransaction"); 
//AccessBean ab already injected; 
//TheEntity e already exists 

trans.begin(); //this implicates a new persistent context 
e = da.reattach(e); //critical line 
e.setText("New text"); 
e = da.updateEvent(e); 
trans.commit(); 
TestCase.assertEquals("New text", e.getField()); //yes! 

중요한 라인은 겉으로는 불필요한 라인이지만 그렇지 않습니다. 이 행을 주석 처리하면 엔티티를 분리하거나 다른 영구 컨텍스트에 첨부하여 작업하게됩니다. 그러면 내 질문의 문제인 재미있는 행동을 보게 될 것입니다.

참고 : 또한 명시 적 트랜잭션 내에서 데이터를 가져와야합니다.

trans.begin(); 
e = da.reattach(e); 
String s = e.getField(); 
trans.commit();