数据库中表与表之间可以有一对多和多对多的关联关系,要在hibernate中映射表之间的关系时,就需要使用hibernate中的集合映射,所以很有必须了首先了解一下JDK中的常见的集合类型,再来学习如何映射这些集合类型。
< 一> jdk中常见的集合类型
JDK中常见的集合类型有Set,List,Map及各自的实现类。
1,Set 接口
Set 是一个接口,实例化的是其实现类,常用到的实现类是:HashSet,LinkedHashSet,TreeSet 。
Set的特点是:加入的对象不得,并且固定顺序。HashSet内部使用hash算法保存元素对象,存取对象拉开距离芘其他实现类,是最常用的Set接口实现类; LinkedHashSet是HashSet的子类,内部使用链表数据结构保存数据,有固定顺序;TreeSet会排序保存的对象,被保存的对象要实现comparable接口,TreeSet按照重写的comparableTo()方法排序。
2,List接口
List对象包含的对象可以重复添加,并且记录添加的顺序.ArrayList和LinkedList是list接口的常用实现类。ArrayList类的内部使用数组来实现集合功能,所以对于随机读取添加的对象可以获得较好的效率.但是很显然,在使用ArrayList对象移除或者插入新对象时,其效率很低。LinkedList的在内部使用链表形式保存数据,因此从LinkedList对象中移除数据或者增加元素效率更高。
3,Map接口
Map对象中保存key/value形式的一对对象,key与value都是Object类型的变量 。二者是一对一的关系,key的值必须是唯一的。如果后加入的元素的key值在Map中已经存在,则将替换到原来的值.
Map常用实现类是HashMap,LinkedHashMap,TreeMap 。HashMap是基于哈希表的Map接口的实现,允许null作为key或者value的值。不记录key/value的顺序,且不保证 线程安全,查找key/value的效率比较高;LinkedHashMap内部使用链表保存元素,记录添加的顺序;TreeMap实现了Map和SortedMap接口,内部使用红黑树算法来排序加入的对象,还可以自定义排序规则实现排序功能,另外TreeMap中还有定义了一些自己的方法。Map接口的测试代码如下:
package cn.edu.ccnu.lwm;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
/**
* Map对象中以key/value对的形式保存对象,key和value都是Object类型的变量,
* 且key的值在一个map对象内必须是唯一的。
* 如果后加入的元素的key值在Map中已经存在,则将替换到原来的值.
* Map接口的常用实现类有HashMap,LinkedHashMap,TreeMap .
* HashMap是基于哈希表的Map接口的实现,允许null作为key或者value的值。不记录key/value的顺序,且不保证
* 线程安全,查找key/value的效率比较高。
* LinkedHashMap内部使用链表保存元素,记录添加的顺序!
* TreeMap实现了Map和SortedMap接口,内部使用红黑树算法来排序加入的对象,还可以自定义排序规则实现排序功能。
* 另外TreeMap中还有定义了一些自己的方法。
* @author 桂子山下一棵草
* @mail: slowguy@qq.com
*/
public class HashMapExample {
public static void main(String[] args)
{
// HashMapExample.testHashMap() ;
HashMapExample.testLinkedHashMap();
HashMapExample.testTreeMap() ;
}
/**
* console输出内容为:注意:顺序变了
* 输出集合中的内容:
aaa 48878985
lwm 123456
*
*/
static void testHashMap()
{
Map<String,String> classmates = new HashMap<String, String>() ;
classmates.put("lwm", "123456") ;
classmates.put("aaa", "48878985") ;
System.out.println("输出集合中的内容:");
Set<String> keys = classmates.keySet() ;
for (String key : keys)
{
System.out.print(key+"\t");
System.out.println(classmates.get(key));
}
}
/*
* console输出内容为:注意:顺序与加入的顺序相同
* 输出集合中的内容:
lwm 123456
aaa 48878985
*/
static void testLinkedHashMap()
{
Map<String,String> classmates = new LinkedHashMap<String, String>() ;
classmates.put("lwm", "123456") ;
classmates.put("lwm", "123456789") ;
classmates.put("aaa", "48878985") ;
System.out.println("输出集合中的内容:");
Set<String> keys = classmates.keySet() ;
for (String key : keys)
{
System.out.print(key+"\t");
System.out.println(classmates.get(key));
}
}
/**
*注意:本例中加入的是string对象,因此执行结果会自动依key值的字典顺序排序。
*JDK中的解释如下:
Red-Black tree based implementation of the SortedMap interface.
This class guarantees that the map
will be in ascending key order, sorted according to the natural
order for the key's class (see Comparable), or by the comparator provided
at creation time, depending on which constructor is used.
*
*/
static void testTreeMap()
{
Map<String,String> classmates = new TreeMap<String, String>() ;
classmates.put("lwm", "123456789") ;
classmates.put("lwm", "123456") ;
classmates.put("aaa", "48878985") ;
System.out.println("输出集合中的内容:");
Set<String> keys = classmates.keySet() ;
for (String key : keys)
{
System.out.print(key+"\t");
System.out.println(classmates.get(key));
}
}
}
<二>集合类型映射
下面演示如何在实体映射配置文件中,如何映射集合类型。
1,映射Set类型
测试的实体类User代码如下:
package cn.edu.ccnu.inc.entity;
import java.io.Serializable;
import java.util.HashSet;
import java.util.Set;
public class User implements Serializable {
private Integer id ; //代理主键
private String username ; //用户名
private String password ; //密码
private Set emails = new HashSet<String>(0) ; //邮箱地址
public User()
{
}
private void setId(Integer id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public Set getEmails() {
return emails;
}
public void setEmails(Set emails) {
this.emails = emails;
}
public Integer getId() {
return id;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((id == null) ? 0 : id.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
User other = (User) obj;
if (id == null) {
if (other.id != null)
return false;
} else if (!id.equals(other.id))
return false;
return true;
}
}
User.hbm.xml文件写法如下:
<?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"> <hibernate-mapping> <class name="cn.edu.ccnu.inc.lwm.entity.User" table="dbuser" catalog="hibernate"> <id name="id" type="java.lang.Integer"> <column name="id" precision="8" scale="0"> </column> <generator class="increment"></generator> </id> <property name="username" type="java.lang.String"> <column name="username" length="10" /> </property> <property name="password" type="java.lang.String"> <column name="password" length="30" /> </property> <set name="emails" table="email"> <key column="userid" foreign-key="id"></key> <element type="java.lang.String" column="email"></element> </set> </class> </hibernate-mapping>
说明:<set name="emails" table="email">行中,name为User类的emails属性,table值为与emails属性对应的数据库表。
<key column="userid" foreign-key="id"></key>行中,key指定email表中的userid是外键,引用users表的id字段。
<element type="java.lang.String" column="email"></element> 指定emails集合中元素的类型,每一个元素对应映射emails表中的email 字段。
2,映射List类型
如前所述,List类型是一种有序的集合类型,所以保存List集合中的对象时,需要在数据库中同时记录元素的顺序。
测试实体仍然是上面的User对象,只不过是将emails属性的类型换成List即可。
User.hbm.xml中用户名和密码的映射与上面相同,emails部分映射如下:
<!-- 使用<list>标签定义list集合映射,name="emails"设置user类的emails属性是一个list对象,table="email"设置数据库表EMAILS和emails属性对应 <key>标签指定emails表的USERID字段是外键,引用user表的id字段 <list-index>标签指定emails表中记录索引的字段为idx --> <list name="emails" table="emails" inverse="true"> <key foreign-key="id"> <column name="USERID" /> </key> <list-index column="IDX"></list-index> <element type="java.lang.String" column="EMAIL"></element> </list>
3,映射Map类型
修改List映射中的映射文件,将<list>标签部分替换如下,即可:
<!-- 使用<map>标签定义map集合映射 --> <!-- name属性设置MapUser类的emails属性是一个map对象,table属性设置数据库中mapemail表与emails属性对应 --> <map name="mapemails" table="mapemail"> <!-- key 设置mapemail表中userid是外键,引用mapuser表的ID字段 --> <key column="userid" foreign-key="id" /> <!--map-key设置mapemail表的usage用来保存map集合的key值 --> <map-key column="useage" type="java.lang.String"/> <!-- elmennt标签设置emails集合中的元素的value值保存到mapemails表的email字段中 --> <element type="java.lang.String" column="email"/> </map>
未完,待续!!!!