我想保留一个包含键值对的列表,但我不知道如何通过JPA实现我的目标。我可以用简单的jdbc实现它,但我想使用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
...
用例:
如果"汽车类型1"从数据库中删除然后我想保留属性表中的键。例如,id为10的属性只属于这个产品,所以我可以从数据库中删除这个项目而没有任何sql异常(其他产品没有使用密钥)但是我想把它保存在表格中。
带有新密钥的新产品:没问题,jpa存储它们
使用现有密钥的新产品:
product.name =产品A
属性:color-white | price-11usd | resolution-big
需要将新密钥插入属性 - 密钥表(" resolution"),然后将剩余的值插入到属性表中。
需要存储具有重复键(和值)的产品:
product.name =产品B
属性:彩色红色|颜色绿色|色绿色
带有重复新密钥的产品(密钥尚未保留)
product.name = product C
属性:attR1位-VALUE1 | attR1位-值2 | ...
我的代码工作正常,但有两个用例:
列表中的项目具有相同的密钥,并且密钥尚未保留(案例5)。 Jpa迭代列表并持久保存新密钥。当jpa想要使用相同的密钥持久保存下一个项目时,我得到一个"错误:重复的密钥值违反了唯一约束"异常,因为密钥在数据库中定义为唯一字段,并存储在第一轮中。
列表中有一个项目,其中包含一个存在于数据库中的密钥。 例外:同一实体的多个表示
代码:
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实现这个逻辑?