2010-06-07 8 views
4

Tomcat에 배포 된 J2EE 서버 응용 프로그램에서 작업하고 있습니다. Spring 소스를 MVC 프레임 워크로 사용하고 Hibernate를 ORM 제공자로 사용합니다. 내 개체 모델에는 많은 지연 관계가 있습니다 (종속 개체는 요청시 가져옵니다). 상위 레벨 디자인은 서비스 레벨 메소드가 데이터베이스 조작을 수행하는 몇 가지 DAO 메소드를 호출하는 것과 유사합니다. 서비스 메소드는 Flex UI 또는 예약 된 작업으로 호출됩니다. Flex UI에서 호출 할 때 서비스 메소드는 잘 작동합니다. 즉, DAO 메소드를 사용하여 일부 객체를 가져오고 지연로드 작업까지 수행합니다. 이는 UI 서블릿으로 구성된 OpenSessionInViewFilter를 사용하면 가능합니다.예약 된 작업에서 LazyInitializationException을 해결하는 방법은 무엇입니까?

그러나 동일한 서비스 메소드가 예약 된 작업으로 호출되면 LazyInitializationException이 발생합니다. OpenSessionInViewFilter를 구성 할 수 없습니다. 서블릿이나 UI 요청이 연관되어 있지 않기 때문입니다.

서비스 메서드가 트랜잭션을 시작하고 모든 DAO 메서드가 트랜잭션이 활성 상태로 유지되고 최대 절전 모드 세션을 사용할 수 있도록 동일한 예약 트랜잭션에 참여하도록 예약 된 작업 메서드 주위에 트랜잭션을 구성하려고했습니다. 그러나 그것은 효과가 없습니다.

누구나 그런 구성을 사용할 수 있었는지 제안하십시오. 필요하다면, 나는 Hibernate 구성과 로그 메시지를 게시 할 수있다.

도움을 주셔서 감사합니다. Shreerang

+0

은 당신이 주위에 거래를 포장하는 방법을 게시 할 수 없습니다 : 여기 TransactionTemplate 참조하시기 바랍니다 스프링 소스 문서에 대한 자세한 내용은

 transactionTemplate.execute(new TransactionCallbackWithoutResult() { protected void doInTransactionWithoutResult(TransactionStatus status) { // Invoke the real method inside transaction context doWork(); } }); 

예정된 직업? 어떤 부분이 작동하지 않는가 - 트랜잭션을 열지 않거나 거래가 너무 일찍 종료 되었습니까? – Rachel

+0

귀하의 의견에 대답하기 위해, 나는 point-cut 표현식을 사용하여 자체 트랜잭션의 내부에 스케줄 된 작업 메소드를 래핑하려고했습니다. 그러나 point-cut은 실행을 시작할 때 실제로 내 메서드를 선택하지 않았으므로 트랜잭션이 전혀 시작되지 않았습니다. – Shreerang

답변

3

마지막으로 스프링 트랜잭션 참조 자료를 읽은 후 문제를 해결할 수있었습니다. 이전에 예약 된 jon을 트랜잭션 내에서 실행하기 위해 포인트 컷 식을 작성하려고했습니다. 그러나 포인트 컷은 OR (||)을 사용하고 있었고 어떻게 든 실행을 시작할 때 내 방법을 선택하지 않았습니다. 따라서 거래는 결코 공개되지 않았습니다. (나는 이미 DAO 방법에 대한 작업 포인트 컷식이 있고 그 일정에 내 스케줄 된 방법을 추가하려고했습니다.)

그런 다음 프로그래밍 방식으로 내 문제를 해결 한 트랜잭션을 열 수있는 방법을 발견했습니다.다른 사람의 이익을 위해, 여기를 수행하는 코드는 다음과 같습니다 http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/transaction.html#transaction-programmatic

+0

'나는 커밋 할 수 없습니다. 트랜잭션은 rollbackOnly' 예외입니다. 이 문제를 어떻게 해결할 수 있습니까? –

0

OpenSessionInViewFilter

는 너무 많이에 의존 좋지 않아, 해킹의 비트 어쨌든입니다.

더 나은 일반적인 해결책은 데이터가 지연없이가 아니라 열망하여 가져 오도록 최대 절전 모드 쿼리를 작성하는 것입니다. 이는 fetch joins을 사용한다는 것을 의미합니다.

불가능하거나 실용적인 경우 예약 된 작업은 transaction 안에 전체 작업을 수행 할 수 있습니다. 이것은 끝날 때까지 세션을 열어 두어야합니다.

+0

예, 트랜잭션 내에서 작업을 실행하려고했지만 포인트 - 컷 식으로 작업 할 수 없습니다. 트랜잭션이 시작되지 않았습니다. 그래서 나는이 질문을 올렸다. 하지만 내가 올바른 방향으로 나아가고 있다는 것을 확인해 주셔서 감사합니다. – Shreerang

+0

거래에 대한 인내심, 그것이 올바른 방향입니다. – skaffman

1

OpenSessionInViewFilter 안의 코드는 복잡하지 않습니다. 내 요구에 맞도록 소스를 수정하는 데 성공했습니다. 실제로 필요한 것은 지연로드가 발생하는 스레드입니다.

저는 Quartz를 많은 예약 된 작업에 사용했으며, 컨테이너 관리 트랜잭션과 매우 잘 작동합니다. 코드는 트랜잭션 경계가 내가 필요한 방법을 호출 할 경우 전용 방법을 만드는 것입니다 종료 전에 몇 번에 의지 한 트릭은 게으른 컬렉션로드받을 수 있도록 : 이러한 경우

@Transactional 
private SomeOobj getSomeObj(Long id) { 
    SomeObj o = someObjDao.find(id); 
    o.getLazyCollection().size(); // <- load the collection 
    return o; 
} 

를, 그것은 것 객체가 처음으로 가져올 때 필요한 데이터를 열심히로드하는 것이 좋지만 항상 옵션이 아닌 것은 알고 있습니다. 행운을 빕니다.

관련 문제