2

 在多对多关系中有两个类,Person 和 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;
  ...
4

1 回答 1

1

插入或更新之前的查询不是一个选项,因为有许多线程可以更新或插入。

但这是如何做到的。

如果是性能问题(我不这么认为),那么考虑使用二级缓存。第一级无法处理此问题,因为它绑定到一个会话,并且每个线程至少需要一个会话。

Person然后您需要在和中都有一个版本列Vehicle

在您的应用程序中,您已经遇到了以下问题: 1. 用户 A 加载了个人记录。2. 用户 B 加载相同的人员记录。3. 用户A修改电话号码并保存Person记录。4. 用户 B 修改了地址,也保存了人员记录。=> 结果:用户A的修改(电话号码更改)被覆盖,记录有旧的电话号码,没有人知道这个问题。

版本列避免了这个问题。当有版本列时,Hibernate 在步骤 4 中发现记录同时被修改并抛出异常。必须捕获此异常,并且必须告知用户 B 重新加载记录并重做他的地址更改。这迫使用户 B 做一些额外的工作(不多,因为这种情况很少发生),但不会丢失任何信息,并且数据库包含正确的信息。

当第一次阅读时没有找到记录时,您必须做同样的事情,但在插入时发现约束违规。你已经发现了这个错误,但你没有通知用户,你可能应该这样做。

在 Hibernate 级别对此没有简单的解决方案,因为应用程序逻辑必须处理这种情况(例如通知用户)。

于 2013-01-18T10:37:59.550 回答