Java, Hibernate - объект ссылается на несохраненный временный экземпляр - PullRequest
0 голосов
/ 06 февраля 2019

Я пытаюсь сохранить Comment в спящем режиме.Помимо идентификатора и тела, у Comment есть пользователь и свойство проблемы.Следующий код выдает org.hibernate.TransientObjectException, сказав, что я должен сохранить User перед сбросом.

   public static long saveComment(Comment comment) {

    long ret;

    try (Session ses = factory.openSession()) {
        ses.beginTransaction();
        ses.save(comment.getUser());
        ses.save(comment.getIssue());
        ret = (long) ses.save(comment);
        ses.getTransaction().commit();
    }
    return ret;
}

Изменение ses.save(comment.getUser()); на ses.persist(comment.getUser()); приводит к org.hibernate.PersistentObjectException, говорящему, что User отсоединен.Я в замешательстве, насколько я понимаю, объект в спящем режиме является либо временным, либо отсоединенным, но здесь он показывает, что они оба.

Я уже пробовал разные каскадные типы в аннотациях User s OneToMany,в настоящее время они установлены на PERSIST, швы ведьмы, что я хочу.Кроме того, насколько я понимаю, Comment не должно иметь значения cascade, поскольку User и Issue владеют Comment.

Ниже приведен код, который получает Пользователь икод, который вызывает saveComment.

public static Response create(String body) throws IOException {
    Map<String, Object> map = new ObjectMapper()
            .configure(DeserializationFeature.USE_LONG_FOR_INTS, true)
            .readValue(body, Map.class);
    User creator;
    Issue issue;

    try {
        creator = Repository.getUserById((long) map.get("user_id"));
    } catch (NoResultException ex) {
        return Response.status(404).entity(ex.getMessage()).build();
    }
    try {
        issue = Repository.getIssueById((long) map.get("issue_id"));
    } catch (NoResultException ex) {
        return Response.status(404).entity(ex.getMessage()).build();
    }

    Comment comment = new Comment();
    comment.setBody((String) map.get("body"));
    comment.setIssue(issue);
    comment.setUser(creator);
    creator.addComment(comment);
    issue.addComment(comment);

    long id = Repository.saveComment(comment);

    return Response.created(URI.create("/comment/"+id)).build();
}

public static User getUserById(long id) {
    User ret;

    try (Session ses = factory.openSession()) {
        ses.beginTransaction();
        ret = (User) ses.createQuery(
                "from User u where u.id = :id")
                .setParameter("id", id)
                .getSingleResult();
        ses.getTransaction().commit();
    }

    return ret;
}

РЕДАКТИРОВАТЬ: сущности пользователя и комментария.

package de.phs.issues.model;

import com.fasterxml.jackson.annotation.JsonIdentityInfo;
import com.fasterxml.jackson.annotation.JsonIdentityReference;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.ObjectIdGenerators;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import lombok.Data;
import lombok.EqualsAndHashCode;

import javax.persistence.*;
import java.io.IOException;
import java.util.HashSet;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;

@Entity
@Data
@EqualsAndHashCode(exclude = {"issues", "comments"})
@Table(name="`user`")
@JsonIgnoreProperties({"hibernateLazyInitializer", "handler"})
@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "id", scope = User.class)
public class User {

    @Column(nullable = false, unique = true)
    private String name;

    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE)
    private long id;

    @OneToMany(fetch = FetchType.EAGER, mappedBy = "creator", cascade = CascadeType.PERSIST)
    @JsonIdentityInfo(generator=ObjectIdGenerators.PropertyGenerator.class, property="id")
    @JsonIdentityReference(alwaysAsId=true)
    private Set<Issue> issues = new HashSet<>();

    @OneToMany(fetch = FetchType.EAGER, mappedBy = "user", cascade = CascadeType.PERSIST)
    @JsonIdentityInfo(generator=ObjectIdGenerators.PropertyGenerator.class, property="id")
    @JsonIdentityReference(alwaysAsId=true)
    private Set<Comment> comments = new HashSet<>();

    public String toJson() throws JsonProcessingException {
        return new ObjectMapper()
                .enable(SerializationFeature.INDENT_OUTPUT)
                .writeValueAsString(this);
    }

    public static User fromJson(String json) throws IOException {
        return new ObjectMapper()
                .configure(DeserializationFeature.USE_LONG_FOR_INTS, true)
                .readValue(json, User.class);
    }

    public boolean addIssue(Issue issue) {
        issue.setCreator(this);
        return issues.add(issue);
    }

    public boolean removeIssue(Issue issue) {
        issue.setCreator(null);
        return issues.remove(issue);
    }

    public boolean addComment(Comment comment) {
        comment.setUser(this);
        return comments.add(comment);
    }

    public boolean removeComment(Comment comment) {
        comment.setUser(null);
        return comments.remove(comment);
    }

    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder();
        sb.append("User{id=");
        sb.append(id);
        sb.append(" ,name=");
        sb.append(name);
        sb.append(", issues=[");
        String issue_ids = issues.stream()
                .map(Issue::getId)
                .map(l -> Long.toString(l))
                .flatMap(s -> Stream.of(",", s))
                .skip(1)
                .collect(Collectors.joining());
        sb.append(issue_ids);
        sb.append("], comments=[");
        String comment_ids = comments.stream()
                .map(Comment::getId)
                .map(l -> Long.toString(l))
                .flatMap(s -> Stream.of(",", s))
                .skip(1)
                .collect(Collectors.joining());
        sb.append(comment_ids);
        sb.append("]}");
        return sb.toString();
    }
}

package de.phs.issues.model;

import com.fasterxml.jackson.annotation.JsonIdentityInfo;
import com.fasterxml.jackson.annotation.JsonIdentityReference;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.ObjectIdGenerators;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import lombok.Data;
import lombok.EqualsAndHashCode;

import javax.persistence.*;
import java.io.IOException;

@Data
@EqualsAndHashCode(exclude = {"user", "issue"})
@Entity
@JsonIgnoreProperties({"hibernateLazyInitializer", "handler"})
@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "id", scope = Comment.class)
public class Comment {

    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE)
    private long id;
    private String body;

    @ManyToOne(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
    @JsonIdentityInfo(generator=ObjectIdGenerators.PropertyGenerator.class, property="id")
    @JsonIdentityReference(alwaysAsId=true)
    private User user;

    @ManyToOne(fetch = FetchType.EAGER)
    @JsonIdentityInfo(generator=ObjectIdGenerators.PropertyGenerator.class, property="id")
    @JsonIdentityReference(alwaysAsId=true)
    private Issue issue;

    public String toJson() throws JsonProcessingException {
        return new ObjectMapper()
                .enable(SerializationFeature.INDENT_OUTPUT)
                .writeValueAsString(this);
    }

    public static Comment fromJson(String json) throws IOException {
        return new ObjectMapper()
                .configure(DeserializationFeature.USE_LONG_FOR_INTS, true)
                .readValue(json, Comment.class);
    }

    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder();
        sb.append("Comment{body=");
        sb.append(body);
        sb.append(", id=");
        sb.append(id);
        sb.append(", user=");
        sb.append(user.getId());
        sb.append(", issue=");
        sb.append(issue.getId());
        sb.append("}");
        return sb.toString();
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...