0

I want to persist a list with key-values pairs but I do not know how I can reach my objective with JPA. I can implement it with simple jdbc but I want to use jpa.

Requirements:

  1. prue JPA, I do not want to see any hibernate, eclipselink, etc. related imports in the java classes
  2. keys need to be unique in the database
  3. if the parent is deleted than value needs to be deleted but I need to keep keys in the database
  4. there can be same items in the list (same keys with different values OR same keys with same values)

Database tables:

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

use cases:

  1. If the "car type1" is deleted from the database then I want to keep keys in the attribute table. For example attribute with id 10 is only belongs to this product so I can delete this item from database without any sql exception (key is not used by other product) but I want to keep it in the table.

  2. New product with new keys: no problem, jpa store them

  3. New product with existing key:

    product.name=product A

    attributes: color-white|price-11usd|resolution-big

    New keys need to be inserted into the attribute-key table ("resolution") and after that persist values into the attribute table.

  4. Product with duplicated keys (and values) needs to be stored:

    product.name=product B

    attributes:color-red|color-green|color-green

  5. Product with duplicated NEW keys (keys are not persisted yet)

    product.name=product C

    attributes:attr1-value1|attr1-value2|...

My code works fine but there are two use-cases when it falls:

  1. There are items in the list with same keys and the key is not persisted yet (case 5). Jpa iterates on the list and persists the new key. When jpa wants to persist the next item with same key I get a "ERROR: duplicate key value violates unique constraint" exception because key is defined in the database as a unique field and it is stored in the first round.

  2. There is an item in the list with a key which is existing in the database. Exception: Multiple representations of the same entity

Code:

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

Is it possible to implement this logic with jpa?

zappee
  • 20,148
  • 14
  • 73
  • 129
  • It is impossible to use JPA without any ORM framework like Hibernate or EclipseLink. JPA is just a specification, and Hibernate or EclipseLink are its implementations. See here: http://stackoverflow.com/questions/9881611/whats-the-difference-between-jpa-and-hibernate – Szarpul Apr 22 '15 at 15:03
  • I know that JPA is a programming interface specification and there are many implementation of it like Hibernate, EclipseLink etc. I want to write independent java code so I only want to use classes from javax.persistence.* package. I do not want to use any extra feature/classes from Hibernate or EclipseLink. – zappee Apr 22 '15 at 20:33
  • If you stick to plain old JPA you can avoid the import of eclipse, hibernate etc classes. You CANNOT avoid including at least one of their JAR files as a library. You have to choose one or the other. If you stick to pure JPA you can migrate between the lot. – Namphibian Apr 22 '15 at 21:57
  • Also please post your table structures. What you are showing us is not clear. – Namphibian Apr 22 '15 at 22:00

0 Answers0