与JPA有多对一的关系

时间:2015-04-21 21:06:35

标签: jpa arraylist many-to-one

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

要求:

  1. prue J​​PA,我不希望在java类中看到任何与hibernate,eclipselink等相关的导入
  2. 密钥在数据库中必须是唯一的
  3. 如果父项被删除,则需要删除值,但我需要将密钥保存在数据库中
  4. 列表中可以有相同的项目(具有不同值的相同键或具有相同值的相同键)
  5. 数据库表:

    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
    ...
    

    用例:

    1. 如果"汽车类型1"从数据库中删除然后我想保留属性表中的键。例如,id为10的属性只属于这个产品,所以我可以从数据库中删除这个项目而没有任何sql异常(其他产品没有使用密钥)但是我想把它保存在表格中。

    2. 带有新密钥的新产品:没问题,jpa存储它们

    3. 使用现有密钥的新产品:

      product.name =产品A

      属性:color-white | price-11usd | resolution-big

      需要将新密钥插入属性 - 密钥表(" resolution"),然后将剩余的值插入到属性表中。

    4. 需要存储具有重复键(和值)的产品:

      product.name =产品B

      属性:彩色红色|颜色绿色|色绿色

    5. 带有重复新密钥的产品(密钥尚未保留)

      product.name = product C

      属性:attR1位-VALUE1 | attR1位-值2 | ...

    6. 我的代码工作正常,但有两个用例:

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

      2. 列表中有一个项目,其中包含一个存在于数据库中的密钥。 例外:同一实体的多个表示

      3. 代码:

        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;
            ...
        }
        

        是否可以用jpa实现这个逻辑?

0 个答案:

没有答案