Hibernate集合映射

集合属性

集合属性只声明接口。
不管什么集合属性,都需要@ElementCollection注解进行映射,该注解有2个属性:
- fetch: 指定该实体对集合属性的抓取策略。有2种,分别是FetchType.LAZY,FetchType.EAGER,前者标识延迟加载,后者为立即加载。
- targetClass: 指定集合属性中集合元素的类型。

集合属性需要保存在另外一张表中,举个例子: 一个毕业生,他上完了小学、初中、高中、大学,那这4个学校级别都是属于同一个集合的,也就是说一个人对应一个属性的多个值。所以可以把这些值放在另一个表中,该表中必须包含一个外键列,这样才能根据原始表中的主键值找到另一个数据表的数据。该外键连使用@JoinColumn注解修饰。
CollectionTable注解指定映射保存集合属性的表。
对于List、数组集合,是有序的,可以使用@OrderColumn注解,用户定义List、数组的索引列,指定顺序。
对于Map集合,使用key作为集合元素的索引,可以使用@MapKeyColumn注解,用于映射Map集合索引列。

1. List集合属性映射

现有一个Person类,它有一个集合: schools,该属性对应多个学校。由于集合属性只能声明接口,所以schools类型只能是List,而不是ArrayList,但是该属性必须使用对应实现的类初始化。对于List,需要实例化ArrayList或实现List接口的类。

//使用JPA规范的主键生成策略
@Entity
@Table(name = "person_inf")
public class Person_list {

    @Id
    @Column(name = "person_id")
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private int id;
    private String name;
    private int age;

    //指定集合的抓取策略为延迟抓取(默认为lazy),指定集合元素的类型
    @ElementCollection(fetch = FetchType.LAZY, targetClass = String.class)
    //映射保存集合属性的表
    @CollectionTable(name = "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<>();
    //省略get、set
    ...
}
  • @ElementCollection(fetch = FetchType.LAZY, targetClass = String.class)表示获取该集合元素使用延迟(默认就是延迟),集合元素类型为String
  • @CollectionTable(name = "school_inf", joinColumns = @JoinColumn(name = "person_id", nullable = false)) 表示集合映射表名为school_inf,映射的一个外键列名为person_id,不能为空。如果原表中主键有多个,映射表需要指定对应数量的外键列。
  • @Column(name = "school_name"): 指定映射表存放元素值的名称。
  • @OrderColumn(name = "list_order"): 用于映射表的索引列名,用来排序。

测试代码:

            session.beginTransaction();

            Person_list personList = new Person_list();
            personList.setName("sweat1");
            personList.setAge(21);
            personList.getSchools().add("小学");
            personList.getSchools().add("中学");
            personList.getSchools().add("高中");
            personList.getSchools().add("大学");
            session.save(personList);

            session.getTransaction().commit();

数据库数据:

mysql> select * from person_inf;
+-----------+-----+--------+
| person_id | age | name   |
+-----------+-----+--------+
|         1 |  21 | sweat1 |
+-----------+-----+--------+
1 row in set (0.00 sec)

mysql> select * from school_inf;
+-----------+-------------+------------+
| person_id | school_name | list_order |
+-----------+-------------+------------+
|         1 | 小学        |          0 |
|         1 | 中学        |          1 |
|         1 | 高中        |          2 |
|         1 | 大学        |          3 |
+-----------+-------------+------------+
4 rows in set (0.00 sec)

2. 数组映射

数组和List非常相似,所以使用上也基本相同,直接给出代码。
Person

@Entity
@Table(name = "person_inf")
public class Person_Arr {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private int id;
    private String name;
    private int age;

    @ElementCollection(fetch = FetchType.LAZY, targetClass = String.class)
    @CollectionTable(name = "school_inf",
            joinColumns = @JoinColumn(name = "person_id", nullable = false))
    @Column(name = "school_name")
    @OrderColumn(name = "array_order")
    private String[] schools;
    //省略get、set
    ...
}

测试代码:

            session.beginTransaction();
            Person_Arr personArr = new Person_Arr();
            personArr.setName("sweat");
            personArr.setAge(21);
            String[] str = {"小学", "初中", "高中", "大学"};
            personArr.setSchools(str);
            session.save(personArr);
            session.getTransaction().commit();

数据库数据:

mysql> select * from person_inf;
+----+-----+-------+
| id | age | name  |
+----+-----+-------+
|  1 |  21 | sweat |
+----+-----+-------+
1 row in set (0.00 sec)

mysql> select * from school_inf;
+-----------+-------------+-------------+
| person_id | school_name | array_order |
+-----------+-------------+-------------+
|         1 | 小学        |           0 |
|         1 | 初中        |           1 |
|         1 | 高中        |           2 |
|         1 | 大学        |           3 |
+-----------+-------------+-------------+
4 rows in set (0.00 sec)

3. set集合映射

set集合和之前的List、数组有一个不同,set集合时无序、不重复的,所以set不需要@OrderColumn注释。和List一样,应该声明接口。
Person类:

@Entity
@Table(name = "person_inf")
public class Person_set {

    @Id
    @Column(name = "person_id")
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private int id;
    private String name;
    private int age;

    @ElementCollection(targetClass = String.class, fetch = FetchType.LAZY)
    @CollectionTable(name = "school_inf",
            joinColumns = @JoinColumn(name = "person_id", nullable = false))
    @Column(name = "school_name", nullable = false)
    private Set<String> schools = new HashSet<>();
    //省略get、set、构造函数
    ...
}

测试代码:

            session.beginTransaction();
            Person_set personSet = new Person_set();
            personSet.setName("sweat");
            personSet.setAge(21);
            Set<String> set = new HashSet<>();
            set.add("小学");
            set.add("高中");
            set.add("初中");
            set.add("大学");
            personSet.setSchools(set);
            session.save(personSet);
            session.getTransaction().commit();

数据库数据:

mysql> select * from person_inf;
+-----------+-----+-------+
| person_id | age | name  |
+-----------+-----+-------+
|         1 |  21 | sweat |
+-----------+-----+-------+
1 row in set (0.00 sec)

mysql> select * from school_inf;
+-----------+-------------+
| person_id | school_name |
+-----------+-------------+
|         1 | 初中        |
|         1 | 大学        |
|         1 | 小学        |
|         1 | 高中        |
+-----------+-------------+
4 rows in set (0.00 sec)

4. Map集合映射

Map属性映射也需要使用@ElementCollection映射集合,使用CollectionTable来指定映射表信息,还需要使用@MapKeyColumn注解指定Mapkey的数据列名。Hibernate同时会将外键列和key列作为联合主键。
Person类:

@Entity
@Table(name = "person_inf")
public class Person_Map {

    @Id
    @Column(name = "person_id")
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private int id;
    private String name;
    private int age;

    @ElementCollection(fetch = FetchType.LAZY, targetClass = Float.class)
    @CollectionTable(name = "score_inf",
            joinColumns = @JoinColumn(name = "person_id", nullable = false))
    @MapKeyColumn(name = "key_col")
    @MapKeyClass(String.class)
    @Column(name = "value_col")
    private Map<String, Float> scores = new HashMap<>();
    //省略get、set、构造函数
    ...
}
  • @ElementCollection(fetch = FetchType.LAZY, targetClass = Float.class)和其它一样。
  • @CollectionTable(name = "score_inf", joinColumns = @JoinColumn(name = "person_id", nullable = false))指定映射表名,指定外键列名,非空。
  • @MapKeyColumn(name = "key_col"):指定映射表中Mapkey列名。
  • @MapKeyClass(String.class): 指定映射表中Mapkey数据类型。
  • @Column(name = "value_col"): 指定映射表中Mapvalue列名。

测试代码:

            session.beginTransaction();
            Person_Map personMap = new Person_Map();
            personMap.setName("sweat");
            personMap.setAge(21);
            Map<String, Float> mp = new HashMap<>();
            mp.put("key1", 1.5f);
            mp.put("key2", 2.5f);
            mp.put("key4", 3.5f);
            mp.put("key3", 4.5f);
            personMap.setScores(mp);
            session.save(personMap);
            session.getTransaction().commit();

数据库数据:
先看person_inf表描述:

mysql> desc person_inf;
+-----------+--------------+------+-----+---------+----------------+
| Field     | Type         | Null | Key | Default | Extra          |
+-----------+--------------+------+-----+---------+----------------+
| person_id | int(11)      | NO   | PRI | NULL    | auto_increment |
| age       | int(11)      | NO   |     | NULL    |                |
| name      | varchar(255) | YES  |     | NULL    |                |
+-----------+--------------+------+-----+---------+----------------+
3 rows in set (0.00 sec)

score_inf表描述:

mysql> desc score_inf;
+-----------+--------------+------+-----+---------+-------+
| Field     | Type         | Null | Key | Default | Extra |
+-----------+--------------+------+-----+---------+-------+
| person_id | int(11)      | NO   | PRI | NULL    |       |
| value_col | float        | YES  |     | NULL    |       |
| key_col   | varchar(255) | NO   | PRI | NULL    |       |
+-----------+--------------+------+-----+---------+-------+
3 rows in set (0.00 sec)

插入的数据:

mysql> select * from person_inf;
+-----------+-----+-------+
| person_id | age | name  |
+-----------+-----+-------+
|         1 |  21 | sweat |
+-----------+-----+-------+
1 row in set (0.00 sec)

mysql> select * from score_inf;
+-----------+-----------+---------+
| person_id | value_col | key_col |
+-----------+-----------+---------+
|         1 |       1.5 | key1    |
|         1 |       2.5 | key2    |
|         1 |       4.5 | key3    |
|         1 |       3.5 | key4    |
+-----------+-----------+---------+
4 rows in set (0.00 sec)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值