我有以下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()
);
表格的两个相应映射:
@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 //
....
}
和
@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 //
....
}
但是每当我试图保存AudioTrack时,填充Genres表中已经存在的Genres,就像这里一样:
Set<Genre> genres = new HashSet<Genre>();
genres.add(new Genre("ambient"));
AudioTrack track = new AudioTrack();
track.setGenres(genres);
audioTrackService.addAudioTrack(track);
(audioTrackService.addAudioTrack(track)
事件在最低DAO级别sessionFactory.getCurrentSession().save(track)
我得到了:
ERROR: ERROR: duplicate key value violates unique constraint "genres_name_key"
Detail: Key (name)=(ambient) already exists.
我如何告诉Hibernate不要尝试将现有类型重新插入到级联插入的Genres
表中?
答案 0 :(得分:3)
如果该类型已存在,则必须提供其ID。
请看这一行:new Genre("ambient")
。
hibernate怎么可能猜出Genre环境中现有的id是什么?
Hibernate尝试插入相应的类型,因为你没有提供它的id。
插入音轨时,hibernate必须在AudioTrackGenre表中插入记录。 Hibernate必须知道类型的ID。否则,休眠假设它们是新类型。
修改强>
您似乎在按需添加流派(如StackOverflow标记)。
您可以在代码中执行以下操作:
for (String genreName : submittedTextGenres) {
Genre genre = genreDAO.findByName(genre);
if (genre == null) { //a new genre
genre = new Genre(genreName);
}
audioTrack.addGenre(genre);
}
如果您害怕并发用户添加相同类型:( 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);
}