【发布时间】:2015-11-02 20:15:46
【问题描述】:
我在尝试更新实体时遇到以下错误。 The solution to this problem 说“拥有”实体必须在持久化所有者之前持久化,但我这样做了。或者用级联标记两个实体。
错误(我猜不需要完整的堆栈跟踪):
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.
这是我坚持帖子的方法,我使用了flush,因为我认为帖子id没有生成或smtg:
@Override
public Post createPostAndGiveItBack(Post post) {
em.persist(post);
em.flush();
return post;
}
这是我更新 Thethread 的 lastPost 的方法。我可以直接将它与我之前提取的那个合并,但如果我这样做了,那么如果 2 个不同的用户观看同一页面并更新线程,我的 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() {
}
线程实体:
@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 来发布的,你是否在 createPostAndGiveItBack 方法返回的内容中检查了它的值?错误指出引用的帖子不是来自此持久性单元 - 您可以更改级联选项以对 lastPost 关系进行级联合并,或者从当前 EntityManager 查找帖子并使用它来设置引用
-
@Chris id 为“0”。您告诉我的 2 中是否有最佳选择?此外,我发现我必须查找我刚刚坚持的实体有点奇怪。我不能直接从函数中返回它吗?如果不是,那就太可惜了,而且查找似乎没有必要。问题是我什至无法查找帖子,因为 id 未知。
-
所以你没有设置ID?在某些提供程序中,默认情况下 0 不被视为有效的 ID 值。尝试设置一个值或使用 ID 生成。如果设置了 ID,则提供者将能够使用它来确定它是现有实例(尽管可能仍然不受管理),并将其用于外键引用。
-
@Chris 谢谢我添加了@GeneratedValue(strategy = GenerationType.IDENTITY) 并且它有效。如果您想自己发布它,我会接受它作为答案。甜蜜的免费业力!我实际上已经发布了它,如果你这样做,我会删除它(我在阅读你的评论之前发布了)。
标签: jakarta-ee jpa jpql persistence-manager