2013-01-03 2 views
4

나는 최대 절전 4와 3을 사용한다.json에 대한 최대 절전 엔터티

나는 두 개의 엔터티를 가지고있다.

@Entity 
@Table(name = "author") 
public class Author implements Serializable { 

    public Author() { 
    } 

    private static final long serialVersionUID = 1L; 

    @Id 
    @GeneratedValue(strategy = GenerationType.IDENTITY) 
    private int id; 
    private String name; 

    @OneToMany(mappedBy = "author", cascade = CascadeType.ALL, orphanRemoval = true) 
    private Set<Book> books = new HashSet<Book>(); 


    public int getId() { 
     return id; 
    } 
    public void setId(int id) { 
     this.id = id; 
    } 
    public String getName() { 
     return name; 
    } 
    public void setName(String name) { 
     this.name = name; 
    } 

    public Set<Book> getBooks() { 
     return books; 
    } 
    public void setBooks(Set<Book> books) { 
     this.books = books; 
    } 

    public void addBook(Book book) { 
     book.setAuthor(this); 
     getBooks().add(book); 
    } 

    public void removeBook(Book book) { 
     getBooks().remove(book);   
    } 

} 

와 JSON은 pom.xml 파일

<dependency> 
      <groupId>com.fasterxml.jackson.core</groupId> 
      <artifactId>jackson-core</artifactId> 
      <version>2.1.2</version> 
     </dependency> 


     <dependency> 
      <groupId>com.fasterxml.jackson.datatype</groupId> 
      <artifactId>jackson-datatype-hibernate4</artifactId> 
      <version>2.1.2</version> 
     </dependency> 

내 루트 컨텍스트가 여기에 달려

@Entity 
@Table(name = "book") 
public class Book implements Serializable { 

    public Book() { 
    } 

    private static final long serialVersionUID = 1L; 

    @Id 
    @GeneratedValue(strategy = GenerationType.IDENTITY) 
    private int id; 

    @ManyToOne() 
    @JoinColumn(name = "author_id") 
    private Author author; 

    private String name; 
    private int pages; 

    @Version 
    @Column(name = "VERSION") 
    private int version; 

    public int getId() { 
     return id; 
    } 

    public void setId(int id) { 
     this.id = id; 
    } 

    public Author getAuthor() { 
     return author; 
    } 

    public void setAuthor(Author author) { 
     this.author = author; 
    } 

    public String getName() { 
     return name; 
    } 

    public void setName(String name) { 
     this.name = name; 
    } 

    public int getPages() { 
     return pages; 
    } 

    public void setPages(int pages) { 
     this.pages = pages; 
    } 

    public int getVersion() { 
     return version; 
    } 

    public void setVersion(int version) { 
     this.version = version; 
    } 


} 

및 저자 엔티티 도서 엔티티 -

<!-- Root Context: defines shared resources visible to all other web components --> 
    <context:annotation-config/> 

    <context:component-scan base-package="org.jar.libs.dao" /> 
    <context:component-scan base-package="org.jar.libs.service" /> 

    <tx:annotation-driven transaction-manager="transactionManager" /> 

    <bean id="jspViewResolver" 
     class="org.springframework.web.servlet.view.InternalResourceViewResolver"> 
     <property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/> 
     <property name="prefix" value="/WEB-INF/views/"/> 
     <property name="suffix" value=".jsp"/> 
    </bean> 

    <bean id="dataSource" 
     class="org.springframework.jdbc.datasource.DriverManagerDataSource" 
     p:driverClassName="com.mysql.jdbc.Driver" p:url="jdbc:mysql://localhost:3306/hibernate" 
     p:username="root" p:password="root" /> 

    <bean id="sessionFactory" 
     class="org.springframework.orm.hibernate4.LocalSessionFactoryBean"> 
     <property name="dataSource" ref="dataSource" /> 
     <property name="annotatedClasses"> 
      <list> 
       <value>org.jar.libs.domain.Book</value> 
       <value>org.jar.libs.domain.Author</value> 
      </list> 
     </property> 
     <property name="hibernateProperties"> 
      <props> 
       <prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop> 
       <prop key="hibernate.show_sql">true</prop> 
       <prop key="hibernate.hbm2ddl.auto">update</prop> 
      </props> 
     </property> 
    </bean> 

    <bean id="transactionManager" 
     class="org.springframework.orm.hibernate4.HibernateTransactionManager"> 
     <property name="sessionFactory" ref="sessionFactory" /> 
    </bean> 

</beans> 

... 서블릿-context.xml에

<!-- Enables the Spring MVC @Controller programming model --> 
    <annotation-driven /> 

    <!-- Handles HTTP GET requests for /resources/** by efficiently serving up static resources in the ${webappRoot}/resources directory --> 
    <resources mapping="/resources/**" location="/resources/" /> 

    <!-- Resolves views selected for rendering by @Controllers to .jsp resources in the /WEB-INF/views directory --> 
    <beans:bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> 
     <beans:property name="prefix" value="/WEB-INF/views/" /> 
     <beans:property name="suffix" value=".jsp" /> 
    </beans:bean> 

    <context:component-scan base-package="org.jar.libs.controller" /> 

컨트롤러. 내 DAO에서

@Controller 
@RequestMapping (value = "books/rest") 
public class BookController { 

    @Autowired 
    private BookService bookService; 

    // logger 
    private static final Logger logger = LoggerFactory.getLogger(BookController.class); 


    @SuppressWarnings("unchecked") 
    @RequestMapping(method = RequestMethod.GET) 
    public @ResponseBody List<Book> getBook() { 


     List<Book> res = bookService.findAll(); 
     return res; 


    } 

} 

findall은이 : 디버그

public List<Book> findAll() { 
     Session session = sessionFactory.getCurrentSession(); 
     List<Book> result = (List<Book>) session.createQuery("select c from Book c").list(); 
     return result; 
    } 

는 그 방법 리턴 2 개 기록을 볼 수 있지만 봄은 JSON으로 결과를 변환 406 HTTP 오류를 반환 할 수 없습니다. 뭐가 문제 야?

디버그에서 볼 수있는 이미지를 첨부합니다. - http://tinypic.com/view.php?pic=35kvi9i&s=6

+0

'LazyInitialization' 예외가 발생합니까? –

+0

번호. 크롬 디버그에서 500 Internal Server Error를보고, SpringToolSuite 콘솔에서 예외를 볼 수 없습니다. – Benjamin

+0

어떤 버전의 Spring을 사용하고 있습니까? 3.2 이하를 사용하는 경우 JSON의 내용이 달라집니다. 이 [질문] (http://stackoverflow.com/a/14102773/1037210)에서 언급 한 것과 같은 문제가 발생합니까? 406 HTTP 오류는 서버가 리턴 한 자원을 승인 할 수 없음을의 L합니다. – Lion

답변

4

일반적으로 트랜잭션에서 관계 객체를 반환하는 엔티티 클래스의 getter 메소드를 호출하면 LazyInitializationException을 얻게됩니다.

엔티티 클래스 개체 (쿼리에서 검색 한)를 거래에서 json 으로 변환하는 경우 문제가 발생할 수 있습니다.

동일한 문제가 있었는데, 최대 절전 모드로 검색 한 엔티티 개체를 컨트롤러의 json으로 변환했습니다. 컨트롤러가 트랜잭션 (서비스 계층의 트랜잭션)에서 json으로 변환하는 동안 엔티티 클래스 객체의 getter 메소드가 호출되었고 LazyInitializationException이되었습니다. json으로의 객체 변환을 방해 한 응답이 반환되지 않았습니다.

내 솔루션이 시도 :

다른 제안으로
@SuppressWarnings("unchecked") 
@RequestMapping(method = RequestMethod.GET) 
public @ResponseBody List<Book> getBook() { 
    List<Book> res = bookService.findAll(); 
    for(Book book : res) { 
     book.getAuthor().setBooks(null); 
    } 
    return res; 
} 
+0

그것은 작동합니다. 벌금. 하지만 지금은 "setter 메서드 (null);"라고 불러야합니다. – Benjamin

+0

그것을 피하는 방법? (관계 객체에 대해 null을 설정하십시오.) – Benjamin

+0

예, 관계 객체에 대해 null을 설정해야하지만 위와 같이'Set'의 경우'Set'에 대해 수행했습니다. 다른 방법은 빈 매핑을 사용하는 것입니다. –

0

가로 변경하여 대신 컨트롤러 시도에서 또한

<dependency> 
<groupId>org.codehaus.jackson</groupId> 
<artifactId>jackson-mapper-asl</artifactId> 
<version>1.9.9</version> 
</dependency> 

<dependency> 
<groupId>org.codehaus.jackson</groupId> 
<artifactId>jackson-core-asl</artifactId> 
<version>1.9.9</version> 
</dependency> 

을 두 잭슨 아티팩트를 사용해보십시오 -

@SuppressWarnings("unchecked") 
@RequestMapping(method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE) 
public @ResponseBody List<Book> getBook() { 

마지막으로, 당신의 뷰가 JSON 요청을하고 있는지 확인하십시오.

+0

감사합니다,하지만이 방법은 효과가 없습니다. 나는 그것을 테스트하기 위해 컬을 사용한다. 그건 내 요청이야 - C : \> curl.exe -i -H "accept : application/json"http : // localhost : 8080/libs/books/rest/.. – Benjamin

1


, 난 정말 당신이 JSON의 직렬화하려고 (또는 실제로 직렬화 수행) 최대 절전 모드 엔티티를 조언하지 않을 것입니다.
가져온 엔티티는 실제로 "프록시 화 된"객체입니다 (Hibernate는 ASM, CGLIB 및 기타 "동적 프록시"프레임 워크를 사용함).
예를 들어, 콜렉션이 [지연 시간]으로 초기화 될 수있는 [PersistenceBags]로 바뀌고 예외가 최대 절전 모드로 전환됩니다 (1).

하지만 문제는 내가이 당신이 "boillerplate"코드를 작성 좋아 들리 겠지만 알고 최대 절전 모드 custom type
를 직렬화하려고 할 때이 문제를 볼 수 있습니다, 거기서 멈추지 않습니다하지만 당신은 DTO들 코딩 끝낼 수 있습니다 - 데이터 전송 객체 소요됩니다 엔티티는 DAL에서 반환하고 직렬화 할 수있는 객체로 변환합니다.

엔티티와 DTO 간의 직렬화 개발을 쉽게하기 위해 도저와 같은 프레임 워크를 사용할 수 있습니다.

-1

필드를 직렬화하지 않으려면 @com.fasterxml.jackson.annotation.JsonIgnore 주석을 사용할 수 있습니다. 따라서 해당 필드의 getter는 호출되지 않습니다.

@JsonIgnore 
@OneToMany(mappedBy = "author", cascade = CascadeType.ALL, orphanRemoval = true) 
private Set<Book> books = new HashSet<Book>(); 
관련 문제