Helpex - Trao đổi & giúp đỡ Đăng nhập
317

Về cơ bản, tôi đang tìm kiếm chú thích loại "@Ignore" mà tôi có thể ngăn một trường cụ thể tiếp tục tồn tại. Làm thế nào điều này có thể đạt được?

317 hữu ích 0 bình luận 212k xem chia sẻ
10 trả lời 10
501

@Transient phù hợp với nhu cầu của bạn.

501 hữu ích 5 bình luận chia sẻ
155

Để bỏ qua một trường, hãy chú thích nó bằng @Transientđể nó không được ánh xạ bởi chế độ ngủ đông.

nhưng sau đó jackson sẽ không tuần tự hóa trường khi chuyển đổi sang JSON.

Nếu bạn cần kết hợp JPA với JSON (bỏ qua JPA nhưng vẫn đưa vào Jackson), hãy sử dụng @JsonInclude:

@JsonInclude()
@Transient
private String token;

TIỀN BOA:

Bạn cũng có thể sử dụng JsonInclude.Include.NON_NULL và ẩn các trường trong JSON trong quá trình giải mã khi token == null:

@JsonInclude(JsonInclude.Include.NON_NULL)
@Transient
private String token;
155 hữu ích 5 bình luận chia sẻ
26

Để bỏ qua một trường, hãy chú thích nó bằng @Transientđể nó không được ánh xạ bởi chế độ ngủ đông.
Nguồn: Hibernate Annotations .

26 hữu ích 0 bình luận chia sẻ
19

Câu trả lời này đến hơi muộn, nhưng nó hoàn thành câu trả lời.

Để tránh trường từ một thực thể vẫn tồn tại trong DB, người ta có thể sử dụng một trong hai cơ chế:

@Transient - chú thích JPA đánh dấu một trường là không thể tồn tại

từ khóa tạm thời trong java. Hãy cẩn thận - sử dụng từ khóa này sẽ ngăn trường được sử dụng với bất kỳ cơ chế tuần tự hóa nào từ java. Vì vậy, nếu trường phải được tuần tự hóa, bạn tốt hơn nên chỉ sử dụngchú thích @Transient .

19 hữu ích 2 bình luận chia sẻ
10

Có nhiều giải pháp tùy thuộc vào loại thuộc tính thực thể.

Thuộc tính cơ bản

Hãy xem xét bạn có accountbảng sau :

Cách dễ nhất để bỏ qua trường JPA trong thời gian tồn tại là gì?

Các accountbảng được ánh xạ tới các Accountthực thể như thế này:

@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
}

Các thuộc tính cơ bản của thực được ánh xạ vào các cột bảng, vì vậy tính chất thích id, iban, centslà các thuộc tính cơ bản.

Nhưng dollars, interestCentsinterestDollarsđược tính toán tài sản, vì vậy bạn có chú thích chúng bằng @Transientloại trừ chúng khỏi SELECT, INSERT, UPDATE, và câu lệnh SQL DELETE.

Vì vậy, đối với các thuộc tính cơ bản, bạn cần sử dụng @Transientđể loại trừ việc duy trì một thuộc tính nhất định.

Hiệp hội

Giả sử bạn có các bảng postpost_commentbảng sau:

Cách dễ nhất để bỏ qua trường JPA trong thời gian tồn tại là gì?

Bạn muốn ánh xạ latestCommentliên kết trong Postthực thể với PostCommentthực thể mới nhất đã được thêm vào.

Để làm điều đó, bạn có thể sử dụng @JoinFormulachú thích:

@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
}

Khi tìm nạp Postthực thể, bạn có thể thấy rằng thực thể latestCommentđã được tìm nạp, nhưng nếu bạn muốn sửa đổi nó, thay đổi sẽ bị bỏ qua.

Vì vậy, đối với các liên kết, bạn có thể sử dụng @JoinFormulađể bỏ qua các thao tác ghi trong khi vẫn cho phép đọc liên kết.

@MapsId

Một cách khác để bỏ qua các liên kết đã được ánh xạ bởi mã định danh thực thể là sử dụng @MapsId.

Ví dụ: hãy xem xét mối quan hệ một-một bảng sau:

Cách dễ nhất để bỏ qua trường JPA trong thời gian tồn tại là gì?

Thực PostDetailsthể được ánh xạ như thế này:

@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
}

Lưu ý rằng cả idthuộc tính và postliên kết ánh xạ cùng một cột cơ sở dữ liệu, đó là post_detailscột Khóa chính.

Để loại trừ idthuộc tính, @MapsIdchú thích sẽ cho Hibernate biết rằng postliên kết sẽ quản lý giá trị cột Khóa chính của bảng.

Vì vậy, khi định danh thực thể và một liên kết chia sẻ cùng một cột, bạn có thể sử dụng @MapsIdđể bỏ qua thuộc tính định danh thực thể và thay vào đó sử dụng liên kết.

Sử dụng insertable = false, updatable = false

Một tùy chọn khác là sử dụng insertable = false, updatable = falsecho liên kết mà bạn muốn bỏ qua bởi Hibernate.

Ví dụ: chúng ta có thể ánh xạ liên kết 1-1 trước đó như thế này:

@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();
        }
    }
}

Các thuộc tính insertableupdatablecủa @JoinColumnchú thích sẽ hướng dẫn Hibernate bỏ qua postliên kết vì mã định danh thực thể quản lý post_idcột Khóa chính.

10 hữu ích 3 bình luận chia sẻ
5

Đôi khi bạn muốn:

  1. Nối tiếp một cột
  2. Bỏ qua cột không được duy trì:

Sử dụng @Column(name = "columnName", insertable = false, updatable = false)

Một kịch bản tốt là khi một cột nhất định được tính toán tự động bằng cách sử dụng các giá trị cột khác

5 hữu ích 1 bình luận chia sẻ
3

Để hoàn thành các câu trả lời ở trên, tôi đã gặp trường hợp sử dụng tệp ánh xạ XML trong đó tệp ánh xạ @Transientcũng không transienthoạt động ... Tôi phải đặt thông tin tạm thời vào tệp xml:

<attributes>
(...)
    <transient name="field" />
</attributes>
3 hữu ích 0 bình luận chia sẻ
3

Không có câu trả lời nào ở trên phù hợp với tôi khi sử dụng Hibernate 5.2.10, Jersey 2.25.1 và Jackson 2.8.9. Cuối cùng tôi đã tìm thấy câu trả lời (đại loại là họ tham chiếu đến hibernate4module nhưng nó cũng hoạt động với 5) ở đây . Không có chú thích Json nào hoạt động với @Transient. Rõ ràng Jackson2 đủ 'thông minh' để vui lòng bỏ qua những thứ được đánh dấu @Transienttrừ khi bạn nói rõ ràng rằng không nên làm như vậy. Chìa khóa là thêm mô-đun hibernate5 (mà tôi đang sử dụng để xử lý các chú thích Hibernate khác) và tắt USE_TRANSIENT_ANNOTATIONtính năng này trong Ứng dụng Jersey của tôi:

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

Đây là phần phụ thuộc cho Hibernate5Module:

<dependency>
    <groupId>com.fasterxml.jackson.datatype</groupId>
    <artifactId>jackson-datatype-hibernate5</artifactId>
    <version>2.8.9</version>
</dependency>
3 hữu ích 1 bình luận chia sẻ
1

sử dụng @Transient để làm cho JPA bỏ qua trường.

nhưng! Jackson cũng sẽ không đăng hàng loạt lĩnh vực đó. để giải quyết chỉ cần thêm @JsonProperty

một ví dụ

@Transient
@JsonProperty
private boolean locked;
1 hữu ích 0 bình luận chia sẻ
0

Rõ ràng, bằng cách sử dụng Hibernate5Module, @Transient sẽ không được tuần tự hóa nếu sử dụng ObjectMapper. Loại bỏ sẽ làm cho nó hoạt động.

import javax.persistence.Transient;

import org.junit.Test;

import com.fasterxml.jackson.annotation.JsonInclude.Include;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;

import lombok.Builder;
import lombok.Getter;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;

@Slf4j
public class TransientFieldTest {

    @Test
    public void Print_Json() throws JsonProcessingException {

        ObjectMapper objectEntityMapper = new ObjectMapper();
        //objectEntityMapper.registerModule(new Hibernate5Module());
        objectEntityMapper.setSerializationInclusion(Include.NON_NULL);

        log.info("object: {}", objectEntityMapper.writeValueAsString( //
                SampleTransient.builder()
                               .id("id")
                               .transientField("transientField")
                               .build()));

    }

    @Getter
    @Setter
    @Builder
    private static class SampleTransient {

        private String id;

        @Transient
        private String transientField;

        private String nullField;

    }
}
0 hữu ích 0 bình luận chia sẻ
loading
Không tìm thấy câu trả lời bạn tìm kiếm? Duyệt qua các câu hỏi được gắn thẻ java database hibernate jpa , hoặc hỏi câu hỏi của bạn.

Có thể bạn quan tâm

loading