在多对多关系中有两个类,Person和Vehicle。如果创建了新的Person或更新了现有Person的记录(例如添加了Vehicle记录),则可能需要使用现有的Vehicle记录(如果存在)。
问题是如何实现它。插入或更新之前的查询不是一个选项,因为有许多线程可以更新或插入。
此时,应用程序检查唯一约束异常,当捕获它时,新的现有Vehicle对象将替换为通过“registration”列从db查询的对象。这个解决方案正在运行,但它似乎有点笨拙,因为必须为每个Vehicle记录创建一个单独的会话。
有什么方法可以通过hibernate注释实现所需的行为?还是完全不同的解决方感谢。
@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;
...
答案 0 :(得分:1)
插入或更新之前的查询不是一个选项,因为有许多线程可以更新或插入。
但这是怎么做的。
如果是性能问题(我不这么认为),那么请考虑使用二级缓存。第一级无法处理,因为它绑定到一个会话,每个线程至少需要一个会话。
然后,您需要Person
和Vehicle
中的版本列。
在您的应用程序中,您已经遇到以下问题:1。用户A加载了人员记录。 2.用户B加载相同的Person记录。 3.用户A修改电话号码并保存人员记录。 4.用户B修改地址并保存人员记录。 =&GT;结果:用户A的修改(电话号码变更)被覆盖,记录中有旧电话号码,没有人知道此问题。
版本列可以避免此问题。当有版本列时,在步骤4中,Hibernate发现记录在此期间被修改并抛出异常。必须捕获此异常,并且必须告知用户B重新加载记录并重做其地址更改。这迫使用户B做了一些额外的工作(不多见,因为这种情况很少发生),但没有信息丢失,数据库包含正确的信息。
在第一次阅读时没有找到记录时你必须这样做,但是在插入时会捕获约束违规。您已经捕获了此错误,但是您没有通知用户,您可能应该这样做。
Hibernate级别没有简单的解决方案,因为应用程序逻辑必须处理这种情况(例如通知用户)。