Hibernate一对多使用Map和Set的区别

 使用Map和Set的集合映射,都可以配合1对多,但是其中还是有细微的差别,主要体现在一方的inverse属性上

数据库结构如下:
其中member表的team字段对应team的id

CREATE   TABLE  `member1` (
  `id` 
varchar ( 50 NOT   NULL ,
  `name` 
varchar ( 50 default   NULL ,
  `age` 
varchar ( 50 default   NULL ,
  `teamRole` 
varchar ( 50 default   NULL ,
  `team` 
varchar ( 50 default   NULL ,
  
PRIMARY   KEY   (`id`)
) ENGINE
= InnoDB  DEFAULT  CHARSET = gb2312;

CREATE   TABLE  `team1` (
  `id` 
varchar ( 50 NOT   NULL ,
  `name` 
varchar ( 50 default   NULL ,
  
PRIMARY   KEY   (`id`)
) ENGINE
= InnoDB  DEFAULT  CHARSET = gb2312;

 

持久话类(使用Set方式)

 

package  maponetomany;

public   class  Member  {
    
private String id;
   
private String name;
   
private String teamRole;
   
private Team team;
   
private String age;
public String getAge() {
    
return age;
}

public void setAge(String age) {
    
this.age = age;
}


public String getName() {
    
return name;
}

public void setName(String name) {
    
this.name = name;
}



public String getTeamRole() {
    
return teamRole;
}

public void setTeamRole(String teamRole) {
    
this.teamRole = teamRole;
}

public String getId() {
    
return id;
}

public void setId(String id) {
    
this.id = id;
}

public Team getTeam() {
    
return team;
}

public void setTeam(Team team) {
    
this.team = team;
}

}


package  maponetomany;

import  java.util.HashSet;
import  java.util.Map;
import  java.util.Set;

public   class  Team  {
   
private String id;
   
private String name;
   
private Set members=new HashSet();
public String getId() {
    
return id;
}

public void setId(String id) {
    
this.id = id;
}


public Set getMembers() {
    
return members;
}

public void setMembers(Set members) {
    
this.members = members;
}

public String getName() {
    
return name;
}

public void setName(String name) {
    
this.name = name;
}

}


这是相应的HBM映射文件
<? xml version="1.0" encoding="utf-8" ?>
<! DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"
>
<!--  
    Mapping file autogenerated by MyEclipse - Hibernate Tools
-->
< hibernate-mapping  package ="maponetomany" >
   
    
     
< class  name ="Member"  table ="member1" >
       
< id  name ="id"  column ="id" >
         
< generator  class ="uuid.hex" ></ generator >
       
</ id >
       
< property  name ="name"  column ="name" />
       
< property  name ="age"  column ="age" />
       
< property  name ="teamRole"  column ="teamRole"   />
       
< many-to-one  name ="team"  column ="team"   />
    
</ class >
</ hibernate-mapping >


<? xml version="1.0" encoding="utf-8" ?>
<! DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"
>
<!--  
    Mapping file autogenerated by MyEclipse - Hibernate Tools
-->
< hibernate-mapping  package ="maponetomany" >
    
< class  name ="Team"  table ="team1" >
       
< id  name ="id"  column ="id" >
         
< generator  class ="uuid.hex" ></ generator >
       
</ id >
       
< property  name ="name"  column ="name" />
       
< set  name ="members"  inverse ="true"  cascade ="save-update" >
          
< key  column ="team" />
          
< one-to-many  class ="Member" />
       
</ set >
    
</ class >
</ hibernate-mapping >

以下是测试代码:
这里要注意的是,member的teamRole属性是通过javabean的set方式注入的,用Map实现时,则是作为map的index属性去注入,没有在代码中显示的调用set方法,这也是本文讨论的重点
public   static   void  main(String[] args)  {
        Configuration cfg
=new Configuration();
        cfg.configure();
        SessionFactory sf
=cfg.buildSessionFactory();
        Session session
=sf.openSession();
        Transaction t
=session.beginTransaction();

        Team team
=new Team();
        team.setName(
"足球队-01");
        

        
        Member m1
=new Member();
        m1.setName(
"01队01号");
        m1.setAge(
"22");
        m1.setTeam(team);
        m1.setTeamRole(
"中后卫");
        
        Member m2
=new Member();
        m2.setName(
"01队02号");
        m2.setAge(
"33");
        m2.setTeam(team);
        m2.setTeamRole(
"守门员");
        
        team.getMembers().add(m1);
        team.getMembers().add(m2);

       
        session.save(team);


        t.commit();
        System.out.println(
"success");

    }


运行结果如下:
Hibernate: insert into team1 (name, id) values (?, ?)
Hibernate: insert into member1 (name, age, teamRole, team, id) values (?, ?, ?, ?, ?)
Hibernate: insert into member1 (name, age, teamRole, team, id) values (?, ?, ?, ?, ?)

可以看到,两个表的数据都插入了,而且关联正确(member的team值为team表的id)

如果我们改成Map方式,则需要改变持久话类的代码和映射文件,如下:
持久话类变化不大,只不过是把Set换成Map,但映射文件变化较大

 

package  maponetomany;

public   class  Member  {
    
private String id;
   
private String name;
   
private String teamRole;
   
private Team team;
   
private String age;
public String getAge() {
    
return age;
}

public void setAge(String age) {
    
this.age = age;
}


public String getName() {
    
return name;
}

public void setName(String name) {
    
this.name = name;
}



public String getTeamRole() {
    
return teamRole;
}

public void setTeamRole(String teamRole) {
    
this.teamRole = teamRole;
}

public String getId() {
    
return id;
}

public void setId(String id) {
    
this.id = id;
}

public Team getTeam() {
    
return team;
}

public void setTeam(Team team) {
    
this.team = team;
}

}



package  maponetomany;

import  java.util.HashMap;
import  java.util.Map;

public   class  Team  {
   
private String id;
   
private String name;
   
private Map members=new HashMap();
public String getId() {
    
return id;
}

public void setId(String id) {
    
this.id = id;
}



public Map getMembers() {
    
return members;
}

public void setMembers(Map members) {
    
this.members = members;
}

public String getName() {
    
return name;
}

public void setName(String name) {
    
this.name = name;
}

}


<? xml version="1.0" encoding="utf-8" ?>
<! DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"
>
<!--  
    Mapping file autogenerated by MyEclipse - Hibernate Tools
-->
< hibernate-mapping  package ="maponetomany" >
   
    
     
< class  name ="Member"  table ="member1" >
       
< id  name ="id"  column ="id" >
         
< generator  class ="uuid.hex" ></ generator >
       
</ id >
       
< property  name ="name"  column ="name" />
       
< property  name ="age"  column ="age" />

      //这里缺少了
< property  name ="teamRole"  column ="teamRole" />  因为这个属性不再由set方式注入,换成map的index

       
< many-to-one  name ="team"  column ="team"   />
    
</ class >
</ hibernate-mapping >

<? xml version="1.0" encoding="utf-8" ?>
<! DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"
>
<!--  
    Mapping file autogenerated by MyEclipse - Hibernate Tools
-->
< hibernate-mapping  package ="maponetomany" >
    
< class  name ="Team"  table ="team1" >
       
< id  name ="id"  column ="id" >
         
< generator  class ="uuid.hex" ></ generator >
       
</ id >
       
< property  name ="name"  column ="name" />
       
< map  name ="members"  inverse ="true"  cascade ="save-update" >
          
< key  column ="team" />
          
< index  type ="string"  column ="teamRole" />    //map映射,把index映射成teamRole字段
          
< one-to-many  class ="Member" />
       
</ map >
    
</ class >
</ hibernate-mapping >

测试代码做一些相应的调整
     public   static   void  main(String[] args)  {
        Configuration cfg
=new Configuration();
        cfg.configure();
        SessionFactory sf
=cfg.buildSessionFactory();
        Session session
=sf.openSession();
        Transaction t
=session.beginTransaction();

        Team team
=new Team();
        team.setName(
"足球队-01");
        

        
        Member m1
=new Member();
        m1.setName(
"01队01号");
        m1.setAge(
"22");
        m1.setTeam(team);
        m1.setTeamRole(
"中后卫");
        
        Member m2
=new Member();
        m2.setName(
"01队02号");
        m2.setAge(
"33");
        m2.setTeam(team);
        m2.setTeamRole(
"守门员");
        

        team.getMembers().put(
"守门员", m1);
        team.getMembers().put(
"中后卫", m2);
       
        session.save(team);


        t.commit();
        System.out.println(
"success");

    }


运行代码:
Hibernate: insert into team1 (name, id) values (?, ?)
Hibernate: insert into member1 (name, age, team, id) values (?, ?, ?, ?)
Hibernate: insert into member1 (name, age, team, id) values (?, ?, ?, ?)

可以发现,这是不正确的,虽然关联正常,但是member的teamRole字段没有写入,原因就是因为我们在1方还是设置成inverse="true" 这在使用set方式时候,由多方来进行关系维护可以带来效率的提升,但是,在使用Map的时候,由于member的teamRoles属性是定义在1方的,所以,为了能正确的写入teamRoles,必须要在1方设置inverse="false"

 

修改后的HQL如下:

Hibernate: insert into team1 (name, id) values (?, ?)
Hibernate: insert into member1 (name, age, team, id) values (?, ?, ?, ?)
Hibernate: insert into member1 (name, age, team, id) values (?, ?, ?, ?)
Hibernate: update member1 set team=?, teamRole=? where id=?
Hibernate: update member1 set team=?, teamRole=? where id=?

 

可以看到,数据都正确了,hibernate用了两个update来进行更新teamRole字段

 

PS:不知道Map映射有什么好处,要是数据大,会有很多update,效率肯定会有一些影响

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值