hibernate关联映射(一对多)

来源:互联网 发布:咸阳广电网络营业时间 编辑:程序博客网 时间:2024/05/19 13:17

这篇博客将会给大家带来hibernate的关联映射的学习。在现实生活中,不仅只是一对一的映射关系,更多的是一对多,多对多等。

一对多单项关联映射

这里我以网盘为例,一个用户可以拥有多个文件,及用户和文件之间是一对多的关系。
这里写图片描述
user实体类:

public class Users {    private int uid;    private String uname;    //用户上传的所有文件 // one方 可以获取  many方    private Set<UpFile> files = new HashSet<UpFile>();    public Users() {        super();        // TODO Auto-generated constructor stub    }    public Users(int uid, String uname) {        super();        this.uid = uid;        this.uname = uname;    }    public int getUid() {        return uid;    }    public void setUid(int uid) {        this.uid = uid;    }    public String getUname() {        return uname;    }    public void setUname(String uname) {        this.uname = uname;    }    public Set<UpFile> getFiles() {        return files;    }    public void setFiles(Set<UpFile> files) {        this.files = files;    }}

UpFile实体类如下:

public class UpFile {    private int fid;    private String fileName;    private int fsize;    public UpFile() {        super();        // TODO Auto-generated constructor stub    }    public UpFile(int fid, String fileName, int fsize) {        super();        this.fid = fid;        this.fileName = fileName;        this.fsize = fsize;    }    public int getFid() {        return fid;    }    public void setFid(int fid) {        this.fid = fid;    }    public String getFileName() {        return fileName;    }    public void setFileName(String fileName) {        this.fileName = fileName;    }    public int getFsize() {        return fsize;    }    public void setFsize(int fsize) {        this.fsize = fsize;    }}

可以看到,一对多的设置只是在一方通过set集合来实现的,因为set集合是不能重复的,所以使用它。
Users.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="a.b.c.Users">        <id name="uid">            <generator class="native"/>        </id>        <property name="uname"/>        <!-- one-to-many -->        <set name="files">            <key column="u_id"/>            <one-to-many class="a.b.c.UpFile"/>        </set>    </class></hibernate-mapping>  

UpFile.hbm.xml

<hibernate-mapping>    <class name="a.b.c.UpFile">        <id name="fid">            <generator class="native"/>        </id>        <property name="fileName"/>        <property name="fsize"/>    </class></hibernate-mapping>

通过<set></set> 标签实现的一对多关系。对于user表的主键作为upfile表的外键。
此时,执行一条插入操作:

session.beginTransaction();                             Users u = new Users(0,"赵六");UpFile f = new UpFile(0,"ccc.txt",453);UpFile f2 = new UpFile(1,"bbb.txt",500);u.getFiles().add(f);    //one端集合关系u.getFiles().add(f2);session.save(f);session.save(f2);session.save(u);

此时控制台打印的sql语句如下:
这里写图片描述
可以看到hibernate是首先插入所有的多方,然后利用update来更新一对多的关系。
这里写图片描述
可以看到在upfile中,有一个u_id作为外键。

一对多级联操作

在上面的一对多的插入操作当中,首先插入了两个UpFile,然后插入单个user,其实不必这么麻烦,可以配置级联操作:

<set name="files" cascade="all">    <key column="u_id"/>    <one-to-many class="a.b.c.UpFile"/></set>

cascade=”all”这里,我配置值为all,表示基于user的所有操作都会关联到和其关联的UpFile表的数据,cascade有如下一些值:
delete,
update,
all,
none
在配置了级联操作以后,执行插入就可以只插入User了,hibernate会将和该user关联的所有upfile都进行添加操作:

session.beginTransaction();                             Users u = new Users();u.setUname("adsf");UpFile f = new UpFile("ccc.txt",453);UpFile f2 = new UpFile("bbb.txt",500);u.getFiles().add(f);    //one端集合关系u.getFiles().add(f2);session.save(u);session.getTransaction().commit();  

一对多关联延迟加载

<set name="files" cascade="all" lazy="false">    <key column="u_id"/>    <one-to-many class="a.b.c.UpFile"/></set>

如果配置lazy=”false”表示立即加载。此时只要查询每一个user的时候,都会将该user对应的upfile查询出来,如果lazy=”true”,那么当查询user的时候,不会立即将该user对应的upfile查询出来,而是在使用到的时候,才根据该user的主键去upfile表中查找。

删除一对多关联

Configuration cfg = new Configuration().configure();    SessionFactory factory = cfg.buildSessionFactory();     Session session = factory.openSession();                Transaction transaction = session.beginTransaction();Users u1  = (Users)session.get(Users.class, 1);UpFile upFile = (UpFile) session.get(UpFile.class,2);u1.getFiles().remove(upFile);transaction.commit();session.close();                

这里写图片描述
此时,所有的数据都还继续存在,只是将关联删除。

一对多双向关联

之前关于user和upfile的一对多的关联是单向的,也就是说我们只能通过user来获得和操作upfile,反过来则是不行的,那么怎么配置”一对多的双向关联”??
1.需要在Upfile类中增加user属性,并为该属性提供get和set方法
private Users users;
2.配置映射文件:
Users.hbm.xml

<hibernate-mapping>    <class name="a.b.c.Users">        <id name="uid">            <generator class="increment"/>        </id>        <property name="uname"/>        <!-- one-to-many -->        <set name="files" cascade="all">            <key column="u_id"/>            <one-to-many class="a.b.c.UpFile"/>        </set>    </class></hibernate-mapping>  

Upfile.hbm.xml

<hibernate-mapping>    <class name="a.b.c.UpFile">        <id name="fid">            <generator class="increment"/>        </id>        <property name="fileName"/>        <property name="fsize"/>        <many-to-one name="users" column="u_id" cascade="all"></many-to-one>    </class></hibernate-mapping>    

此时如果从多的一端来维护数据,比如我在这里插入为uid=1的user插入在关联一个upfile文件:

Configuration cfg = new Configuration().configure();    SessionFactory factory = cfg.buildSessionFactory();     Session session = factory.openSession();                try {    session.beginTransaction();     Users u = (Users) session.get(Users.class,1);    UpFile f = new UpFile("fff.txt",453);    UpFile f2 = new UpFile("ttt.txt",500);    f.setUsers(u);    f2.setUsers(u);    session.save(f);    session.save(f2);    session.getTransaction().commit();                      } catch (HibernateException e) {    e.printStackTrace();    session.getTransaction().rollback();                    }session.close();

可以看到,这个时候就是通过f2.setUsers(u);这样的方式来建立关联的。存入数据也是存入的多端数据即可。
这里写图片描述
此时对于一对多的双向关联,一的一端和多的一端都可以同时维护数据,那么如果我只想让多的一端来维护数据,可以添加一个inverse=”true”这个关键字。

<set name="files" cascade="all" inverse="true">    <key column="u_id"/>    <one-to-many class="a.b.c.UpFile"/></set>

好了,关于hibernate一对多的学习就到这里了。

0 0
原创粉丝点击