Ошибка каскадирования JPA для сущности, которая уже существует
У меня есть ошибка ниже при попытке обновить сущность. Решение этой проблемы говорит о том, что "принадлежащий" объект должен быть сохранен перед сохранением владельца, но я сделал это. Или пометить обе сущности каскадом.
ошибка (я думаю, что полная трассировка стека не нужна):
2015-08-10T20:45:11.481+0200|Warning: A system exception occurred during an invocation on EJB ThreadLookUpService, method: public void main.java.services.ThreadLookUpService.setLastPost(long,main.java.entities.Post)
Caused by: java.lang.IllegalStateException: During synchronization a new object was found through a relationship that was not marked cascade PERSIST: main.java.entities.Post@6724f919.
(Если я добавлю cascade = CascadeType.ALL
Я получаю еще одну ошибку, сообщая, что внешний ключ не существует, но я просто сохранил его. Насколько я понимаю, мне даже не пришлось бы использовать каскад, если я сохраняю сущности в правильном порядке.
Caused by: com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Cannot add or update a child row: a foreign key constraint fails (`forumcs`.`thethreads`, CONSTRAINT `fk_thethreads_posts1` FOREIGN KEY (`last_post`) REFERENCES `posts` (`idpost`) ON DELETE NO ACTION ON UPDATE NO ACTION)
)
Здесь я сохраняю пост (принадлежит), затем Thethread(владелец):
post = postLookup.createPostAndGiveItBack(post);
threadLookup.setLastPost(thread.getThread().getIdthread(), post); //this gives error.
Вот мой способ сохранить сообщение, я использовал flush, потому что я думал, что идентификатор сообщения не был сгенерирован или smtg:
@Override
public Post createPostAndGiveItBack(Post post) {
em.persist(post);
em.flush();
return post;
}
Вот мой способ обновить lastPost ofthread. Я мог бы объединить его непосредственно с тем, который я вытащил ранее, но если я это сделаю, то мои поля upvote и downvote будут испорчены, если два разных пользователя будут просматривать одну и ту же страницу и обновлять тему:
@Override
public void setLastPost(long id, Post post) {
Query query = em.createQuery(FIND_THREAD_BY_ID);
query.setParameter("id", id);
Thethread thread = (Thethread) query.getSingleResult();
thread.setLastPost(post);
}
Почтовый объект:
@Entity
@Table(name = "posts")
@NamedQuery(name = "Post.findAll", query = "SELECT p FROM Post p")
public class Post implements Serializable, Comparable<Post> {
private static final long serialVersionUID = 1L;
@Id
private int idpost;
private String content;
@Temporal(TemporalType.TIMESTAMP)
@Column(name = "date_post")
private Date datePost;
private int downvotes;
private int upvotes;
// bi-directional many-to-one association to PostVote
@OneToMany(mappedBy = "post")
private List<PostVote> postVotes;
// bi-directional many-to-one association to Post
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "reply_to_post")
private Post replyTo;
// bi-directional many-to-one association to Post
@OneToMany(mappedBy = "replyTo")
private List<Post> replies;
// bi-directional many-to-one association to Thethread
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "threads_idthread")
private Thethread thethread;
// bi-directional many-to-one association to User
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "users_username")
private User user;
@Transient
private double confidenceScore;
public Post() {
}
Thethread Entity:
@Entity
@Table(name = "thethreads")
@NamedQuery(name = "Thethread.findAll", query = "SELECT t FROM Thethread t")
public class Thethread implements Serializable {
private static final long serialVersionUID = 1L;
@Id
private int idthread;
private String content;
@Temporal(TemporalType.TIMESTAMP)
@Column(name = "date_posted")
private Date datePosted;
// I could get this by scanning the Threadvotes and count the number of downvotes
// But I thought it was better like this for ease and performance.
private int downvotes;
@Column(name = "hot_score")
private int hotScore;
@Column(name = "is_pol")
private String isPol;
private String title;
private String type;
private int upvotes;
// bi-directional many-to-one association to Post
@OneToMany(mappedBy = "thethread")
private List<Post> posts;
// bi-directional many-to-one association to Category
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "categories_idcategory")
private Category category;
// UNI-directional many-to-one association to Post
@OneToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "last_post")
private Post lastPost;
// bi-directional many-to-one association to User
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "posted_by")
private User user;
// bi-directional many-to-one association to ThreadVote
@OneToMany(mappedBy = "thethread")
private List<ThreadVote> threadVotes;
1 ответ
Я добавил это к своему идентификатору сущности:
@GeneratedValue(strategy = GenerationType.IDENTITY)
и это работает.