Hibernate映射集合属性

集合属性大致有两种:一种是单纯的集合属性,例如List、Set或数组等集合属性;另一种是Map结构的集合属性,每个属性值都有对应的key映射。不管哪种类型的集合属性,都统一用@ElementCollection注解进行映射。使用@ElementCollection注解时可指定如下的属性。


Hibernate使用标准的@CollectionTable注解映射保存集合属性的表,使用该注解时可指定如下的属性。


@JoinClumn注解专门用于定义外键列,使用@JoinColumn时可指定如下的属性。


1. List集合

List是有序集合,因此持久化到数据库时也必须增加一个列来表示集合元素的次序。看下面的持久化类,该Person类有一个集合属性:schools,该属性对应多个学校。

@Entity
@Table(name="person_inf")
public class Person
{
	@Id @Column(name="perosn_id")
	@GeneratedValue(strategy=GenerationType.IDENTITY)
	// 标识属性
	private Integer id;
	private String name;
	private int age;
	// 集合属性,保留该对象关联的学校
	@ElementCollection(targetClass=String.class)
	// 映射保存集合属性的表
	@CollectionTable(name="school_inf", // 指定表名为school_inf
		joinColumns=@JoinColumn(name="person_id" , nullable=false))
	// 指定保存集合元素的列为 school_name
	@Column(name="school_name")
	// 映射集合元素索引的列
	@OrderColumn(name="list_order")
	private List<String> schools
		= new ArrayList<>();

	// id的setter和getter方法
	public void setId(Integer id)
	{
		this.id = id;
	}
	public Integer getId()
	{
		return this.id;
	}

	// name的setter和getter方法
	public void setName(String name)
	{
		this.name = name;
	}
	public String getName()
	{
		return this.name;
	}

	// age的setter和getter方法
	public void setAge(int age)
	{
		this.age = age;
	}
	public int getAge()
	{
		return this.age;
	}

	// schools的setter和getter方法
	public void setSchools(List<String> schools)
	{
		this.schools = schools;
	}
	public List<String> getSchools()
	{
		return this.schools;
	}
}

 上面的代码依次使用的注解:

1)        ElementCollection:用于映射集合属性。

2)        CollectionTable:用于映射集合属性表。其中name属性指定集合属性表的表名,joinColumns属性用于映射外键列。

3)        @Column:用于映射保存集合元素的数据列

4)        @OrderColumn:用于映射List集合的索引列。

开发了上面的持久类(POJO + 持久化注解),该类可以用于支持持久化访问。用于完成持久化访问的主程序片段如下。

 public class PersonManager
{
	public static void main(String[] args)
	{
		PersonManager mgr = new PersonManager();
		mgr.createAndStorePerson();
		HibernateUtil.sessionFactory.close();
	}
// 创建并保存Person对象
private void createAndStorePerson()
{
	// 打开线程安全的session对象
	Session session = HibernateUtil.currentSession();
	// 打开事务
	Transaction tx = session.beginTransaction();
	// 创建Person对象
	Person person = new Person();
	//为Person对象设置属性
	person.setAge(20);
	person.setName("owen.org");
	// 向person的schools属性中添加2个元素
	person.getSchools().add("小学");
	person.getSchools().add("中学");
	session.save(person);
	tx.commit();
	HibernateUtil.closeSession();
}
}

结果对应的数据表school_inf:


 person_inf表:

2. 数组属性

Hibernate对数组和List的处理方式非常相似,它们用法区别是:List的长度可能变化,而数组长度不可以变化。

下面笔者定义一个关于使用数组的Person类。

@Entity
@Table(name="person_inf")
public class Person
{
	@Id @Column(name="person_id")
	@GeneratedValue(strategy=GenerationType.IDENTITY)
	// 标识属性
	private Integer id;
	private String name;
	private int age;
	// 集合属性,保留该对象关联的学校
	@ElementCollection(targetClass=String.class)
	// 映射保存集合属性的表
	@CollectionTable(name="school_inf", // 指定表名为school_inf
		joinColumns=@JoinColumn(name="person_id" , nullable=false))
	// 指定保存集合元素的列为 school_name
	@Column(name="school_name")
	// 映射集合元素索引的列
	@OrderColumn(name="array_order")
	private String[] schools;

	// id的setter和getter方法
	public void setId(Integer id)
	{
		this.id = id;
	}
	public Integer getId()
	{
		return this.id;
	}

	// name的setter和getter方法
	public void setName(String name)
	{
		this.name = name;
	}
	public String getName()
	{
		return this.name;
	}

	// age的setter和getter方法
	public void setAge(int age)
	{
		this.age = age;
	}
	public int getAge()
	{
		return this.age;
	}

	// schools的setter和getter方法
	public void setSchools(String[] schools)
	{
		this.schools = schools;
	}
	public String[] getSchools()
	{
		return this.schools;
	}
}

执行持久化的类与上面相同。运行的数组也是相同的,所以这里就不给出结果图。

3. Set集合属性

Set集合属性的映射与List有点不同,因为Set是无序、不可重复的集合,因此Set集合属性无须使用@OrderColumn注解映射集合元素的索引。下面我们定义了一个Set的List集合属性的Pserson类。

@Entity
@Table(name="person_inf")
public class Person
{
	@Id @Column(name="person_id")
	@GeneratedValue(strategy=GenerationType.IDENTITY)
	// 标识属性
	private Integer id;
	private String name;
	private int age;
	// 集合属性,保留该对象关联的学校
	@ElementCollection(targetClass=String.class)
	// 映射保存集合属性的表
	@CollectionTable(name="school_inf", // 指定表名为school_inf
		joinColumns=@JoinColumn(name="person_id" , nullable=false))
	// 指定保存集合元素的列为 school_name,nullable=false增加非空约束
	@Column(name="school_name" , nullable=false)
	private Set<String> schools
		= new HashSet<>();

	// id的setter和getter方法
	public void setId(Integer id)
	{
		this.id = id;
	}
	public Integer getId()
	{
		return this.id;
	}

	// name的setter和getter方法
	public void setName(String name)
	{
		this.name = name;
	}
	public String getName()
	{
		return this.name;
	}

	// age的setter和getter方法
	public void setAge(int age)
	{
		this.age = age;
	}
	public int getAge()
	{
		return this.age;
	}

	// schools的setter和getter方法
	public void setSchools(Set<String> schools)
	{
		this.schools = schools;
	}
	public Set<String> getSchools()
	{
		return this.schools;
	}

}

下面主程序来保存持久化实例。

public class PersonManager
{
	public static void main(String[] args)
	{
		PersonManager mgr = new PersonManager();
		mgr.createAndStorePerson();
		HibernateUtil.sessionFactory.close();
	}

	private void createAndStorePerson()
	{
		Session session = HibernateUtil.currentSession();
		Transaction tx = session.beginTransaction();
		// 创建Person对象
		Person person = new Person();
		person.setAge(20);
		person.setName("owen.org");
		// 向person的schools集合属性中添加两个字符串元素
		person.getSchools().add("小学");
		person.getSchools().add("中学");
		session.save(person);
		tx.commit();
		HibernateUtil.closeSession();
	}
}

执行的数据为结果:



4. Map集合属性

Map集合属性同样需要使用@ElementCollection映射集合属性,使用@CollectionTable映射保存集合属性的数据表,如果Map的value是基本类型及其包装类、String或Date类型,同样也可使用@Column映射保存Map Value的数据列。除此之外,程序需要使用@MapKeyColumn映射保存Map Key的数据列。

下面我们定义了一个Map类型的集合属性。

@Entity
@Table(name="person_inf")
public class Person
{
	@Id @Column(name="person_id")
	@GeneratedValue(strategy=GenerationType.IDENTITY)
	// 标识属性
	private Integer id;
	private String name;
	private int age;
	// 集合属性,保留该对象关联的考试成绩
	@ElementCollection(targetClass=Float.class)
	// 映射保存集合属性的表
	@CollectionTable(name="score_inf", // 指定表名为score_inf
		joinColumns=@JoinColumn(name="person_id" , nullable=false))
	@MapKeyColumn(name="subject_name")
	// 指定Map key的类型为String类型
	@MapKeyClass(String.class)
	// 映射保存Map value的数据列
	@Column(name="mark")
	private Map<String , Float> scores
		= new HashMap<>();

	// id的setter和getter方法
	public void setId(Integer id)
	{
		this.id = id;
	}
	public Integer getId()
	{
		return this.id;
	}

	// name的setter和getter方法
	public void setName(String name)
	{
		this.name = name;
	}
	public String getName()
	{
		return this.name;
	}

	// age的setter和getter方法
	public void setAge(int age)
	{
		this.age = age;
	}
	public int getAge()
	{
		return this.age;
	}

	// scores的setter和getter方法
	public void setScores(Map<String , Float> age)
	{
		this.scores = scores;
	}
	public Map<String , Float> getScores()
	{
		return this.scores;
	}
}

执行持久化的类如下。

 public class PersonManager
{
	public static void main(String[] args)
	{
		PersonManager mgr = new PersonManager();
		mgr.createAndStorePerson();
		HibernateUtil.sessionFactory.close();
	}

	private void createAndStorePerson()
	{
		// 打开线程安全的Session对象
		Session session = HibernateUtil.currentSession();
		// 打开事务
		Transaction tx = session.beginTransaction();
		// 创建Person对象
		Person person = new Person();
		person.setAge(20);
		person.setName("owen.org");
		// 向person的Map集合属性中添加key-value对
		person.getScores().put("语文" , 67f);
		person.getScores().put("英文" , 45f);
		session.save(person);
		tx.commit();
		HibernateUtil.closeSession();
	}
}

执行的结果。


5. 集合的有序

  Hibernate还支持使用SortedSet和SortedMap两个有序集合,当需要映射这种有序集合时,只有使用Hibernate本身提供的@SortNatural或@SortComparator注解,其中当前者表明对集合采用自然排序,后者表明对集合元素采用定制排序,因此使用@SortComparator时必须指定vaLue属性,该属性值为Comparator实现类。

…..  	
// 有序集合属性
	@ElementCollection(targetClass=String.class)
	// 映射保存集合元素的表
	@CollectionTable(name="training_inf",
		joinColumns=@JoinColumn(name="person_id" , nullable=false))
	// 定义保存集合元素的数据列
	@Column(name="training_name" , nullable=false)
	// 使用@SortNatural指定使用自然排序
	@SortNatural
	private SortedSet<String> trainings
		= new TreeSet<>();
……





评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值