Рубрики
Без рубрики

Лучший способ сопоставить необязательный атрибут сущности Java 1.8 с JPA и гибернацией

Автор оригинала: Vlad Mihalcea.

StackOverflow-это нескончаемый источник больших вопросов. На этот раз мы рассмотрим этот вопрос об использовании Java 1.8 Необязательно с JPA и гибернацией .

Java 1.8 представила java.util. Необязательный объект-контейнер, который может содержать или не содержать определенное значение. Объединение Необязательно и потоков очень удобно. Поэтому вы можете захотеть, чтобы некоторые атрибуты сущности, допускающие обнуление, были представлены как Необязательные .

В этой статье мы продемонстрируем, каковы предостережения при использовании Необязательно с атрибутами сущностей и как вы можете их преодолеть.

Давайте предположим, что у нас есть следующая модель сущности:

Сущность Post является корнем в нашей совокупности сущностей. Может быть несколько Комментариев к сообщению(комментариям) связано с Сообщением , и каждый Комментарий к сообщению может иметь Приложение . Поскольку Вложение не является обязательным, имеет смысл использовать для него Необязательный

Файл java.util. Необязательно не реализует Сериализуемый интерфейс. По этой причине мы никогда не должны отображать атрибут сущности как Необязательный , потому что это ограничит использование сущности.

Например, у нас может быть отдельный экземпляр, хранящийся в HttpSession , потому что мы выполняем рабочий процесс длительного разговора . Каждый объект, хранящийся в HttpSession , должен быть Сериализуемый потому что сеанс может быть сгруппирован на нескольких веб-узлах.

Если вы используете Java EE и компоненты сеанса с сохранением состояния, то вы должны убедиться, что все сущности сериализуемы, так как в противном случае процесс пассивации завершится неудачей .

По всем этим причинам атрибут сущности не должен отображаться как java.util. Необязательно .

Но только потому , что мы не можем отобразить атрибут сущности как Необязательный , это не означает, что мы не можем предоставить его с помощью Необязательного контейнера. Если мы используем сохраняемость доступа на основе полей, то базовый атрибут сущности может быть сопоставлен с использованием фактического сохраняемого типа, в то время как метод получения может использовать Необязательно вместо этого.

@Entity(name = "PostComment")
@Table(name = "post_comment")
public class PostComment 
    implements Serializable {

    @Id
    @GeneratedValue
    private Long id;

    private String review;

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

    @ManyToOne(fetch = FetchType.LAZY)
    private Attachment attachment;

    public Optional getAttachment() {
        return Optional.ofNullable(attachment);
    }

    public void setAttachment(Attachment attachment) {
        this.attachment = attachment;
    }
    
    //Other getters and setters omitted for brevity
}

Вот и все!

Если вы используете доступ на основе свойств, то получатель должен предоставить фактический сохраняемый тип, и в этом случае вам потребуется отдельный метод @Transient , который использует Необязательно тип возвращаемого метода.

Предполагая, что у нас есть следующие сущности:

byte[] coverContent = new byte[] {1, 2, 3};

Post post = new Post();
post.setId(1L);
post.setTitle("High-Performance Java Persistence");
entityManager.persist(post);

PostComment comment1 = new PostComment();
comment1.setPost(post);

entityManager.persist(comment1);

Attachment cover = new Attachment();
cover.setContent(coverContent);
entityManager.persist(cover);

PostComment comment2 = new PostComment();
comment2.setPost(post);
comment2.setAttachment(cover);

entityManager.persist(comment2);

Если у нас уже есть список Комментариев к публикациям :

List comments = entityManager.createQuery(
    "select pc " +
    "from PostComment pc " +
    "join pc.post p " +
    "where p.id = :postId", PostComment.class)
.setParameter("postId", 1L)
.getResultList();

Мы можем обработать Вложения(ы) следующим образом:

Attachment notAvailable = getNotAvaillableImage();

List attachments = comments
.stream()
.map(pc -> pc.getAttachment()
.orElse(notAvailable))
.collect(Collectors.toList());

Если его нет Вложение уже установлено, мы можем использовать значение по умолчанию N/A изображение.

При использовании JPA и гибернации вы можете использовать Java 1.8 Необязательно в сущностях вашей модели домена. Однако вы должны убедиться, что не используете его в качестве постоянного типа свойства.