2013-09-29 2 views
0

REST 컨트롤러에서 Customer 오브젝트 아래에서 삭제하려고 할 때 "분리 된 인스턴스 제거" 예외.삭제시 detached 인스턴스 오류 제거

LOG :

org.springframework.dao.InvalidDataAccessApiUsageException: Removing a detached instance com.test.model.Customer#1750; nested exception is java.lang.IllegalArgumentException: Removing a detached instance com.test.model.Customer#1750 

도메인 :

@Entity 
public class Customer{ 

@Id 
private Long id; 

@OneToOne(fetch = FetchType.EAGER) 
@JoinColumn(name="COUNTRY_ID", nullable=false) 
private Country country; 

// other stuff with getters/setters 

} 

REST 컨트롤러 :

@Controller 
@RequestMapping("/shop/services/customers") 
public class CustomerRESTController { 

    /** 
    * Deletes a customer 
    */ 
    @RequestMapping(value="/{id}", method=RequestMethod.DELETE) 
    @ResponseStatus(HttpStatus.NO_CONTENT) 
    public void deleteCustomer(@PathVariable Long id, HttpServletRequest request, HttpServletResponse response) throws Exception { 

     Customer customer = customerService.getById(id); 
     if(customer != null){ 
      customerService.delete(customer); 
     }else{ 
      response.sendError(503, "No Customer found for ID : " + id); 
     } 
    } 

    // other stuff 
} 

I 얻고 고객 그러나 데이터베이스의 개체는 여전히 동면하는 동면 상태입니다. 제안 사항 ??

+1

'customerService' 코드를 표시 할 수 있습니까? –

+0

물론 ....여기있다 :'@Service ("CustomerService를") 공용 클래스 CustomerServiceImpl { \t 공공 고객 getById (긴 ID) { \t \t \t 반환 customerDAO.getById (ID); \t \t \t} } –

답변

2

엔티티가 현재 세션 (또는 더 나은 트랜잭션)에서 분리됩니다. 당신이 봄 안에 있기 때문에 당신은 거래 행동을 위해 Java Transaction Service (JTS)을 사용하는 것이 일반적입니다. 그런 Hibernate는 (JPA 솔루션으로 사용될 때와 마찬가지로) 커밋 후에 자동적으로 영속 컨텍스트를 지 웁니다.

일반적으로 Hibernate는 세션의 영속 컨텍스트를 지우지 않으므로 엔티티는 커밋 후에 정상적으로 분리되지 않습니다. (분산 환경에서는 안전하지 않지만 Hibernate 만 사용하여 데이터베이스에 액세스하고 Ehcache와 같은 분산 캐시를 사용할 경우 제외).

해결책 : session.merge(object) 현재 세션 개체의 지속성 컨텍스트에 엔티티를 다시 연결하십시오.

실제로는 병합이 아니며 다시 연결됩니다. Hibernate가 엔티티의 현재 상태가 적절한 데이터베이스 캐시를 반영하고 있는지 확신 할 수없는 경우 엔티티를 다시로드합니다. (그리고 버전 속성 (@Version)의 선물의 경우 특별한 행동을 추가하십시오).

복사 같은 식별자의 영구 물체 상에 지정된 오브젝트의 상태 : 하이버 네이트의 문서 상태 그런데

. 현재 세션과 연관된 지속 인스턴스가 없으면로드됩니다.

업데이트

코드를 본 후이 트랜잭션 문제처럼 보인다. customerService.getById (id) 및 customerService.delete (customer) 서비스 호출로 인해 트랜잭션 커밋이 발생하는지 확인하십시오. 동일한 트랜잭션 내에서 둘 다 배치해야합니다. 또한 문제를 해결할 당신은 또한 할 수

한 가지입니다

public void deleteCustomer(@PathVariable Long id, HttpServletRequest request, HttpServletResponse response) throws Exception { 
    boolean wasDeleted = customerService.delete(id); 
    if(!wasDeleted) 
     response.sendError(503, "No Customer found for ID : " + id); 
    } 
} 

두 서비스 호출이 필요하지 않습니다 이쪽으로. 하이 레벨 서비스 호출에서 하이버 네이트 엔티티를 사용하는 것은 사실 전형적이지 않습니다 (그러나 아키텍처에 따라 다를 수 있습니다. 스프링을 많이 사용하지는 않습니다).

+0

고마워! ... 귀하의 제안이 작동 중입니다. 컨트롤러에서 단일 서비스 메소드로 논리를 검색 및 삭제했습니다. –