【问题标题】:JPA cascade persist - many to one unidirectionalJPA 级联持续存在 - 多对一单向
【发布时间】:2017-04-01 05:37:45
【问题描述】:

我有一个多对一的单向关系,我正在尝试保留一个子实体,即 SubscriptionEntity 也希望它也应该保留 Parent,因为我正在使用 cascade = CascadeType.PERSIST

关于关系的背景:SubscriptionEntity 让您知道哪个 用户 与哪个 企业 相关联,并且很少有实体喜欢状态和产品告诉我们 状态 订阅以及与订阅相关的产品是什么。订阅状态是一对多双向的,因为订阅可以在会员资格暂停、活动、停用等过程中转变为多种状态。类似地,与产品的订阅关系是一对多双向的,因为用户可以订阅一种产品或不止一个。

我们不能在用户和订阅之间进行双向关联,因为用户可以与许多企业有关联。

    public class SubscriptionEntity implements Domain, Serializable
    {
        @Column(name = "subscription2user")
        @ManyToOne(optional = false, fetch = FetchType.EAGER, cascade = CascadeType.PERSIST)
        @JoinColumn(name = "subscription2user")
        private UserEntity user;

        @Column(name = "subscription2biz")
        @ManyToOne(optional = false, fetch = FetchType.LAZY)
        @JoinColumn(name = "subscription2biz")
        private BusinessEntity business;

        @OneToMany(fetch = FetchType.EAGER, mappedBy = "subscription", cascade = CascadeType.PERSIST)
        private List<ProductSubscriptionEntity> subscribedProducts;

        @OneToMany(fetch = FetchType.EAGER, mappedBy = "subscription", cascade = CascadeType.PERSIST)
        private List<SubscriptionStateEntity> state;
    }

public class UserEntity implements Domain, Serializable
{
    private static final long serialVersionUID = 755369097357065341L;

    @Id
    @Column(name = "user_id")
    private String id;

    @Column(name = "user_first_name")
    private String firstName;

    @Column(name = "user_last_name")
    private String lastName;

    @Column(name = "user_mobile")
    private BigInteger mobile;

    @Column(name = "user_password")
    private String password;

    @Column(name = "user_create_date")
    private Date createDate;

    @OneToOne(cascade = CascadeType.PERSIST)
    @JoinColumn(name = "user2address")
    @Column(name = "user2address")
    private UserAddressEntity address;
}

public class SubscriptionStateEntity implements Domain, Serializable
{
    @Column(name = "subscription_state2subscription")
    @ManyToOne(optional = false)
    @JoinColumn(name="subscription_state2subscription")
    protected SubscriptionEntity subscription;
}

public class ProductSubscriptionEntity implements Domain, Serializable
{
    @Column(name = "user_product_subscription2subscription")
    @ManyToOne(optional = false, fetch = FetchType.EAGER)
    @JoinColumn(name = "user_product_subscription2subscription")
    private SubscriptionEntity subscription;
}

场景:业务已经存在,但用户是新的,用户和订阅之间的关联也是新的。当我尝试添加新订阅时出现以下错误。如果用户已经存在于数据库中,那么它可以顺利运行。

void addSubscription(final UserEntity user, final String businessID)
{
    final UserEntity userTemp = this.userDao.readUserByIdOrMobile(user.getId(), user.getMobile());
    if (null == userTemp)
    {
        user.setId(java.util.UUID.randomUUID().toString());
        user.setCreateDate(DateUtil.getDateTimestamp());
    }
    final BusinessEntity business = getBusinessByID(businessID);
    SubscriptionEntity subscription = new SubscriptionEntity();
    subscription.setUser(user);
    subscription.setBusiness(business);

    super.getEm().persist(subscription);
}

原因: org.apache.openjpa.persistence.EntityExistsException:无法添加或 更新子行:外键约束失败 ... ... 参考 user (user_id) ON DELETE NO ACTION ON UPDATE NO ACTION

非常感谢任何帮助。提前致谢。

【问题讨论】:

  • 你确定这是工作代码吗?通常,当您有 JoinColumn 时,不会使用 Column。会抛出注解异常
  • 是的,它的工作代码在持续订阅时遇到异常。
  • 对于 OpenJPA,它适用于 JoinColumn。当我们使用 Hibernate 时它不会工作。

标签: java jpa openjpa


【解决方案1】:

您似乎没有在 UserEntity 实体上给出表和列映射注释。

由于您没有为 UserEntity 设置 id,您是否定义了 id 生成策略?当您没有设置 id 时,订阅和用户之间没有链接。

您可以使用下面在 id 字段上的 UserEntity 中给出的注释将 id 生成策略添加为自动增量。这将在创建时生成 id。

GeneratedValue(strategy=GenerationType.IDENTITY) 私有字符串id;

【讨论】:

  • 用户表有 id、firstName、lastName、mobile、emaild、address。我正在检查用户是否已经通过手机号码存在,如果没有,则分配 id 新 UUID,如下所示: void addSubscription(final UserEntity user, final String businessID) { final UserEntity userTemp = this.userDao.readUserByIdOrMobile(user.getId(), user .getMobile()); if (null == userTemp) { user.setId(java.util.UUID.randomUUID().toString()); user.setCreateDate(DateUtil.getDateTimestamp()); } }
  • 你能用 UserEntity 类代码更新你的问题吗?
  • 更新了 UserEntity 的问题,感谢您抽出时间提问。
【解决方案2】:

您没有为用户实体指定任何 ID,因为 ID 是字符串,它将创建一个 ID 为“”的 UserEntity。尝试为用户实体ID添加一些id生成策略,否则新创建的用户总是会导致这个EntityExistsException的用户。

附:双向关联仅意味着您可以从双方获取实体。它与您的业务逻辑没有任何关系。

【讨论】:

  • 我已经更新了我的原始问题,最初的帖子中遗漏了以下文字。 user.setId(java.util.UUID.randomUUID().toString());
  • 我们避免在 UserEntity 和 SubscriptionEntity 之间使用双向关联,因为如果我们通过任何业务拉取用户,那么由于双向关联,它将允许与其他业务关联的订阅的可见性,这我们不想暴露。
  • 好的,现在我明白你的意思了。如果您尝试为新订阅设置新用户,为什么要将用户传递给订阅?
  • 我有一个 rest api,它接受用户对象和业务 ID 的输入,这表明我们必须存储新用户并将其与该业务相关联。由于用户和业务关联存储在订阅表中。添加订阅,但用户也是新用户,所以也添加它。
  • this.userDao.createUser(userTemp); this.subscriptionDao.createSubscribeUser(subscription);还尝试先创建用户,然后再创建用户和业务关联,但失败并出现同样的错误。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-11-04
  • 1970-01-01
  • 1970-01-01
  • 2013-03-05
  • 2013-12-04
  • 2018-09-12
相关资源
最近更新 更多