【发布时间】:2013-01-18 10:04:23
【问题描述】:
在多对多关系中有两个类,Person 和 Vehicle。如果创建了新的 Person 或更新了现有 Person 的记录(例如添加了 Vehicle 记录),则最好使用现有的 Vehicle 记录(如果存在)。
问题是如何实现它。插入或更新之前的查询不是一个选项,因为有许多线程可以更新或插入。
此时,应用程序检查唯一约束异常,当它被捕获时,新的现有车辆对象被替换为从数据库中通过“注册”列查询的对象。此解决方案有效,但它似乎有点笨拙,因为必须为每个车辆记录创建单独的会话。
有什么方法可以通过休眠注释实现所需的行为?还是完全不同的解决方案?谢谢。
@Entity
@Table(name="PERSON", uniqueConstraints = { @UniqueConstraint(columnNames = "name", name="NAME_KEY") })
public class Person implements Serializable {
private static final long serialVersionUID = 3507716047052335731L;
@Id
@GeneratedValue(strategy=GenerationType.SEQUENCE, generator="PersonIdSeq")
@SequenceGenerator( name = "PersonIdSeq", sequenceName="PERSON_ID_SEQ")
private Long id;
@Index(name="PERSON_NAME_IDX")
private String name;
@ManyToMany(targetEntity=Vehicle.class, cascade={CascadeType.PERSIST, CascadeType.MERGE})
@JoinTable(name="PERSON_VEHICLE_LNK", joinColumns=@JoinColumn(name="PERSON_ID"),inverseJoinColumns=@JoinColumn(name="VEHICLE_ID"),
uniqueConstraints = { @UniqueConstraint(columnNames = {"PERSON_ID", "VEHICLE_ID"}, name="person_vehicle_lnk_key")})
@GeneratedValue(strategy=GenerationType.SEQUENCE, generator="PersonVehicleLnkIdSeq")
@SequenceGenerator(name = "PersonVehicleLnkIdSeq", sequenceName="PERSON_VEHICLE_LNK_ID_SEQ")
@CollectionId(columns = @Column(name="ID"), type=@Type(type="long"), generator = "PersonVehicleLnkIdSeq")
private List<Vehicle> vehicle = new ArrayList<>();
...
@Entity
@Table( name = "VEHICLE", uniqueConstraints = {@UniqueConstraint(columnNames="registration", name="REGISTRATION_KEY")} )
public class Vehicle implements Serializable {
private static final long serialVersionUID = -5592281235230216382L;
@Id
@GeneratedValue(strategy=GenerationType.SEQUENCE, generator="VehicleIdSeq")
@SequenceGenerator( name = "VehicleIdSeq", sequenceName="VEHICLE_ID_SEQ")
private Long id;
@Index(name="REGISTRATION_IDX")
private String registration;
...
【问题讨论】:
-
在 MySQL 中是
INSERT ... ON DUPLICATE KEY UPDATE ... -
尝试以下操作:尝试插入;如果失败,请更新。如果还有并发删除,这可能需要多轮尝试。
-
感谢。我确定这是数据库级别的解决方案,但我宁愿留在 ORM 级别。
-
您可以在对象级别执行更新重试循环。
-
实际上,正如我在问题中所说,我已经在这样做了,但是我对解决方案不满意,因为对于每条车辆记录,都必须打开一个新会话,如果它失败了必须回滚并且必须创建另一个新会话以从表中查询现有记录。
标签: java hibernate many-to-many unique-constraint