JPA cascade persist error with an entity that has already persisted
JPA cascade persist error with an entity that is already persisted
我在尝试更新实体时遇到以下错误。 The solution to this problem 表示必须在保留所有者之前保留 "owned" 实体,但我做到了。或者用级联标记两个实体。
错误(我猜不需要完整的堆栈跟踪):
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)
)
这里我坚持post(owned)然后Thethread(owner):
post = postLookup.createPostAndGiveItBack(post);
threadLookup.setLastPost(thread.getThread().getIdthread(), post); //this gives error.
这是我坚持post的方法,我使用flush是因为我认为post id没有生成或者smtg:
@Override
public Post createPostAndGiveItBack(Post post) {
em.persist(post);
em.flush();
return post;
}
这是我更新 Thethread 的最后一个Post 的方法。我可以将它直接与我之前退出的那个合并,但如果我这样做了,那么如果 2 个不同的用户观看同一页面并更新线程,我的赞成票和反对票字段将被弄乱:
@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);
}
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() {
}
线程实体:
@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;
我将此添加到我的实体 ID:
@GeneratedValue(strategy = GenerationType.IDENTITY)
而且有效。
我在尝试更新实体时遇到以下错误。 The solution to this problem 表示必须在保留所有者之前保留 "owned" 实体,但我做到了。或者用级联标记两个实体。
错误(我猜不需要完整的堆栈跟踪):
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)
)
这里我坚持post(owned)然后Thethread(owner):
post = postLookup.createPostAndGiveItBack(post);
threadLookup.setLastPost(thread.getThread().getIdthread(), post); //this gives error.
这是我坚持post的方法,我使用flush是因为我认为post id没有生成或者smtg:
@Override
public Post createPostAndGiveItBack(Post post) {
em.persist(post);
em.flush();
return post;
}
这是我更新 Thethread 的最后一个Post 的方法。我可以将它直接与我之前退出的那个合并,但如果我这样做了,那么如果 2 个不同的用户观看同一页面并更新线程,我的赞成票和反对票字段将被弄乱:
@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);
}
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() {
}
线程实体:
@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;
我将此添加到我的实体 ID:
@GeneratedValue(strategy = GenerationType.IDENTITY)
而且有效。