论坛首页 Java企业应用论坛

JPA实现自身的ManyTOMany映射

浏览 8046 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2007-12-27  

小弟最近学EJB3.0,写个小网站来练练手,中间也碰到一些问题。把解决过程写下来主要是怕自己忘了,如果能给大伙帮点忙,也算没白敲这些字了。

需求很简单:商品分类实体,一个商品分类既可以拥有多个子分类,比如水果分类下可以有苹果,香蕉等等。

也可以属于多个分类。比如剃须刀既可以属于小电器,也可以属于男士用品。

这就要用到JPA的@ManyToMany注释了。先创建分类表

java 代码
  1. create table category (   
  2.    cid                  integer              identity,   
  3.    cname                varchar(100)         null,   
  4.    constraint PK_CATEGORY primary key (cid)   
  5. )  

此外,使用ManyToMany映射还需要一张中间表来保存分类之间的关系从属关系

java 代码
  1. create table ctg_relation (   
  2.    upcid                integer              null,/*父类id*/  
  3.    cid                  integer              null/*子类Id*/  
  4. )  

废话少说,贴代码:

java 代码
  1. @Entity  
  2. public class Category {   
  3.     private int cid;   
  4.     private String cname;   
  5.     private List<Category> subCategories = new ArrayList();   
  6.     private List<Category> UpCategories = new ArrayList();   
  7.     @ManyToMany(cascade = { CascadeType.PERSIST }, fetch = FetchType.LAZY)   
  8.     @JoinTable(name = "ctg_relation", joinColumns = @JoinColumn(name = "upcid"), inverseJoinColumns = @JoinColumn(name = "cid"))   
  9.     public List<Category> getSubCategories() {   
  10.         return subCategories;   
  11.     }   
  12.   
  13.     public void setSubCategories(List<Category> subCategories) {   
  14.         this.subCategories = subCategories;   
  15.     }   
  16.   
  17.        
  18.     @ManyToMany(cascade = { CascadeType.PERSIST }, fetch = FetchType.LAZY)   
  19.     @JoinTable(name = "ctg_relation", joinColumns = @JoinColumn(name = "cid"), inverseJoinColumns = @JoinColumn(name = "upcid"))   
  20.     public List<Category> getUpCategories() {   
  21.         return UpCategories;   
  22.     }   
  23.     public void setUpCategories(List<Category> upCategories) {   
  24.         UpCategories = upCategories;   
  25.     }   
  26.   
  27.     @Id  
  28.     @GeneratedValue(strategy = GenerationType.AUTO)   
  29.     public int getCid() {   
  30.         return cid;   
  31.     }   
  32.   
  33.     public void setCid(int cid) {   
  34.         this.cid = cid;   
  35.     }   
  36.   
  37.     public String getCname() {   
  38.         return cname;   
  39.     }   
  40.   
  41.     public void setCname(String cname) {   
  42.         this.cname = cname;   
  43.     }   
  44.   
  45. }  

说明:

java 代码
  1. @ManyToMany(cascade = { CascadeType.PERSIST }, fetch = FetchType.LAZY)   
  2. @JoinTable(name = "ctg_relation", joinColumns = @JoinColumn(name = "upcid"), inverseJoinColumns = @JoinColumn(name = "cid"))   
  3. public List getSubCategories() {   
  4.  return subCategories;   
  5. }  

这个是对子类的映射,cascade设为PERSIST表示保存分类时,把所有的子类也一起保存。

@JoinTable注释指明了关联表是ctg_relation ,拥有方为upid(即父分类),被动方(inverseJoinColumns)是cid(即子分类)。

关于拥有方和被动方的概念我也没太搞清楚。我认为是两个实体关联时的“对方”作为被动方。大家请看下面那个ManyToMany注释

java 代码
  1. @ManyToMany(cascade = { CascadeType.PERSIST }, fetch = FetchType.LAZY)   
  2. @JoinTable(name = "ctg_relation", joinColumns = @JoinColumn(name = "cid"), inverseJoinColumns = @JoinColumn(name = "upcid"))   
  3.   
  4. public List getUpCategories() {   
  5.  return UpCategories;   
  6. }   

这是对本分类的上级分类的映射,此时就要把joinColumns改为cid(子分类),inverseJoinColumns改为upcid(父分类)。

写个测试类测试一下:

java 代码
  1. public class TestEntity implements TestEntityLocal, TestEntityRemote {   
  2.  @PersistenceContext  
  3.  private EntityManager em;   
  4.   
  5.  public void testCategory() {   
  6.   Category food = new Category();   
  7.   food.setCname("food");   
  8.   Category fruit = new Category();   
  9.   fruit.setCname("fruit");   
  10.   Category bananer = new Category();   
  11.   bananer.setCname("bananer");   
  12.   fruit.getUpCategories().add(food);   
  13.   bananer.getUpCategories().add(fruit);   
  14.   bananer.getUpCategories().add(food);   
  15.   em.persist(bananer);   
  16.  }   
  17.   
  18. }   

 结果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就没搞明白,请大家一起讨论讨论

 

 

论坛首页 Java企业应用版

跳转论坛:
Global site tag (gtag.js) - Google Analytics