集合属性大致有两种:
集合映射的元素大致有如下几种:
接下来我们就来一一详解以上集合映射的元素。
Set是无序,不可重复的集合。
以案例的方式来介绍映射Set集合属性,大概效果好点,并且在讲解其他集合属性时,我们都会遵循这点。试看这样一个案例,在生活中,我们都已会网上购物,在填写收货地址时,我们大概都会写多个收货地址,想想看是不是这样?我们可以剖析这个案例,作为介绍映射Set集合属性的基石。
我们在Eclipse中新建一个普通的Java工程,如Hibernate_Test,接着我们搭建好Hibernate的开发环境,这个不说了。然后我们在cn.itcast.e_hbm_collection包下新建一个Java类——User.java,用于表示一个个用户。
public class User {
private Integer id; // 推荐使用包装类
private String name;
private Set addressSet; // 未初始化的Set集合
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Set getAddressSet() {
return addressSet;
}
public void setAddressSet(Set addressSet) {
this.addressSet = addressSet;
}
}
接下来我们是该要创建出该类对应的映射配置文件的,在做之前,我们总该要分析出数据库中的表结构吧!只要分析出来,那创建相应的映射配置文件还不是分分钟的事情,我们可以用下图来表示:
这样,我们就能依葫芦画瓢写出映射配置文件——User.hbm.xml了。记住,该映射配置文件还得和User类待在一块,即在同一个包下。
<hibernate-mapping package="cn.itcast.e_hbm_collection">
<class name="User" table="user">
<id name="id">
<generator class="native">generator>
id>
<property name="name" />
<set name="addressSet" table="user_addressSet">
<key column="userId">key>
<element type="string" column="address">element>
set>
class>
hibernate-mapping>
为了便于测试,我们总是会编写一个单元测试类,所以我们还应在cn.itcast.e_hbm_collection包下创建出这样一个类——App.java。
public class App {
private static SessionFactory sessionFactory = new Configuration() //
.configure() //
.addClass(User.class) // 添加Hibernate实体类(加载对应的映射文件)
.buildSessionFactory();
@Test
public void testSave() {
Session session = sessionFactory.openSession();
session.beginTransaction();
// -------------------------------------------
// 构建对象
Set set = new HashSet();
set.add("御富科贸园xxx");
set.add("棠东东路");
User user = new User();
user.setName("张天一");
user.setAddressSet(set);
// 保存
session.save(user);
// -------------------------------------------
session.getTransaction().commit();
session.close();
}
@Test
public void testGet() {
Session session = sessionFactory.openSession();
session.beginTransaction();
// -------------------------------------------
// 获取数据
User user = (User) session.get(User.class, 1);
// 显示信息
System.out.println(user.getName());
System.out.println(user.getAddressSet());
// -------------------------------------------
session.getTransaction().commit();
session.close();
}
}
测试,会发现毫无问题,大发!
但有时候,我们会发现User类中的addressSet属性已经初始化过了,如:
public class User {
private Integer id; // 推荐使用包装类
private String name;
private Set addressSet = new HashSet(); // Set集合
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Set getAddressSet() {
return addressSet;
}
public void setAddressSet(Set addressSet) {
this.addressSet = addressSet;
}
}
我都是初始化集合属性的,因为这样写还是很有还好处的,那就是我们编写测试代码的时候少写一点代码,相应地单元测试类——App.java的代码就要改为:
public class App {
private static SessionFactory sessionFactory = new Configuration() //
.configure() //
.addClass(User.class) // 添加Hibernate实体类(加载对应的映射文件)
.buildSessionFactory();
@Test
public void testSave() {
Session session = sessionFactory.openSession();
session.beginTransaction();
// -------------------------------------------
// 构建对象
User user = new User();
user.setName("张天二");
user.getAddressSet().add("御富科贸园xxx");
user.getAddressSet().add("棠东东路");
// 保存
session.save(user);
// -------------------------------------------
session.getTransaction().commit();
session.close();
}
@Test
public void testGet() {
Session session = sessionFactory.openSession();
session.beginTransaction();
// -------------------------------------------
// 获取数据
User user = (User) session.get(User.class, 2);
// 显示信息
System.out.println(user.getName());
System.out.println(user.getAddressSet());
// -------------------------------------------
session.getTransaction().commit();
session.close();
}
}
测试,一致通过,大发!
注意:映射Set集合属性时,如果element元素包括not-null=”true”属性,则集合属性表以关联持久化类的外键和元素列作为联合主键,否则该表没有主键。但List集合属性不会,List集合属性总是以外键列和元素次序列作为联合主键。
重申一遍,Set是无序,不可重复的集合。但有时不可避免地要让Set集合中的元素具有一定顺序,这时就可以用到sort属性了,如我们要让Set集合中的字符串按照自然顺序排序,我们可以修改映射配置文件——User.hbm.xml为:
<hibernate-mapping package="cn.itcast.e_hbm_collection">
<class name="User" table="user">
<id name="id">
<generator class="native">generator>
id>
<property name="name" />
<set name="addressSet" table="user_addressSet" sort="natural">
<key column="userId">key>
<element type="string" column="address">element>
set>
class>
hibernate-mapping>
sort属性的取值有:unsorted、natural、comparatorClass,默认值为unsorted。
为了更加方便于我们看清Set集合中的字符串是按照自然顺序排序的,我们最好将App类的代码修改为:
public class App {
private static SessionFactory sessionFactory = new Configuration() //
.configure() //
.addClass(User.class) // 添加Hibernate实体类(加载对应的映射文件)
.buildSessionFactory();
@Test
public void testSave() {
Session session = sessionFactory.openSession();
session.beginTransaction();
// -------------------------------------------
// 构建对象
User user = new User();
user.setName("张天一");
user.getAddressSet().add("2御富科贸园");
user.getAddressSet().add("1棠东东路");
// 保存
session.save(user);
// -------------------------------------------
session.getTransaction().commit();
session.close();
}
@Test
public void testGet() {
Session session = sessionFactory.openSession();
session.beginTransaction();
// -------------------------------------------
// 获取数据
User user = (User) session.get(User.class, 1);
// 显示信息
System.out.println(user.getName());
System.out.println(user.getAddressSet());
// -------------------------------------------
session.getTransaction().commit();
session.close();
}
}
当测试testSave()方法时,会发现报异常:java.lang.ClassCastException: java.util.HashSet cannot be cast to java.util.SortedSet。出现异常,我们就要解决嘛!解决办法很简单,我们只须修改App类的代码为:
public class App {
private static SessionFactory sessionFactory = new Configuration() //
.configure() //
.addClass(User.class) // 添加Hibernate实体类(加载对应的映射文件)
.buildSessionFactory();
@Test
public void testSave() {
Session session = sessionFactory.openSession();
session.beginTransaction();
// -------------------------------------------
// 构建对象
User user = new User();
user.setName("张天一");
user.setAddressSet(new TreeSet()); // 当设置了sort属性时,就要使用SortedSet类型
user.getAddressSet().add("2御富科贸园");
user.getAddressSet().add("1棠东东路");
// 保存
session.save(user);
// -------------------------------------------
session.getTransaction().commit();
session.close();
}
@Test
public void testGet() {
Session session = sessionFactory.openSession();
session.beginTransaction();
// -------------------------------------------
// 获取数据
User user = (User) session.get(User.class, 1);
// 显示信息
System.out.println(user.getName());
System.out.println(user.getAddressSet());
// -------------------------------------------
session.getTransaction().commit();
session.close();
}
}
要让Set集合中的元素具有一定顺序,上面使用了sort属性,但是该排序是在计算机内存中进行的,效率比较偏低,如果希望效率高点,我们可以使用order by属性,它应该是就在数据库中就排好序了。为了测试这点,我们将映射配置文件——User.hbm.xml改为:
<hibernate-mapping package="cn.itcast.e_hbm_collection">
<class name="User" table="user">
<id name="id">
<generator class="native">generator>
id>
<property name="name" />
<set name="addressSet" table="user_addressSet" order-by="address DESC">
<key column="userId">key>
<element type="string" column="address">element>
set>
class>
hibernate-mapping>
我们又要修改App类的代码了。
public class App {
private static SessionFactory sessionFactory = new Configuration() //
.configure() //
.addClass(User.class) // 添加Hibernate实体类(加载对应的映射文件)
.buildSessionFactory();
@Test
public void testSave() {
Session session = sessionFactory.openSession();
session.beginTransaction();
// -------------------------------------------
// 构建对象
User user = new User();
user.setName("张天一");
// user.setAddressSet(new TreeSet()); // 当设置了sort属性时,就要使用SortedSet类型
user.getAddressSet().add("2御富科贸园");
user.getAddressSet().add("1棠东东路");
// 保存
session.save(user);
// -------------------------------------------
session.getTransaction().commit();
session.close();
}
@Test
public void testGet() {
Session session = sessionFactory.openSession();
session.beginTransaction();
// -------------------------------------------
// 获取数据
User user = (User) session.get(User.class, 2);
// 显示信息
System.out.println(user.getName());
System.out.println(user.getAddressSet());
// -------------------------------------------
session.getTransaction().commit();
session.close();
}
}
List是有序集合,因此持久化到数据库时必须增加一列来表示集合元素的次序。
集合属性只能以接口声明(当持久化某个实例时,Hibernate会自动把程序中的集合实现类替换成Hibernate自己的集合实现类),因此下面代码中,addressList的类型只能是List,而不能是ArrayList。
private List<String> addressList = new ArrayList<String>(); // List集合
为了介绍映射List集合属性,我们需要将User类的代码置为:
public class User {
private Integer id; // 推荐使用包装类
private String name;
private List addressList = new ArrayList(); // List集合
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public List getAddressList() {
return addressList;
}
public void setAddressList(List addressList) {
this.addressList = addressList;
}
}
同样,在创建出该类所对应的映射配置文件之前,我们还要分析出数据库中的表结构!我们可以用下图来表示:
接下来我们就要修改映射配置文件——User.hbm.xml的内容了。
<hibernate-mapping package="cn.itcast.e_hbm_collection">
<class name="User" table="user">
<id name="id">
<generator class="native">generator>
id>
<property name="name" />
<list name="addressList" table="user_addressList">
<key column="userId">key>
<list-index column="idx">list-index>
<element type="string" column="address">element>
list>
class>
hibernate-mapping>
映射说明:
之后我们每讲一个映射集合属性,都遵循这样一个原则——将数据库hibernate_20160926中的user表和userXxx表删干净,还给大家一片净土,便于大家查看测试后的结果。接下来,我们要将App类的代码修改为:
public class App {
private static SessionFactory sessionFactory = new Configuration() //
.configure() //
.addClass(User.class) // 添加Hibernate实体类(加载对应的映射文件)
.buildSessionFactory();
@Test
public void testSave() {
Session session = sessionFactory.openSession();
session.beginTransaction();
// -------------------------------------------
// 构建对象
User user = new User();
user.setName("张天一");
user.getAddressList().add("御富科贸园");
user.getAddressList().add("棠东东路");
user.getAddressList().add("棠东东路");
// 保存
session.save(user);
// -------------------------------------------
session.getTransaction().commit();
session.close();
}
@Test
public void testGet() {
Session session = sessionFactory.openSession();
session.beginTransaction();
// -------------------------------------------
// 获取数据
User user = (User) session.get(User.class, 1);
// 显示信息
System.out.println(user.getName());
System.out.println(user.getAddressList());
// -------------------------------------------
session.getTransaction().commit();
session.close();
}
}
测试,顺利通过,大发!
数组属性的映射和List的处理方式基本一致。数组使用
元素完成完成映射。
为了介绍映射数组属性,我们需要将User类的代码置为:
public class User {
private Integer id; // 推荐使用包装类
private String name;
private String[] addressArray; // 数组
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String[] getAddressArray() {
return addressArray;
}
public void setAddressArray(String[] addressArray) {
this.addressArray = addressArray;
}
}
接下来我们就要修改映射配置文件——User.hbm.xml的内容了。
<hibernate-mapping package="cn.itcast.e_hbm_collection">
<class name="User" table="user">
<id name="id">
<generator class="native">generator>
id>
<property name="name" />
<array name="addressArray" table="user_addressArray">
<key column="userId">key>
<list-index column="idx">list-index>
<element type="string" column="address">element>
array>
class>
hibernate-mapping>
最后,我们要将App类的代码修改为:
public class App {
private static SessionFactory sessionFactory = new Configuration() //
.configure() //
.addClass(User.class) // 添加Hibernate实体类(加载对应的映射文件)
.buildSessionFactory();
@Test
public void testSave() {
Session session = sessionFactory.openSession();
session.beginTransaction();
// -------------------------------------------
// 构建对象
User user = new User();
user.setName("张天一");
user.setAddressArray(new String[] { "御富科贸园", "棠东东路" });
// 保存
session.save(user);
// -------------------------------------------
session.getTransaction().commit();
session.close();
}
@Test
public void testGet() {
Session session = sessionFactory.openSession();
session.beginTransaction();
// -------------------------------------------
// 获取数据
User user = (User) session.get(User.class, 1);
// 显示信息
System.out.println(user.getName());
System.out.println(Arrays.toString(user.getAddressArray()));
// -------------------------------------------
session.getTransaction().commit();
session.close();
}
}
测试,顺利通过,大发!
为了介绍映射Map集合属性,我们需要将User类的代码置为:
public class User {
private Integer id; // 推荐使用包装类
private String name;
private Map addressMap = new HashMap(); // Map集合
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Map getAddressMap() {
return addressMap;
}
public void setAddressMap(Map addressMap) {
this.addressMap = addressMap;
}
}
同样,在创建出该类所对应的映射配置文件之前,我们还要分析出数据库中的表结构!我们可以用下图来表示:
接下来我们就要修改映射配置文件——User.hbm.xml的内容了。
<hibernate-mapping package="cn.itcast.e_hbm_collection">
<class name="User" table="user">
<id name="id">
<generator class="native">generator>
id>
<property name="name" />
<map name="addressMap" table="user_addressMap">
<key column="userId">key>
<map-key type="string" column="key_">map-key>
<element type="string" column="address">element>
map>
class>
hibernate-mapping>
最后,我们要将App类的代码修改为:
public class App {
private static SessionFactory sessionFactory = new Configuration() //
.configure() //
.addClass(User.class) // 添加Hibernate实体类(加载对应的映射文件)
.buildSessionFactory();
@Test
public void testSave() {
Session session = sessionFactory.openSession();
session.beginTransaction();
// -------------------------------------------
// 构建对象
User user = new User();
user.setName("张天一");
user.getAddressMap().put("公司", "御富科贸园");
user.getAddressMap().put("家庭", "棠东东路");
// 保存
session.save(user);
// -------------------------------------------
session.getTransaction().commit();
session.close();
}
@Test
public void testGet() {
Session session = sessionFactory.openSession();
session.beginTransaction();
// -------------------------------------------
// 获取数据
User user = (User) session.get(User.class, 1);
// 显示信息
System.out.println(user.getName());
System.out.println(user.getAddressMap());
// -------------------------------------------
session.getTransaction().commit();
session.close();
}
}
测试,顺利通过,大发!
Bag的特性是:允许重复的元素,但无序。在Java的标准API中并没有提供Bag容器,Hibernate提供自己的Bag实现,允许您将List映射为Bag。
为了介绍映射Bag集合属性,我们需要将User类的代码置为:
public class User {
private Integer id; // 推荐使用包装类
private String name;
private List addressBag = new ArrayList();
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public List getAddressBag() {
return addressBag;
}
public void setAddressBag(List addressBag) {
this.addressBag = addressBag;
}
}
接下来我们就要修改映射配置文件——User.hbm.xml的内容了。
<hibernate-mapping package="cn.itcast.e_hbm_collection">
<class name="User" table="user">
<id name="id">
<generator class="native">generator>
id>
<property name="name" />
<bag name="addressBag" table="user_addressBag">
<key column="userId">key>
<element type="string" column="address">element>
bag>
class>
hibernate-mapping>
最后,我们要将App类的代码修改为:
public class App {
private static SessionFactory sessionFactory = new Configuration() //
.configure() //
.addClass(User.class) // 添加Hibernate实体类(加载对应的映射文件)
.buildSessionFactory();
@Test
public void testSave() {
Session session = sessionFactory.openSession();
session.beginTransaction();
// -------------------------------------------
// 构建对象
User user = new User();
user.setName("张天一");
user.getAddressBag().add("御富科贸园");
user.getAddressBag().add("棠东东路");
user.getAddressBag().add("棠东东路");
// 保存
session.save(user);
// -------------------------------------------
session.getTransaction().commit();
session.close();
}
@Test
public void testGet() {
Session session = sessionFactory.openSession();
session.beginTransaction();
// -------------------------------------------
// 获取数据
User user = (User) session.get(User.class, 1);
// 显示信息
System.out.println(user.getName());
System.out.println(user.getAddressBag());
// -------------------------------------------
session.getTransaction().commit();
session.close();
}
}
测试,顺利通过,大发!