Hibernate之集合映射

前言

上节已经学会了Hibernate之CRUD操作了,那么有这么一个需求,当用户购买商品的时候会填写收货地址,有时候收货地址不止一个,那么数据库是如何来保存一个用户对应多个地址的呢,而使用Hibernate如何映射用户和地址的关系呢。我们来看看具体实现吧。

数据库之表结构设计

如果数据库还不是很好的同学,可能会这么设计数据库吧。
这里写图片描述
如果把用户信息和地址放在同一个表中,用户有的可能有三四个收货地址,有的可能只有一个收货地址,那么数据库将会产生大量的冗余,不符合数据库的三大范式,所以不推荐以上设计。

应当采用如下的设计:
这里写图片描述
建立用户与地址表,然后将地址表的外键设置为用户id即可。

那么数据库表建好了,如何通过Hibernate存入数据呢。之前只是存单个表的数据我们会了,现在是一对多的关系,应当使用集合映射来存储。因为集合可以存多个地址,只要在xml文件中配置映射关系即可。

案例代码

User.java

// javabean设计
public class User {

    private int userId;
    private String userName;
    // 一个用户,对应的多个地址
    private Set<String> address;

    public void setAddressList(List<String> addressList) {
        this.addressList = addressList;
    }
    public int getUserId() {
        return userId;
    }
    public void setUserId(int userId) {
        this.userId = userId;
    }
    public String getUserName() {
        return userName;
    }
    public void setUserName(String userName) {
        this.userName = userName;
    }
    public Set<String> getAddress() {
        return address;
    }
    public void setAddress(Set<String> address) {
        this.address = address;
    }       
}

映射文件User.hbm.xml

<hibernate-mapping package="com.nwpu.geeker.collection">

    <class name="User" table="t_user">
        <id name="userId" column="id">
            <generator class="native"></generator>
        </id>   
        <property name="userName"></property>

        <!-- 
            set集合属性的映射
                name 指定要映射的set集合的属性
                table 集合属性要映射到的表
                key  指定集合表(t_address)的外键字段
                element 指定集合表的其他字段
                    type 元素类型,一定要指定
         -->
         <set name="address" table="t_address">
            <key column="uid"></key>
            <element column="address" type="string"></element>
         </set>

    </class>
</hibernate-mapping>

测试代码:APP.java

public class App {

    private static SessionFactory sf;
    static {
        sf = new Configuration()
            .configure()
            .addClass(User.class)   // 测试时候使用
            .buildSessionFactory();
    }

    // 保存set
    @Test
    public void testSaveSet() throws Exception {
        Session session = sf.openSession();
        session.beginTransaction();

        //-- 保存
        Set<String> addressSet = new HashSet<String>();
        addressSet.add("广州");
        addressSet.add("深圳");
        // 用户对象
        User user = new User();
        user.setUserName("Jack");
        user.setAddress(addressSet);

        // 保存
        session.save(user);

        session.getTransaction().commit();
        session.close();
    }
}

数据库保存两张表的数据成功!
这里写图片描述

当然集合映射不只有set集合可以,也可以是数组array,list,map等容器存储多的一方。
修改上面代码:
User.java

public class User {

    private int userId;
    private String userName;
    // 一个用户,对应的多个地址
    private Set<String> address;
    private List<String> addressList = new ArrayList<String>(); 
    //private String[] addressArray; // 映射方式和list一样     <array name=""></array>
    private Map<String,String> addressMap = new HashMap<String, String>();



    public Map<String, String> getAddressMap() {
        return addressMap;
    }
    public void setAddressMap(Map<String, String> addressMap) {
        this.addressMap = addressMap;
    }
    public List<String> getAddressList() {
        return addressList;
    }
    public void setAddressList(List<String> addressList) {
        this.addressList = addressList;
    }
    public int getUserId() {
        return userId;
    }
    public void setUserId(int userId) {
        this.userId = userId;
    }
    public String getUserName() {
        return userName;
    }
    public void setUserName(String userName) {
        this.userName = userName;
    }
    public Set<String> getAddress() {
        return address;
    }
    public void setAddress(Set<String> address) {
        this.address = address;
    }


}

配置文件

<hibernate-mapping package="com.nwpu.geeker.collection">

    <class name="User" table="t_user">
        <id name="userId" column="id">
            <generator class="native"></generator>
        </id>   
        <property name="userName"></property>

        <!-- 
            set集合属性的映射
                name 指定要映射的set集合的属性
                table 集合属性要映射到的表
                key  指定集合表(t_address)的外键字段
                element 指定集合表的其他字段
                    type 元素类型,一定要指定
         -->
         <set name="address" table="t_address">
            <key column="uid"></key>
            <element column="address" type="string"></element>
         </set>

         <!-- 
            list集合映射
                list-index  指定的是排序列的名称 (因为要保证list集合的有序)
          -->
          <list name="addressList" table="t_addressList">
              <key column="uid"></key>
              <list-index column="idx"></list-index>
              <element column="address" type="string"></element>
          </list>

          <!-- 
            map集合的映射
                key  指定外键字段
                map-key 指定map的key 
                element  指定map的value
           -->
          <map name="addressMap" table="t_addressMap">
            <key column="uid"></key>
            <map-key column="shortName" type="string" ></map-key>
            <element column="address" type="string" ></element>
          </map>


    </class>


</hibernate-mapping>

App.java

public class App {

    private static SessionFactory sf;
    static {
        sf = new Configuration()
            .configure()
            .addClass(User.class)   // 测试时候使用
            .buildSessionFactory();
    }

    // 保存set
    @Test
    public void testSaveSet() throws Exception {
        Session session = sf.openSession();
        session.beginTransaction();

        //-- 保存
        Set<String> addressSet = new HashSet<String>();
        addressSet.add("广州");
        addressSet.add("深圳");
        // 用户对象
        User user = new User();
        user.setUserName("Jack");
        user.setAddress(addressSet);

        // 保存
        session.save(user);

        session.getTransaction().commit();
        session.close();
    }

    // 保存list/map
    @Test
    public void testSaveList() throws Exception {
        Session session = sf.openSession();
        session.beginTransaction();
        User user = new User();
        user.setUserName("Tom");
//      // 用户对象  --  list
//      user.getAddressList().add("广州");
//      user.getAddressList().add("深圳");
//      // 保存
//      session.save(user);

        // 用户对象  --  Map
        user.getAddressMap().put("A0001", "广州");
        user.getAddressMap().put("A0002", "深圳");

        // 保存
        session.save(user);

        session.getTransaction().commit();
        session.close();
    }
}

注意:set保存的数据是无序的,数组和list是有序的,但是只能保存一个字符串,也就是只能保存一个值,map强一点能保存两个值,不过,当我们需要保存多个数据,比如一个对象的时候,就需要将对象保存在集合中了,而不是简单的只保存一个地址。本文到这里就结束了,后续将把如何保存对象,即一对多,多方保存对象的案例总结出来!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值