小弟最近学EJB3.0,写个小网站来练练手,中间也碰到一些问题。把解决过程写下来主要是怕自己忘了,如果能给大伙帮点忙,也算没白敲这些字了。
需求很简单:商品分类实体,一个商品分类既可以拥有多个子分类,比如水果分类下可以有苹果,香蕉等等。
也可以属于多个分类。比如剃须刀既可以属于小电器,也可以属于男士用品。
这就要用到JPA的@ManyToMany注释了。先创建分类表
java 代码
- create table category (
- cid integer identity,
- cname varchar(100) null,
- constraint PK_CATEGORY primary key (cid)
- )
此外,使用ManyToMany映射还需要一张中间表来保存分类之间的关系从属关系
java 代码
- create table ctg_relation (
- upcid integer null,
- cid integer null
- )
废话少说,贴代码:
java 代码
- @Entity
- public class Category {
- private int cid;
- private String cname;
- private List<Category> subCategories = new ArrayList();
- private List<Category> UpCategories = new ArrayList();
- @ManyToMany(cascade = { CascadeType.PERSIST }, fetch = FetchType.LAZY)
- @JoinTable(name = "ctg_relation", joinColumns = @JoinColumn(name = "upcid"), inverseJoinColumns = @JoinColumn(name = "cid"))
- public List<Category> getSubCategories() {
- return subCategories;
- }
-
- public void setSubCategories(List<Category> subCategories) {
- this.subCategories = subCategories;
- }
-
-
- @ManyToMany(cascade = { CascadeType.PERSIST }, fetch = FetchType.LAZY)
- @JoinTable(name = "ctg_relation", joinColumns = @JoinColumn(name = "cid"), inverseJoinColumns = @JoinColumn(name = "upcid"))
- public List<Category> getUpCategories() {
- return UpCategories;
- }
- public void setUpCategories(List<Category> upCategories) {
- UpCategories = upCategories;
- }
-
- @Id
- @GeneratedValue(strategy = GenerationType.AUTO)
- public int getCid() {
- return cid;
- }
-
- public void setCid(int cid) {
- this.cid = cid;
- }
-
- public String getCname() {
- return cname;
- }
-
- public void setCname(String cname) {
- this.cname = cname;
- }
-
- }
说明:
java 代码
- @ManyToMany(cascade = { CascadeType.PERSIST }, fetch = FetchType.LAZY)
- @JoinTable(name = "ctg_relation", joinColumns = @JoinColumn(name = "upcid"), inverseJoinColumns = @JoinColumn(name = "cid"))
- public List getSubCategories() {
- return subCategories;
- }
这个是对子类的映射,cascade设为PERSIST表示保存分类时,把所有的子类也一起保存。
@JoinTable注释指明了关联表是ctg_relation ,拥有方为upid(即父分类),被动方(inverseJoinColumns)是cid(即子分类)。
关于拥有方和被动方的概念我也没太搞清楚。我认为是两个实体关联时的“对方”作为被动方。大家请看下面那个ManyToMany注释
java 代码
- @ManyToMany(cascade = { CascadeType.PERSIST }, fetch = FetchType.LAZY)
- @JoinTable(name = "ctg_relation", joinColumns = @JoinColumn(name = "cid"), inverseJoinColumns = @JoinColumn(name = "upcid"))
-
- public List getUpCategories() {
- return UpCategories;
- }
这是对本分类的上级分类的映射,此时就要把joinColumns改为cid(子分类),inverseJoinColumns改为upcid(父分类)。
写个测试类测试一下:
java 代码
- public class TestEntity implements TestEntityLocal, TestEntityRemote {
- @PersistenceContext
- private EntityManager em;
-
- public void testCategory() {
- Category food = new Category();
- food.setCname("food");
- Category fruit = new Category();
- fruit.setCname("fruit");
- Category bananer = new Category();
- bananer.setCname("bananer");
- fruit.getUpCategories().add(food);
- bananer.getUpCategories().add(fruit);
- bananer.getUpCategories().add(food);
- em.persist(bananer);
- }
-
- }
结果Hibernate写了如下语句:
22:06:17,703 INFO [STDOUT] Hibernate: insert into Category (cseq, cname) values (?, ?)
22:06:17,703 INFO [STDOUT] Hibernate: insert into Category (cseq, cname) values (?, ?)
22:06:17,703 INFO [STDOUT] Hibernate: insert into Category (cseq, cname) values (?, ?)
22:06:17,718 INFO [STDOUT] Hibernate: insert into ctg_relation (cid, upcid) values (?, ?)
22:06:17,718 INFO [STDOUT] Hibernate: insert into ctg_relation (cid, upcid) values (?, ?)
22:06:17,718 INFO [STDOUT] Hibernate: insert into ctg_relation (cid, upcid) values (?, ?)
前三个分别是插入food,fruit,banner
后三个往关系表中插入他们之间的关系
小弟初学乍练,不足之处请大家指点。比如这个inverseJoinColumns就没搞明白,请大家一起讨论讨论