假设我们有4个实体:电影,工作室,网站和标签。电影,工作室和网站可以具有0个或多个标签(每个标签具有0到多个标签)。电影有0或1个站点(一个站点有0到许多电影)。电影有0个或多个制片厂(一个电影制片厂有0到许多电影)。我通过如下介绍TagCollection和StudioCollection实现了这些关系。 TagCollection具有与Movie的oneToOne映射,以及具有Tag的manyToMany(与StudioCollection相同)。我这样做是因为:
该计划失败了,因为当我保存带有某些标签的电影并进行检索时,这些标签将链接到制片厂或除原始所有者以外的任何其他实体。测试如下(随后是代码)。知道我在做什么错吗?我怀疑链接表中的ID是错误的,但是我无法证明这一点,也看不出为什么会发生这种情况(这不是由于输入错误或不良影响所致)。完整的代码已发布here,以防万一,但下面是我的实现和测试失败的一部分。谢谢。
@Test
public void addedMoviesWithAttributesArePersisted() {
final MovieBuilder mb = new MovieBuilder();
mb.title("Title");
// Add a site to the movie
final Site site = new Site("Site TEst");
mb.site(site);
//Add 2 studios to the movie
final Studio studio1 = new Studio("Studio 1");
final Studio studio2 = new Studio("Studio 2");
final StudioCollection studioCollection = new StudioCollection();
studioCollection.add(Sets.newSet(studio1, studio2));
mb.studioCollections(studioCollection);
// Add 2 tags to the movie
final Tag tag1 = new Tag("Tag 1");
final Tag tag2 = new Tag("Tag 2");
final TagCollection tagCollection = new TagCollection();
tagCollection.add(Sets.newSet(tag1, tag2));
mb.tagCollection(tagCollection);
final Movie movie = mb.build();
this.underTest.persist(movie);
final Set<Movie> foundMovies = this.underTest.findByTitle("Title");
assertFalse(foundMovies.isEmpty());
assertEquals(1, foundMovies.size());
assertTrue(foundMovies.contains(movie));
final Movie foundMovie = foundMovies.iterator().next();
// This fails
assertFalse(foundMovie.getTagCollection().isEmpty());
// Querying for all entities gives this results
this.underTest.getAll();
// TagCollection: id=[1] Values=[[]]
// TagCollection: id=[2] Values=[[Tag [id=1, tagName=Tag 1], Tag [id=2, tagName=Tag 2]]]
// TagCollection: id=[3] Values=[[]]
// TagCollection: id=[4] Values=[[]]
// Site: id=[1] + Name=Site TEst] + tag=[TagCollection: id=[1] Values=[[]]]
// Studio id=[1] + Name=Studio 2] + tag=[TagCollection: id=[1] Values=[[]]]
// Studio id=[2] + Name=Studio 1] + tag=[TagCollection: id=[2] Values=[[Tag [id=1, tagName=Tag 1], Tag [id=2, tagName=Tag 2]]]]
// Movie: id=[1] + Title=Title] + tag=[TagCollection: id=[1] Values=[[]]]
}
这就是我现在的情况: 标签类别
@Entity
@Table(name = "TAG")
public final class Tag {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
@NotNull
@NotEmpty
@Size(min = 1)
@Column(unique = true, nullable = false)
private String tagName;
// Getter & Setter and constructors
}
标签集合:
@Entity
@Table(name = "TAG_COLLECTION")
public class TagCollection {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private long id;
@ManyToMany(fetch = FetchType.EAGER, cascade = { CascadeType.PERSIST, CascadeType.MERGE, CascadeType.REFRESH })
@JoinTable(name = "tag_link", joinColumns = @JoinColumn(name = "tagCollection_id"), inverseJoinColumns = @JoinColumn(name = "tag_id"))
private final Set<Tag> tags = new HashSet<>();
// Getter & Setter and constructors
}
站点:
@Entity
@Table(name = "SITE")
public class Site implements MovieEntity {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
@NotNull
@NotEmpty
@Size(min = 1)
@Column(unique = true, nullable = false)
private String name;
@OneToOne(cascade = { CascadeType.PERSIST, CascadeType.MERGE, CascadeType.REFRESH })
@JoinColumn(name = "id")
private final TagCollection tags = new TagCollection();
// Getter & Setter and constructors
}
工作室:
@Entity
@Table(name = "STUDIO")
public class Studio implements MovieEntity, Representable, Taggable {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
@NotNull
@NotEmpty
@Size(min = 1)
@Column(unique = true, nullable = false)
private String name;
@OneToOne(cascade = { CascadeType.PERSIST, CascadeType.MERGE, CascadeType.REFRESH })
@JoinColumn(name = "id")
private final TagCollection tags = new TagCollection();
// Getter & Setter and constructors
}
Studio Collection:
@Entity
@Table(name = "STUDIO_COLLECTION")
public class StudioCollection {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private long id;
@ManyToMany(fetch = FetchType.EAGER, cascade = { CascadeType.PERSIST, CascadeType.MERGE, CascadeType.REFRESH })
@JoinTable(name = "studio_link", joinColumns = @JoinColumn(name = "studioCollection_id"), inverseJoinColumns = @JoinColumn(name = "studio_id"))
private final Set<Studio> studios = new HashSet<>();
// Getter & Setter and constructors
}
电影:
@Entity
@Table(name = "MOVIE")
public class Movie {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
@Column(unique = false, nullable = false)
private String title;
@OneToOne(cascade = { CascadeType.PERSIST, CascadeType.MERGE, CascadeType.REFRESH })
@JoinColumn(name = "id")
private final TagCollection tagCollection = new TagCollection();
@OneToOne(cascade = { CascadeType.PERSIST, CascadeType.MERGE, CascadeType.REFRESH })
@JoinColumn(name = "id")
private final StudioCollection studioCollection = new StudioCollection();
@ManyToOne(cascade = { CascadeType.PERSIST, CascadeType.MERGE, CascadeType.REFRESH })
@JoinColumn(name = "site_id")
private Site site;
// Getter & Setter and constructors
}
答案 0 :(得分:0)
这似乎是您所描述的:
但是看来您的实体不符合您的概念模型。您可以像这样对上面的ER图建模:
@Entity
public class Tag {
@Id @GeneratedValue private int id;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
@ManyToMany private Set<Movie> movieTags;
@ManyToMany private Set<Studio> studioTags;
@ManyToMany private Set<Site> siteTags;
@Entity
public class Movie {
@Id @GeneratedValue private int id;
@ManyToMany(mappedBy="movieTags") private Set<Tag> tags;
@ManyToOne private Studio studio;
@ManyToOne private Site site;
@Entity
public class Site {
@Id @GeneratedValue private int id;
@ManyToMany(mappedBy="siteTags") private Set<Tag> tags;
@OneToMany(mappedBy="site") private Set<Movie> movies;
@Entity
public class Studio {
@Id @GeneratedValue private int id;
@ManyToMany(mappedBy="studioTags") private Set<Tag> tags;
@OneToMany(mappedBy="studio") private Set<Movie> movies;
并像这样使用它:
tx.begin();
Tag tag = new Tag();
Movie movie = new Movie();
Studio studio = new Studio();
Site site = new Site();
tag.setMovies(new HashSet<>(Arrays.asList(movie)));
tag.setStudios(new HashSet<>(Arrays.asList(studio)));
tag.setSites(new HashSet<>(Arrays.asList(site)));
site.setMovies(new HashSet<>(Arrays.asList(movie)));
studio.setMovies(new HashSet<>(Arrays.asList(movie)));
em.persist(movie);
em.persist(site);
em.persist(studio);
em.persist(tag);
tx.commit();
em.clear();
List<Tag> r = em.createQuery("select distinct t from Tag t left join fetch t.movieTags left join fetch t.studioTags left join fetch t.siteTags", Tag.class).getResultList();
System.out.println(r.get(0)
+ Arrays.toString(r.get(0).getMovies().toArray())
+":"+Arrays.toString(r.get(0).getStudios().toArray())
+":"+Arrays.toString(r.get(0).getSites().toArray()));