我有以下 SQL 架构布局:
-- postgresql82+ syntax
create table AudioTracks (
id serial primary key
, name text
, size integer
, filePath text
, additionDate timestamp default now()
);
create table Genres (
id serial primary key
, name text unique -- here is the unique constraint which troubles me
, description text
, additionDate timestamp default now()
);
create table AudioTrackGenre (
genreId integer references Genres (id) unique
, audioTrackId integer references AudioTracks (id) unique
, additionDate timestamp default now()
);
Run Code Online (Sandbox Code Playgroud)
以及两个对应的表映射:
@Entity(name = "AudioTracks")
public class AudioTrack implements Serializable {
@Id
@Column
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
@Column
private String name;
@Column
private Integer size;
@Column
private String filePath;
@Column
@Temporal(TemporalType.TIMESTAMP)
private Date additionDate;
@ManyToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL )
@JoinTable(name = "AudioTrackGenre",
joinColumns = { @JoinColumn(name = "audioTrackId") },
inverseJoinColumns = { @JoinColumn(name = "genreId") }
)
@OrderBy("name")
private Set<Genre> genres = new HashSet<Genre>();
// setter/getter methods //
....
}
Run Code Online (Sandbox Code Playgroud)
和
@Entity(name = "Genres")
public class Genre implements Serializable {
@Id
@Column
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
@Column
private String name;
@Column
private String description;
@Column
@Temporal(TemporalType.TIMESTAMP)
private Date additionDate;
@ManyToMany(mappedBy = "genres")
private Set<AudioTrack> audioTracks = new HashSet<AudioTrack>();
public Genre() { }
public Genre(String name) { this.name = name; }
// setter/getter methods //
....
}
Run Code Online (Sandbox Code Playgroud)
但是每当我尝试保存 AudioTrack 时,都会填充流派表中已经存在的流派,如下所示:
Set<Genre> genres = new HashSet<Genre>();
genres.add(new Genre("ambient"));
AudioTrack track = new AudioTrack();
track.setGenres(genres);
audioTrackService.addAudioTrack(track);
Run Code Online (Sandbox Code Playgroud)
(该事情在最低 DAO 级别audioTrackService.addAudioTrack(track)执行)sessionFactory.getCurrentSession().save(track)
我正进入(状态:
ERROR: ERROR: duplicate key value violates unique constraint "genres_name_key"
Detail: Key (name)=(ambient) already exists.
Run Code Online (Sandbox Code Playgroud)
我如何告诉 Hibernate 不要尝试将已经存在的流派重新插入Genres级联插入表中?
如果该类型已存在,则必须提供其 ID。
看这一行:new Genre("ambient")。
hibernate 怎么可能猜测 Genre 环境的现有 id 是什么?
Hibernate 尝试插入相应的流派,因为您尚未提供其 id。
当您插入音轨时,hibernate 必须在 AudioTrackGenre 表中插入记录。Hibernate 必须知道流派的 id。否则,hibernate 会假设它们是新流派。
编辑:
看来您正在按需添加流派(例如 StackOverflow 标签)。
您可以在代码中执行以下操作:
for (String genreName : submittedTextGenres) {
Genre genre = genreDAO.findByName(genre);
if (genre == null) { //a new genre
genre = new Genre(genreName);
}
audioTrack.addGenre(genre);
}
Run Code Online (Sandbox Code Playgroud)
如果您担心并发用户添加相同的流派:(建议JB Nizet)
for (String genreName : submittedTextGenres) {
Genre genre = genreDAO.findByName(genre);
if (genre == null) { //a new genre
try {
genre = genreDAO.insertGenre(genre); //a transaction
} catch (GenreExistsException) {
genre = genreDAO.findByName(genre); //a separate transaction
}
}
audioTrack.addGenre(genre);
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
2464 次 |
| 最近记录: |