我目前在一个学校项目上,我们必须创建自己的“Twitter”应用程序,并且在域对象的持久性方面遇到了一些麻烦。

我的帐户类(为便于阅读而简化):

@Entity
public class Account implements Serializable {

@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE)
private Long id;
@Column(unique = true)
private String email;

@OneToMany
private final List<Account> following = new ArrayList<>();
@OneToMany(mappedBy = "tweetedBy", cascade = ALL)
private final List<Tweet> tweets = new ArrayList<>();

我的Tweet类(为便于阅读而简化):
@Entity
public class Tweet implements Serializable {

@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE)
private Long id;
private String content;

@ManyToOne
private Account tweetedBy;

@OneToMany(cascade = CascadeType.PERSIST)
@JoinTable(name = "tweet_likes")
private final List<Account> likedBy = new ArrayList<>();

@OneToMany(cascade = CascadeType.PERSIST)
@JoinTable(name = "tweet_mentions")
private final List<Account> mentions = new ArrayList<>();

持久性代码(简体):
Account a1 = new Account("user1@gmail.com", "password1");
Account a2 = new Account("user2@gmail.com", "password2");
Account a3 = new Account("user3@gmail.com", "password3");

a1.addTweet("Sup mah dudes.");
a1.addTweet("yoyo");
a2.addTweet("Allo Allo #tweeting");
a2.addTweet("#testing yoyo");
a1.getTweets().get(0).addLike(a3);
a1.addFollowing(a3);

em.persist(a1);
em.persist(a2);
em.persist(a3);

我遇到的问题是likedBymentions没有正确保存。正在生成链接器表,并插入了数据,但是在用户插入时我不断收到重复的输入错误。我相信我已经正确地建立了关系模型(单向OneToMany),因为我不想让一个帐户跟踪提到它的推文。

我尝试过的是:
  • @JoinColumn
  • likes(重复插入的结果)
  • mentions
  • @JoinTable(重复插入的结果)
  • likesmentions都只有@OneToMany(这不会导致错误,但会为两个关系创建1个链接器表,其中两个关系都不能为null)
  • likes转换为mentions,然后将@OneToMany转换为likes,其中@joinColumn(这会导致在tweet中除非您喜欢它,否则无法在u中提及u,这是奇怪的行为)
  • mentions(重复插入结果)

  • Netbeans输出重复插入错误:
    Warning:   Local Exception Stack:
    Exception [EclipseLink-4002] (Eclipse Persistence Services - 2.6.4.qualifier): org.eclipse.persistence.exceptions.DatabaseException
    Internal Exception: com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Duplicate entry 'user6@gmail.com' for key 'EMAIL'
    Error Code: 1062
    Call: INSERT INTO ACCOUNT (AVATARPATH, BIO, EMAIL, ENCRYPTEDPASSWORD, LOCATION, USERNAME, USERROLE, WEBSITE) VALUES (?, ?, ?, ?, ?, ?, ?, ?)
    bind => [8 parameters bound]
    Query: InsertObjectQuery(domain.Account@3c7f9d54)
    

    我相信会由于我的JPA执行下列流程而发生此错误:
  • 帐户已保留
  • 鸣叫持续存在(因为它在帐户中)
  • 帐户已保留(因为它在Tweet中)
    我的期望:
  • 1个链接器表,带有nullable = true@OneToMany(cascade = CascadeType.MERGE)表示喜欢的
  • 1个链接器表,带有tweet_id (fk)account_id (fk)表示所提及的

  • 如果有人可以帮助我进行注释或解释我在做什么错,那将不胜感激。

    请提前寻求任何帮助。

    最佳答案

    我解决了这个问题,原来是likesmentions的注释。 @JoinTable(name = "")修复了它。我认为在重新部署之前不手动删除表会导致我一开始并不认为这是解决方案。

    对于任何有类似问题的人,这是我的解决方案:

    @OneToMany(cascade = CascadeType.PERSIST)
    @JoinTable(name = "tweet_likes") //<--CREATES SEPERATE TABLE
    private final List<Account> likedBy = new ArrayList<>();
    @OneToMany(cascade = CascadeType.PERSIST)
    @JoinTable(name = "tweet_mentions") //<--CREATES SEPERATE TABLE
    private final List<Account> mentions = new ArrayList<>();
    

    另外,同样地,如果我重新启动整个项目(重新启动整个glassfish/payara服务器),则会收到重复的输入错误,因为EntityManager尝试在删除和重新创建表之前将其持久化到数据库。因此,如果我在使payara服务器保持联机状态的同时取消部署和重新部署项目,那么它就可以正常运行。我还没有找到解决这个问题的方法,但是那是另一个问题。

    10-05 22:37
    查看更多