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

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

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

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

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

궁금하다 :

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


답변

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


답변

JPA 사양에 따르면 :

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

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


답변

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

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


답변

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

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


답변

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

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

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


답변

우리가 지속성에 대해서만 이야기한다면, 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역 직렬화 중에 예기치 않은 결과가 발생할 수 있습니다 .


답변

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

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

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

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