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

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

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

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

CREATE TABLE `team1` (
  `id` 
varchar(50NOT NULL,
  `name` 
varchar(50default 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,效率肯定会有一些影响

展开阅读全文

没有更多推荐了,返回首页