Моя модель домена Hibernate-JPA имеет следующие объекты:
AttributeType ------< AttributeValue
Соответствующие классы Java выглядят следующим образом (методы получения и установки отсутствуют):
@Entity
public class AttributeType {
@Id @GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
@Column(unique = true, nullable = false)
private String name;
@OneToMany(mappedBy = "attributeType", cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.EAGER)
private List<AttributeValue> values = new ArrayList<AttributeValue>();
}
@Entity @Table(uniqueConstraints = @UniqueConstraint(columnNames = {"value", "attribute_type_id"}))
public class AttributeValue {
@Id @GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
@ManyToOne(optional = false)
private AttributeType attributeType;
@Column(nullable = false)
private String value;
}
Обратите внимание, что есть уникальное ограничение на AttributeValue.value
и AttributeValue.attributeType
, потому что для типа атрибута (например, размера) мы не хотим, чтобы значение атрибута (например, маленькое) встречалось более одного раза.
Если я обновлю AttributeType
, выполнив следующие операции в одной транзакции:
- удалить значение атрибута "small" из типа атрибута "size"
- добавить значение атрибута "small" к типу атрибута "size"
Я получаю исключение, которое указывает, что ограничение уникальности было нарушено. Это говорит о том, что Hibernate-JPA выполняет вставку значения атрибута перед удалением, что, по-видимому, создает проблему такого рода без видимой причины.
Класс, который выполняет обновление AttributeType
, выглядит следующим образом:
@Transactional(propagation = Propagation.SUPPORTS)
public class SomeService {
private EntityManager entityManager; // set by dependency injection
@Transactional(propagation = Propagation.REQUIRED)
public AttributeType updateAttributeType(AttributeType attributeType) throws Exception {
attributeType = entityManager.merge(attributeType);
entityManager.flush();
entityManager.refresh(attributeType);
return attributeType;
}
}
Я мог бы обойти эту проблему, перебирая значения атрибутов, выясняя, какие из них были обновлены / удалены / вставлены, и выполняя их в следующем порядке:
- удаляет
- обновления
- Вставка
Но похоже, что ORM должен сделать это для меня. Я читал, что Oracle предоставляет опцию «deferConstraints», которая позволяет проверять ограничения только после завершения транзакции. Однако я использую SQL Server, поэтому это мне не поможет.