JPA例外保存父母/子女

时间:2018-12-07 07:30:03

标签: java database jpa

我正在使用JPA,并且具有以下内容:

ProductEntity 

@Basic
@Column(name = "PRODUCT_ID", nullable = false, length = 128)
private String productId;

@ManyToOne
@JoinColumn(name = "PARENT_ID")
private ProductEntity parent;

如您所见,产品表可以有一个父级。有效的亲子关系。

我在数据库中保存了一个产品,然后添加了一些子产品,每个子产品具有相同的父产品。

  • 父产品的ProductEntity父= null;
  • 子产品具有ProductEntity父产品=父产品;

    ProductEntity parentProductEntity = ...
    ProductEntity childProductEntity1 = ...
    ProductEntity childProductEntity2 = ...
    
    em.persist(parentProductEntity);
    childProductEntity1.setParent(parentProductEntity);
    childProductEntity2.setParent(parentProductEntity);
    em.merge(childProductEntity1);
    

数据(从不插入最后两个子行)

    ID        PRODUCT_ID     PARENT_ID
     1           1              null
     2           2                1
     3           3                1

问题

然后我尝试保存每个子产品。但是我收到一条错误消息,表明存在重复的密钥(productId)。保存孩子时,它也会尝试保存父项的重复条目。

  

由以下原因引起:org.postgresql.util.PSQLException:错误:重复键   值违反唯一约束“ t_osm_product_product_id_uindex”

问题

为了成功保存每个子产品,我该如何更改?

谢谢

3 个答案:

答案 0 :(得分:2)

您的实体应如下所示

 ID        PRODUCT_ID     PARENT_ID
 1           abc              null
 2           def                1
 3           xyz                1

您的代码中的其他所有内容都没问题。

数据库中的数据看起来像这样

import facebook
import pyspark
from pyspark import *
from pyspark.sql import *
from pyspark.sql.types import *
from pyspark.sql.functions import *

def fb_func(rows):
    fields='id,first_name,middle_name,last_name,gender,birthday'
    ret = []
    for row in rows:
        token = row[6]
        id = row[7]
        graph = facebook.GraphAPI(access_token=token, version=3.0)
        user = graph.get_object(id=id, fields=fields)

        ret.append(str(id) + "," + str(token) + "," + str(user['first_name']) + "," + str(user['middle_name']) + "," + str(user['last_name']) + "," + str(user['gender']) + "," + str(user['birthday']))

    return ret

file = spark.read.parquet("s3://parquet-files/fb_data/*")
fb_file = file.repartition(5)

fb_schema = StructType([
    StructField('user_id', LongType(), True), 
    StructField('token', StringType(), True), 
    StructField('first_name', StringType(), True), 
    StructField('middle_name', StringType(), True), 
    StructField('last_name', StringType(), True), 
    StructField('gender', StringType(), True), 
    StructField('birthday', StringType(), True)
])

fb_rdd = fb_file.rdd\
    .mapPartitions(fb_func)\
    .toDF(fb_schema)\
    .repartition(2)\
    .collect()

答案 1 :(得分:0)

您可以尝试@ManyToOne(cascade=CascadeType.MERGE)

答案 2 :(得分:0)

请更改以下几点并检查:-

  • 使用“ persist”代替“ merge”,并按以下顺序进行操作。

{

public static void main (String[] agrs){
EntityManager em = ... // from EntityManagerFactory, injection, etc.

em.getTransaction().begin();

A parent   = new A();
A son      = new A();
A daughter = new A();

son.setParent(parent);
daughter.setParent(parent);

em.persist(parent);
em.persist(son);
em.persist(daughter);

em.getTransaction().commit();
}