与JPA的多对一关系

与JPA的多对一关系,jpa,arraylist,many-to-one,Jpa,Arraylist,Many To One,我想保留一个包含键值对的列表,但我不知道如何使用JPA实现我的目标。我可以用简单的jdbc实现它,但我想使用jpa 要求: prue JPA,我不想在java类中看到任何与hibernate、eclipselink等相关的导入 密钥在数据库中必须是唯一的 如果父项被删除,则需要删除该值,但我需要将键保留在数据库中 列表中可以有相同的项(相同的键具有不同的值或相同的键具有相同的值) 数据库表: 用例: 如果从数据库中删除了“cartype1”,那么我希望在属性表中保留键。例如,id为10的属性仅属

我想保留一个包含键值对的列表,但我不知道如何使用JPA实现我的目标。我可以用简单的jdbc实现它,但我想使用jpa

要求:

  • prue JPA,我不想在java类中看到任何与hibernate、eclipselink等相关的导入
  • 密钥在数据库中必须是唯一的
  • 如果父项被删除,则需要删除该值,但我需要将键保留在数据库中
  • 列表中可以有相同的项(相同的键具有不同的值或相同的键具有相同的值)
  • 数据库表:

    用例:

  • 如果从数据库中删除了“cartype1”,那么我希望在属性表中保留键。例如,id为10的属性仅属于此产品,因此我可以从数据库中删除此项,而不会出现任何sql异常(其他产品不使用该键),但我希望将其保留在表中

  • 带新密钥的新产品:没问题,jpa可以存储它们

  • 具有现有密钥的新产品:

    product.name=产品A

    属性:白色|价格-11美元|分辨率大

    需要将新键插入属性键表(“解析”),然后将值持久化到属性表中

  • 需要存储具有重复密钥(和值)的产品:

    product.name=产品B

    属性:红色|绿色|绿色

  • 具有重复新密钥的产品(密钥尚未持久化)

    product.name=产品C

    属性:attr1-value1 | attr1-value2 |

  • 我的代码工作正常,但出现以下两种情况:

  • 列表中有具有相同密钥的项,但该密钥尚未持久化(案例5)。Jpa在列表上迭代并保存新密钥。当jpa想要用相同的键持久化下一个项目时,我会得到一个“错误:重复的键值违反了唯一约束”异常,因为键在数据库中定义为唯一字段,并存储在第一轮中

  • 列表中有一个项,其密钥存在于数据库中。 例外:同一实体的多个表示形式

  • 代码:

    公共作废更新(产品)
    {
    尝试
    {
    Product queryResult=(Product)em.createNamedQuery(“Product.findBy…”)..getSingleResult();
    //现有产品,执行更新
    queryResult.getAttributes().clear();
    updateAttributes(product.getAttributes());
    Product managedProduct=em.merge(产品);
    ...
    }
    捕获(noresulte异常)
    {
    //新产品,执行插入
    updateAttributes(product.getAttributes());
    Product managedProduct=em.merge(产品);
    ...
    }
    捕获(例外e)
    {
    }
    }
    私有void updateAttribute(最终列表属性)
    {
    用于(属性:属性)
    {
    setId(null);
    尝试
    {
    AttributeKey查询结果=(AttributeKey)em.createNamedQuery(“AttributeKey.findByKey”)
    .setParameter(“key”,attribute.getKey().getKey()).getSingleResult();
    //setKey(queryResult);
    attribute.getKey().setId(queryResult.getId());
    }
    捕获(noresulte异常)
    {
    //em.persist(attribute.getKey());
    attribute.getKey().setId(null);
    }
    attribute.getKey().setLastUsed(新日期());
    }
    }
    @实体
    @表(name=“ATTRIBUTE”)
    公共类属性
    {
    @身份证
    @序列发生器。。。
    @生成值。。。
    @列(name=“ID”,unique=true,nullable=false)
    私人长id;
    @ManyToOne(cascade={CascadeType.ALL},optional=false,fetch=FetchType.EAGER)
    @JoinColumn(name=“ATTRIBUTE\u KEY\u ID”,nullable=false,updateable=false)
    私钥;
    ...
    }
    @实体
    @表(name=“ATTRIBUTE\u KEY”)
    @namedquerys(…)
    公共类属性键
    {
    @身份证
    @序列生成器(…)
    @生成值(…)
    @列(name=“ID”,unique=true,nullable=false)
    私人长id;
    @列(name=“KEY”,长度=128,唯一性=true)
    私钥;
    @列(name=“WEIGHT”)
    私人长体重;
    @列(name=“上次使用”)
    上次使用的私人日期;
    ...
    }
    

    有可能用jpa实现这种逻辑吗?

    如果没有任何ORM框架(如Hibernate或EclipseLink),就不可能使用jpa。JPA只是一个规范,Hibernate或EclipseLink是它的实现。请看这里:我知道JPA是一种编程接口规范,有很多实现,比如Hibernate、EclipseLink等。我想编写独立的java代码,所以我只想使用javax.persistence.*包中的类。我不想使用Hibernate或EclipseLink的任何额外特性/类。如果您坚持使用普通的旧JPA,您可以避免导入eclipse、Hibernate等类。您无法避免将至少一个JAR文件包含为库。你必须选择其中一个。如果你坚持使用纯JPA,你可以在不同批次之间进行迁移。也请发布你的表结构。你给我们看的东西不清楚。
    product
    id, name, ...
    1   car type 1
    2   apple
    3   chair
    
    attribute-key
    id, key,      last_used  (key with unique constraint!!)
    10  category
    11  color
    12  quality
    13  packing
    14  price
    
    attribute
    id, prod_id, key_id, value
    50  1        10      small 
    51  1        11      green
    52  1        14      1 million eur
    53  2        13      12 pieces
    54  2        11      red
    55  3        12      poor
    ...
    
    public void update(Product product)
    {
        try
        {
            Product queryResult = (Product) em.createNamedQuery("Product.findBy...")....getSingleResult();
    
            // existing product, perform update
            queryResult.getAttributes().clear();
            updateAttributes(product.getAttributes());
    
            Product managedProduct = em.merge(product);
            ...
        }
        catch (NoResultException e)
        {
            // new product, perform insert
            updateAttributes(product.getAttributes());
    
            Product managedProduct = em.merge(product);
            ...
        }
        catch (Exception e)
        {
        }
    }
    
    private void updateAttributes(final List<Attribute> attributes)
    {
        for (Attribute attribute : attributes)
        {
            attribute.setId(null);
    
            try
            {
                AttributeKey queryResult = (AttributeKey) em.createNamedQuery("AttributeKey.findByKey")
                        .setParameter("key", attribute.getKey().getKey()).getSingleResult();
    
                //attribute.setKey(queryResult);
                attribute.getKey().setId(queryResult.getId());
            }
            catch (NoResultException e)
            {
                //em.persist(attribute.getKey());
                attribute.getKey().setId(null);
            }
    
            attribute.getKey().setLastUsed(new Date());
        }
    }
    
    @Entity
    @Table(name = "ATTRIBUTE")
    public class Attribute
    {
        @Id
        @SequenceGenerator...
        @GeneratedValue...
        @Column(name = "ID", unique = true, nullable = false)
        private Long id;
    
        @ManyToOne(cascade = {CascadeType.ALL}, optional = false, fetch = FetchType.EAGER)
        @JoinColumn(name = "ATTRIBUTE_KEY_ID", nullable = false, updatable = false)
        private AttributeKey key;
        ...
    }
    
    @Entity
    @Table(name = "ATTRIBUTE_KEY")
    @NamedQueries(...)
    public class AttributeKey
    {
        @Id
        @SequenceGenerator(...)
        @GeneratedValue(...)
        @Column(name = "ID", unique = true, nullable = false)
        private Long id;
    
        @Column(name = "KEY", length = 128, unique = true)
        private String key;
    
        @Column(name = "WEIGHT")
        private Long weight;
    
        @Column(name = "LAST_USED")
        private Date lastUsed;
        ...
    }