JPA 엔티티가 언제 그리고 왜 직렬화 가능 인터페이스를 구현해야합니까?


151

질문은 제목에 있습니다. 아래에서 나는 내 생각과 결과 중 일부를 설명했습니다.

매우 간단한 도메인 모델 (관계가없는 3 개의 테이블)이 있었을 때 모든 엔티티가 Serializable을 구현하지 않았습니다.

그러나 도메인 모델이 더 복잡해지면 RuntimeException이 발생하여 엔티티 중 하나가 Serializable을 구현하지 않았다고 말했습니다.

JPA 구현으로 Hibernate를 사용합니다.

궁금하다 :

  1. 공급 업체별 요구 사항 / 동작입니까?
  2. 직렬화 가능 엔터티는 어떻게됩니까? 저장 또는 전송을 위해 직렬화해야합니까?
  3. 어느 순간에 엔티티를 직렬화해야합니까?

답변:


59

이것은 보통 HQL과 기본 SQL 쿼리를 혼합 한 경우에 발생합니다. HQL에서 Hibernate는 전달하는 타입을 DB가 이해하는 모든 것에 매핑합니다. 원시 SQL을 실행할 때는 맵핑을 직접 수행해야합니다. 그렇지 않은 경우 기본 맵핑은 매개 변수를 직렬화하여 데이터베이스로 전송하는 것입니다 (이해하기를 희망 함).


이것은 "어쩌면 어떻게"왜 그런지 설명하지 않습니다. Bozho에서 아래 답변을보십시오
chrips

직렬화 가능한 인터페이스를 구현하지 않고 엔티티가 DB에 저장 될 것입니까?
Hanumantha_3048092

@ Hanumantha_3048092 예. 엔터티 매핑 Serializable은 서로 다른 두 가지 개념입니다.
Aaron Digulla

@AaronDigulla 예제 또는 의사 코드로 설명해 주시겠습니까?
sdindiver

110

JPA 사양에 따르면 :

엔티티 인스턴스가 분리 된 객체로서 값으로 전달되는 경우 (예 : 원격 인터페이스를 통해) 엔티티 클래스는 Serializable 인터페이스를 구현해야합니다.

"JSR 220 : Enterprise JavaBeansTM, 버전 3.0 Java Persistence API 버전 3.0, 최종 릴리스 2006 년 5 월 2 일"


14
(+1) 스펙을 보는 것은 항상 유익합니다
Bozho

20
나는 이것이 왜 그렇게 많은 투표를했는지 알지 못한다. OP는 모델이 더 단순했을 때 필요하지 않았다고 말합니다. Java 직렬화를 통해 원격으로 오브젝트를 전송하려면 복잡성에 관계없이 항상 오브젝트를 직렬화 할 수 있어야합니다. 분명히 이것은 OP의 사용 사례가 아닙니다.
Robin

나는 최대 절전 모드에 대해 잘 모르겠지만 다른 JPA 공급자와 함께 공급자가 엔티티 (객체)의 사본을 만들어야하는 작업이 있습니다. Serializable그것으로 도움이 될 수 있으며, 지속성의 맥락 Cloneable에서 예를 들어 보다 더 일관성이 있습니다.
JimmyB

이 답변은 정보 덤프 일 뿐이며 그 이유를 이해하는 데 전혀 도움이되지 않습니다.
chrips

59

Serializable무선으로 전송 (다른 표현으로 직렬화)하고 http 세션 (서블릿 컨테이너에 의해 하드 디스크로 직렬화 됨)에 저장해야하는 경우 엔티티가 필요합니다.

지속성을 위해 Serializable최소한 최대 절전 모드에서는 필요하지 않습니다. 그러나 그것들을 만드는 것이 가장 좋습니다 Serializable.


2
잘 모르겠습니다. 내 엔터티가 암시 적으로 어딘가로 전송되고있을 것입니다. 나는 최대 절전 모드 + 스프링 + JSF와 Tomcat을 사용합니다. 이 체인 어디에서 전송이 가능합니까?
로마

예를 들어 @Roman은 현재 사용자 (엔티티 일 수 있음)와 모든 관련 엔터티가 세션에서 종료 될 수 있으며 Bozho가 말한 것처럼 서블릿 컨테이너에 의해 디스크로 직렬화 될 수 있습니다.
OrangeDog

이것은 "왜 그리고 언제"최고의 답변입니다! 명확한! 감사합니다
chrips

13

@JoinColumn 주석을 사용하는 동안 최대 절전 모드 문서 에 따르면 :

라는 이름의 매개 변수가 하나 더 referencedColumnName있습니다. 이 매개 변수는 조인에 사용될 대상 엔티티의 열을 선언합니다. referencedColumnName기본 키가 아닌 열에 사용하는 경우 관련 클래스는이어야 Serializable합니다.


8

JSR-317 사양을 참조한 Conor의 훌륭한 답변을 보완합니다. 일반적으로 EAR 프로젝트는 EJB가 원격 인터페이스를 통해 노출 된 EJB 모듈로 구성됩니다. 이 경우 엔티티 Bean이 원격 EJB에서 집계되고 네트워크를 통해 유선으로 작성되므로 직렬화 가능해야합니다.

CDI가없는 JEE6 war 프로젝트 : 직렬화 할 수없는 JPA 엔티티가 지원하는 EJB 라이트를 포함 할 수 있습니다.

CDI가있는 JEE6 war 프로젝트 : 세션, 응용 프로그램 또는 대화 범위를 사용하는 Bean은 직렬화 가능해야하지만 요청 범위를 사용하는 Bean은 직렬화 할 필요는 없습니다. 따라서 기본 JPA 엔티티 bean (있는 경우)은 동일한 의미를 따릅니다.


7

우리가 지속성에 대해서만 이야기한다면, Serializable필요하지는 않지만 엔티티를 만드는 것이 가장 좋습니다 Serializable.

우리가 노출되는 경우 domain/ entities직접 사용하는 대신, 프리젠 테이션 레이어에 노출 객체 DTO우리가 구현해야하는 경우 Serializable. 이러한 도메인 개체는 HTTPSession캐싱 / 최적화 목적으로 저장할 수 있습니다 . http-session은 직렬화 또는 클러스터 될 수 있습니다. 또한 JVM인스턴스 간 데이터 전송에도 필요합니다 .

DTO지속성 계층과 서비스 계층을 분리 하는 데 사용 하는 경우 도메인 개체 Serializable가 비생산적이며 " encapsulation"을 위반하는 것으로 표시합니다 . 그런 다음 안티 패턴이됩니다.

복합 식별자

기본 키 클래스는 직렬화 가능해야합니다.

POJO 모델

엔티티 인스턴스를 분리 된 오브젝트로 원격으로 사용하려면 엔티티 클래스가 Serializable인터페이스 를 구현해야합니다 .

캐시
또한 clustered두 번째 수준 cache을 구현하는 경우 엔터티는이어야합니다 serializable. 식별자는 SerializableJPA 요구 사항이기 때문에 identifier2 단계 캐시 항목의 키로 사용될 수 있기 때문입니다 .

엔터티를 직렬화 할 때는 serialVersionUID개인 액세스 수정자를 명시 적 으로 제공해야합니다 . 경우 때문에 serializable클래스가 명시 적으로 선언하지 않는 serialVersionUID한 다음 직렬화 런타임은 기본 계산합니다 serialVersionUID자바 (TM) 객체 직렬화 사양에 설명 된 바와 같이, 클래스의 다양한 측면을 기준으로 그 클래스의 값입니다. 기본 serialVersionUID계산은 컴파일러 구현에 따라 달라질 수있는 클래스 세부 사항에 매우 민감하므로 InvalidClassExceptions역 직렬화 중에 예기치 않은 결과가 발생할 수 있습니다 .


6

귀하의 문제는 주석이없는 복잡한 유형 (클래스)의 필드를 갖는 것과 관련이 있다고 생각합니다. 이러한 경우 기본 처리는 객체를 직렬화 된 형태로 데이터베이스에 저장합니다 (아마도 의도하지 않은 작업). 예 :

Class CustomerData {
    int getAge();
    void setAge(int age);
}

@Entity
Class Customer {
  CustomerData getCustomerData();
  void setCustomerData(CustomerData data)
}

위의 경우 CustomerData는 데이터베이스의 직렬화 된 형식으로 바이트 배열 필드에 저장됩니다.


5

JPA 사양

JPA 스펙에 따르면 엔티티는 Serializable하나의 JVM에서 다른 JVM으로 전달되어야하거나 EJB 컨테이너에 의해 패시베이션되어야하는 Stateful Session Bean에서 엔티티를 사용하는 경우에만 구현 해야합니다.

엔티티 인스턴스가 분리 된 객체로서 값으로 전달되는 경우 (예 : 원격 인터페이스를 통해) 엔티티 클래스는 Serializable인터페이스 를 구현해야합니다 .

동면

최대 절전 모드에서는 엔터티 속성이 Serializable이지만 엔터티 자체는 아닙니다.

그러나 JPA 사양을 구현하면 Serializable엔터티 와 관련된 모든 JPA 요구 사항 이 최대 절전 모드에도 적용됩니다.

수코양이

에 따르면 톰캣 documantationHttpSession속성도 있어야합니다 Serializable:

Apache Tomcat이 정상적으로 종료되고 다시 시작될 때마다 또는 응용 프로그램 재로드가 트리거 될 때마다 표준 Manager 구현은 현재 활성화 된 모든 세션을 pathname 속성을 통해 위치한 디스크 파일로 직렬화하려고 시도합니다. 그런 다음 응용 프로그램 다시로드가 완료되면 저장된 모든 세션이 역 직렬화되고 (평균 시간이 만료되지 않은 경우) 활성화됩니다.

세션 속성의 상태를 성공적으로 복원하려면 이러한 모든 속성은 반드시 java.io.Serializable 인터페이스를 구현해야합니다.

따라서 엔티티가에 저장된 경우 HttpSession구현해야합니다 Serializable.


4

직렬화하려면 클래스가 직렬화 가능을 구현해야합니다. 이것은 JPA와 직접 관련이 없으며 JPA 스펙에서는 엔티티를 직렬화 할 필요가 없습니다. Hibernate가 정말로 이것에 대해 불평한다면, 나는 그것이 Hibernate 버그라고 생각하지만, 당신이 직접 또는 간접적으로 엔티티와 다른 것을하고 있다고 가정합니다.


3

참조하시기 바랍니다 http://www.adam-bien.com/roller/abien/entry/do_jpa_entities_have_to을 가 java.io.Serializable을 구현 단순히 JVM-인스턴스 간의 IIOP 또는 JRMP (RMI)를 통해 데이터를 transfering 필요 말한다. 순수한 웹 응용 프로그램의 경우 도메인 개체가 캐싱 / 최적화 목적으로 HTTPSession에 저장되는 경우가 있습니다. http- 세션을 직렬화 (패시베이션)하거나 클러스터 할 수 있습니다. 두 경우 모두 모든 컨텐츠는 직렬화 가능해야합니다.


1

postman, ajax 또는 angular js 등을 사용하는 원격 적중은 Jackson fasterxml에서 StackOverflow 예외로 반복주기가 발생할 수 있으므로 직렬 변환기를 사용하는 것이 좋습니다.


1
  1. 어느 순간에 엔티티를 직렬화해야합니까?

디스크 @Cacheable저장소를 사용하여 ehcache를 두 번째 레벨 캐시로 구현하려면 (즉 , 엔티티 또는 저장소 / 서비스 방법에 주석 사용 ) 직렬화가 필요합니다. 그렇지 않으면 캐시가 NotSerializableException엔티티를 디스크 캐시에 쓰는 데 실패합니다 ( ).


0

또한 잘못 입력 된 ID를 두 번째 매개 변수로 em.find ()와 같은 것으로 전달할 때 (예 : ID가 아닌 엔티티 자체를 전달할 때) 발생하는 오류입니다. 실제로 JPA 엔티티를 직렬화 가능하게 선언 할 필요는 없습니다. aman에서 설명한 것처럼 referenceColumnName을 사용하지 않는 한 실제로 필요하지 않습니다.


0

JPA 엔티티가 원격 EJB 조작에 의해 매개 변수 또는 리턴 값으로 사용되는 경우

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.