지속성 동안 JPA 필드를 무시하는 가장 쉬운 방법은 무엇입니까?


281

본질적으로 특정 필드가 유지되는 것을 막을 수있는 "@ 무시"유형 주석을 찾고 있습니다. 이것이 어떻게 달성 될 수 있습니까?

답변:


450

@Transient 당신의 요구를 준수합니다.


20
그러나 Jackson은 JSON으로 변환 할 때 필드를 직렬화하지 않습니다 ... 해결 방법?
MobileMon

그것은 당신의 앱 desing에 달려 있습니다. 엔티티 클래스에 주석을 달면 모든 곳에 적용됩니다. 그러나 엔티티를 사용하는 dao에 주석을 달면 또 다른 이야기입니다. 간단히 말해 : 여러 저장소가있는 경우 DAO를 사용하십시오
Andrii Plotnikov

목록 필드에서는 작동하지 않습니다. 콜렉션 유형 필드의 경우 최대 절전 모드는 실제로 새 중간 테이블을 작성합니다. 그 해결 방법이 있습니까?
zulkarnain shah

@MobileMon 당신은 그것을 해결할 수 있습니다, 내 대답을 확인하십시오 stackoverflow.com/a/41850392/3871754
Kamil Nekanowicz

@MobileMon 데이터베이스와 API 목적으로 동일한 엔터티를 사용하지 않는 것이 좋습니다 (단일 책임).
Jacek Ślimok

127

필드를 무시하려면 필드에 주석을 달아서 @Transient최대 절전 모드로 매핑되지 않습니다.

하지만 잭슨은 직렬화되지 않습니다 JSON으로 변환 할 때 필드.

JPA와 JSON을 혼합해야하는 경우 (JPA에서는 생략했지만 여전히 Jackson에 포함) 다음을 사용하십시오 @JsonInclude.

@JsonInclude()
@Transient
private String token;

팁:

다음 과 같은 경우 JsonInclude.Include.NON_NULL 을 사용하여 역 직렬화 중에 JSON에서 필드를 숨길 수도 있습니다 token == null.

@JsonInclude(JsonInclude.Include.NON_NULL)
@Transient
private String token;

3
JAX-RS 2.0.1 / Jersey 2.25.1 / Jackson 2.8.7을 실행 중이며 해당 스택 @JsonInclude이 필요하지 않습니다. @Transient필드는 여전히 JSON에 포함됩니다. (여전히 내 투표권을 얻었습니다. 기술 자체는 다른 상황에서 매우 유용 할 수 있습니다).
DKroot

2
나는 봄 부팅에 그것을했다
카밀 Nekanowicz에게

안녕하세요, 이것을 사용하려고하는데 @Transient 필드로 직렬화되지 않습니다
Mohammad

@Mohammad @JsonInclude () 주석 추가
Kamil Nekanowicz

Spring Boot 2.1.7에서 이것을 시도했지만 작동하지 않았습니다. 그러나 다른 시나리오에서는 효과가있을 수 있으므로 여전히 투표권을 얻습니다.
Aditya Ekbote '08 년


19

이 답변은 약간 늦었지만 답변을 완료했습니다.

엔티티의 필드가 DB에 유지되는 것을 피하기 위해 두 가지 메커니즘 중 하나를 사용할 수 있습니다.

@Transient- 필드를 지속 불가능으로 표시하는 JPA 주석

자바의 임시 키워드. 이 키워드를 사용하면 필드가 java의 직렬화 메커니즘과 함께 사용되지 않습니다. 따라서 필드를 직렬화해야하는 경우 @Transient 주석만 사용하는 것이 좋습니다.


1
어떻게 get 메소드의 지속성을 무시하고 싶습니까?. 예를 들어 : myjparepository.save ()는 모델을 평소대로 저장하면 myjparepository.find (id)는 원하는 필드를 무시합니까?
xtiger

@xtiger에서는 해당 기능을 보관할 사용자 지정 쿼리를 만들 수 있습니다. 다음 예제의 링크
모 헬레

7

엔티티 속성 유형에 따라 여러 솔루션이 있습니다.

기본 속성

다음 account테이블 이 있다고 가정하십시오 .

계정 테이블

account테이블이 매핑되는 Account이 같은 개체 :

@Entity(name = "Account")
public class Account {

    @Id
    private Long id;

    @ManyToOne
    private User owner;

    private String iban;

    private long cents;

    private double interestRate;

    private Timestamp createdOn;

    @Transient
    private double dollars;

    @Transient
    private long interestCents;

    @Transient
    private double interestDollars;

    @PostLoad
    private void postLoad() {
        this.dollars = cents / 100D;

        long months = createdOn.toLocalDateTime()
            .until(LocalDateTime.now(), ChronoUnit.MONTHS);
        double interestUnrounded = ( ( interestRate / 100D ) * cents * months ) / 12;
        this.interestCents = BigDecimal.valueOf(interestUnrounded)
            .setScale(0, BigDecimal.ROUND_HALF_EVEN).longValue();

        this.interestDollars = interestCents / 100D;
    }

    //Getters and setters omitted for brevity
}

기본 개체의 속성은 속성이 같은 테이블 컬럼에 매핑되는 id, iban, cents기본 속성입니다.

그러나 dollars, interestCents그리고 interestDollars당신이 그들을 주석, 그래서 특성을 계산 @TransientSELECT, INSERT, UPDATE 및 DELETE SQL 문에서 제외 할 수 있습니다.

따라서 기본 속성의 @Transient경우 주어진 속성이 유지되지 않도록 제외하기 위해 사용해야 합니다.

계산 된 엔터티 속성에 대한 자세한 내용은 이 문서를 확인 하십시오 .

협회

다음 postpost_comment테이블 이 있다고 가정합니다 .

post 및 post_comment 테이블

엔터티 의 lastestComment연결을 추가 된 Post최신 PostComment엔터티 에 매핑하려고합니다 .

이를 위해 @JoinFormula주석을 사용할 수 있습니다 .

@Entity(name = "Post")
@Table(name = "post")
public class Post {

    @Id
    private Long id;

    private String title;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinFormula("(" +
        "SELECT pc.id " +
        "FROM post_comment pc " +
        "WHERE pc.post_id = id " +
        "ORDER BY pc.created_on DESC " +
        "LIMIT 1" +
    ")")
    private PostComment latestComment;

    //Getters and setters omitted for brevity
}

페치 할 때 Post엔티티를, 당신은이 것을 볼 수 있습니다 latestComment가져온이지만, 당신이 그것을 수정하려면, 변화는 무시 될 것입니다.

따라서 연결의 @JoinFormula경우 연결 읽기를 허용하면서 쓰기 작업을 무시하는 데 사용할 수 있습니다 .

계산 된 연결에 대한 자세한 내용은 이 문서를 확인 하십시오 .

@MapsId

엔터티 식별자로 이미 매핑 된 연결을 무시하는 또 다른 방법은을 사용하는 것 @MapsId입니다.

예를 들어, 다음의 일대일 테이블 관계를 고려하십시오.

post 및 post_details 테이블

PostDetails엔티티는 다음과 같이 매핑됩니다 :

@Entity(name = "PostDetails")
@Table(name = "post_details")
public class PostDetails {

    @Id
    private Long id;

    @Column(name = "created_on")
    private Date createdOn;

    @Column(name = "created_by")
    private String createdBy;

    @OneToOne(fetch = FetchType.LAZY)
    @MapsId
    private Post post;

    public PostDetails() {}

    public PostDetails(String createdBy) {
        createdOn = new Date();
        this.createdBy = createdBy;
    }

    //Getters and setters omitted for brevity
}

id속성과 post연결 모두 post_details기본 키 열인 동일한 데이터베이스 열을 매핑합니다 .

id속성 을 제외하기 위해 @MapsId어노테이션은 post연관이 테이블 기본 키 열 값을 처리 함을 Hibernate에게 알려 줍니다.

따라서 엔티티 ID와 연관이 동일한 열을 공유하는 @MapsId경우 엔티티 ID 속성을 무시하고 대신 연관을 사용할 수 있습니다.

자세한 내용은 이 기사를@MapsId 확인 하십시오 .

사용 insertable = false, updatable = false

또 다른 옵션은 insertable = false, updatable = false최대 절전 모드에서 무시하려는 연결에 사용하는 것입니다.

예를 들어, 이전의 일대일 연관을 다음과 같이 맵핑 할 수 있습니다.

@Entity(name = "PostDetails")
@Table(name = "post_details")
public class PostDetails {

    @Id
    @Column(name = "post_id")
    private Long id;

    @Column(name = "created_on")
    private Date createdOn;

    @Column(name = "created_by")
    private String createdBy;

    @OneToOne
    @JoinColumn(name = "post_id", insertable = false, updatable = false)
    private Post post;

    //Getters and setters omitted for brevity

    public void setPost(Post post) {
        this.post = post;
        if (post != null) {
            this.id = post.getId();
        }
    }
}

엔티티 식별자가 기본 키 열을 처리하므로 주석 의 insertableupdatable속성은 @JoinColumnHibernate에게 post연결 을 무시하도록 지시 post_id합니다.


id 속성과 사후 연결은 모두 동일한 데이터베이스 열 (post_comment 기본 키 열)을 매핑합니다. postpost_details같이 문맥 과 표의 맥락에서 이것이 맞 습니까?
데이비드

1
그것을 찾아 주셔서 감사합니다. 나는 그것을 고쳤다.
Vlad Mihalcea

3

위의 답변을 완료하려면, 나는 XML 매핑 파일을 사용하는 경우가 있었다 어디 어느 것도 @Transient아니다 transient내가 xml 파일에 과도 정보를 넣어했다 ... 일 :

<attributes>
(...)
    <transient name="field" />
</attributes>

2

위의 답변 중 어느 것도 Hibernate 5.2.10, Jersey 2.25.1 및 Jackson 2.8.9를 사용하여 효과가 없었습니다. 나는 마침내 대답을 찾았습니다 ( 여기 , 그들은 hibernate4module을 참조하지만 5에서도 작동합니다) . Json 주석은 전혀 작동하지 않았습니다 @Transient. 분명히 Jackson2는 @Transient명시 적으로 지시하지 않는 한 표시가있는 것을 친절하게 무시할만큼 '스마트' 합니다. 열쇠는 hibernate5 모듈 (다른 Hibernate 주석을 처리하는 데 사용했던)을 추가하고 USE_TRANSIENT_ANNOTATIONJersey 응용 프로그램에서 기능을 비활성화하는 것입니다.

ObjectMapper jacksonObjectMapper = new ObjectMapper();
Hibernate5Module jacksonHibernateModule = new Hibernate5Module();
jacksonHibernateModule.disable(Hibernate5Module.Feature.USE_TRANSIENT_ANNOTATION);
jacksonObjectMapper.registerModule(jacksonHibernateModule);  

Hibernate5Module의 종속성은 다음과 같습니다.

<dependency>
    <groupId>com.fasterxml.jackson.datatype</groupId>
    <artifactId>jackson-datatype-hibernate5</artifactId>
    <version>2.8.9</version>
</dependency>

위에서 언급 한 다른 방법과 다른 방법을 시도한 후에이 @JsonProperty @JsonInclude @JsonSerialize + @JsonDeserialize mapper.configure(MapperFeature.PROPAGATE_TRANSIENT_MARKER, false));솔루션이 마침내 작동했습니다. 감사!
Aceonline

1

때때로 당신은 :

  1. 열을 직렬화
  2. 열이 지속되지 않도록 무시하십시오.

사용하다 @Column(name = "columnName", insertable = false, updatable = false)

좋은 시나리오는 다른 열 값을 사용하여 특정 열이 자동으로 계산되는 경우입니다.

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