单向的一对多关联
创建对应的实体类以及映射文件
package cn.bdqn.bean; /*** * @author 小豆腐*街道对应的实体类**单向的多对一关联*/ public class Street {private Integer id;private String name;//多个街道 属于 一个区县private District district; //对应的区县public District getDistrict() {return district;}public void setDistrict(District district) {this.district = district;}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 Street(Integer id, String name) {super();this.id = id;this.name = name;}public Street() {super();}@Overridepublic String toString() {return "Street [id=" + id + ", name=" + name + "]";}}
<?xml version="1.0"?> <!DOCTYPE hibernate-mapping PUBLIC"-//Hibernate/Hibernate Mapping DTD 3.0//EN""http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"><hibernate-mapping package="cn.bdqn.bean"><class name="Street"><id name="id"> <generator class="assigned"/><!-- 手动给主键赋值 --></id> <property name="name"/><!-- 配置多对一关联name:对应的是 本类中 关联关系的属性名column:对应数据库中 两个表的 外键!class:关联的实体类--><many-to-one name="district" column="districtId" class="District"/> </class> </hibernate-mapping>
package cn.bdqn.bean; /*** @author 小豆腐**区县的实体类*/ public class District {private Integer id;private String name;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 District(Integer id, String name) {super();this.id = id;this.name = name;}public District() {super();}@Overridepublic String toString() {return "Street [id=" + id + ", name=" + name + "]";}}
<?xml version="1.0"?> <!DOCTYPE hibernate-mapping PUBLIC"-//Hibernate/Hibernate Mapping DTD 3.0//EN""http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"><hibernate-mapping package="cn.bdqn.bean"><class name="District"><id name="id"> <generator class="assigned"/><!-- 手动给主键赋值 --></id> <property name="name"/></class> </hibernate-mapping>
需要在hibernate.cfg.xml文件中 配置映射文件
测试类
Session session=null;Transaction transaction=null;//获取session 开启事务@Beforepublic void before(){session=HibernateSessionUtil.getCurrentSession();transaction= session.beginTransaction();}/*** 测试单向的多对一的关联* * 创建对应的区县 新增几个区县 以备后续使用*/@Testpublic void testAdd(){District district=new District(3, "区县3");session.save(district); //保存transaction.commit(); //提交事务}//新增 街道的同时 给街道对应的区县赋值@Testpublic void test01(){//创建一个街道Street street=new Street();street.setId(1);street.setName("街道1");//给对应的区县赋值District district= (District) session.load(District.class, 1);street.setDistrict(district);session.save(street); //保存transaction.commit(); //提交事务 只会产生一条sql insert}//修改 街道对应的区县 @Testpublic void test02(){//从数据库中获取一个街道Street street=(Street) session.load(Street.class, 1); // 对应的区县是1District district=(District) session.load(District.class, 2); // 区县是2//修改street.setDistrict(district); // 不需要 update 因为两个对象都是持久化对象//提交事务transaction.commit();}//删除 街道对应的区县 @Testpublic void test03(){//从数据库中获取一个街道Street street=(Street) session.load(Street.class, 1); // 对应的区县是2//修改street.setDistrict(null); //提交事务transaction.commit();}
双向的一对多关联就是在单向多对一的基础上增加一个单向的一对多!
修改District代码 一对多关联
package cn.bdqn.bean;import java.util.ArrayList; import java.util.List;/*** @author 小豆腐**区县的实体类* 一对多的关联关系*/ public class District {private Integer id;private String name;// 一个区县 有 多个街道private List<Street> streets=new ArrayList<>();public List<Street> getStreets() {return streets;}public void setStreets(List<Street> streets) {this.streets = streets;}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 District(Integer id, String name) {super();this.id = id;this.name = name;}public District() {super();}@Overridepublic String toString() {//如果写成streets 会出现 堆栈溢出的异常!return "District [id=" + id + ", name=" + name + ", streets=" + streets.size()+ "]";}}
修改District.hbm.xml文件代码
<?xml version="1.0"?> <!DOCTYPE hibernate-mapping PUBLIC"-//Hibernate/Hibernate Mapping DTD 3.0//EN""http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"><hibernate-mapping package="cn.bdqn.bean"><class name="District"><id name="id"> <generator class="assigned"/><!-- 手动给主键赋值 --></id> <property name="name"/><!-- 设置一对多 name:本类中的关联属性名 集合的名称column: 就是数据库表中的外键order-by="id desc" 按照 街道的id 进行 降序排列inverse:是由谁来维护表与表之间的关系! 默认是false!(维护) true(不维护)--><bag name="streets" cascade="all" inverse="true"><key column="districtId"/><one-to-many class="Street"/></bag></class> </hibernate-mapping>
在测试类中增加代码
/*** 创建几个街道 测试 双向的一对多关联*/@Testpublic void test04(){Street street=new Street();street.setId(4);street.setName("街道4");//给对应的区县赋值District district= (District) session.load(District.class, 1);street.setDistrict(district);session.save(street); //保存//提交事务transaction.commit();}//根据区县 获取所管辖的街道@Testpublic void test05(){District district=(District) session.load(District.class, 1);List<Street> streets = district.getStreets();for (Street street : streets) {System.out.println(street);}}/*** 根据区县 获取所管辖的街道 根据街道的编号 降序排列* 01.只需要在 bag节点中 增加 order-by属性 = id desc*/@Testpublic void test06(){District district=(District) session.load(District.class, 1);List<Street> streets = district.getStreets();for (Street street : streets) {System.out.println(street);}}/*** 02.使用hql语句*/@Testpublic void test07(){String hql="from Street s where districtId=:id order by s.id desc";//创建query对象Query query = session.createQuery(hql);//给参数赋值query.setParameter("id", 1); //区县编号是1//遍历结果集List<Street> list = query.list();for (Street street : list) {System.out.println(street);}}/*** cascade属性:定义的是关系两端 对象到对象的级联关系!* 必须是 双向的一对多关联!* * 常用的属性值:* 01.none:默认值!当session操作当前对象的时候,忽略关联的属性!* 02.save-update:当session调用save,saveorUpdate以及update()的时候!* 会级联的保存和修改当前对象以及对象关联的属性!* 001.去区县的xml文件中 的 bag节点 增加 cascade属性! * 002.直接运行以下代码 * 03.delete: 当session调用 delete()的时候,会级联删除所关联的对象 !* 04.all: 包括了save-update和delete!* * 添加区县的同时 添加街道*/@Testpublic void test08(){//创建区县District district=new District(4, "区县4");//创建街道Street street1=new Street(5, "街道5");Street street2=new Street(6, "街道6");Street street3=new Street(7, "街道7");//给区县的街道赋值district.getStreets().add(street1);district.getStreets().add(street2);district.getStreets().add(street3);//保存区县session.save(district); //发现 保存了 区县 但是 没有保存对应的街道!transaction.commit();/*** 程序执行之后的结果:* Hibernate: insert into District (name, id) values (?, ?)Hibernate: update Street set districtId=? where id=?Hibernate: update Street set districtId=? where id=?Hibernate: update Street set districtId=? where id=?*//*** 在xml文件中设置了 cascade="save-update" 之后的结果* * 问题:虽然级联保存成功了!* 但是有多余update语句!* 为什么会出现多余的? 两个对象都在维护彼此之间的关系!* * Hibernate: select street_.id, street_.name as name1_, street_.districtId as districtId1_ from Street street_ where street_.id=?Hibernate: select street_.id, street_.name as name1_, street_.districtId as districtId1_ from Street street_ where street_.id=?Hibernate: select street_.id, street_.name as name1_, street_.districtId as districtId1_ from Street street_ where street_.id=?Hibernate: insert into District (name, id) values (?, ?)Hibernate: insert into Street (name, districtId, id) values (?, ?, ?)Hibernate: insert into Street (name, districtId, id) values (?, ?, ?)Hibernate: insert into Street (name, districtId, id) values (?, ?, ?)Hibernate: update Street set districtId=? where id=?Hibernate: update Street set districtId=? where id=?Hibernate: update Street set districtId=? where id=?*/}/*** cascade="delete" xml中的配置* 删除 区县 的同时 删除 街道!*/@Testpublic void test09(){District district= (District) session.load(District.class, 1);//获取三个街道Street street1= (Street) session.load(Street.class, 2);Street street2= (Street) session.load(Street.class, 3);Street street3= (Street) session.load(Street.class, 4);session.delete(district);transaction.commit();/*** Hibernate: update Street set districtId=null where districtId=?Hibernate: delete from Street where id=?Hibernate: delete from Street where id=?Hibernate: delete from Street where id=?Hibernate: delete from District where id=?*/}/*** 针对于 多余的sql语句 解决办法!* * 只需要一方来维护表之间的关系!* inverse属性:* 01.默认是false(由我维护!)* 02.inverse=true:这一方不维护关系!(不与数据库交互)* * * 不能都维护,也不能都 不维护! 这个时候关键是谁来维护这个关系?* 双向的一对多! * hibernate:规定多的一端来维护关系,那么必须在一的一方设置 inverse=true:*/@Testpublic void test10(){//创建区县District district=new District(4, "区县4");//创建街道Street street1=new Street(5, "街道5");Street street2=new Street(6, "街道6");Street street3=new Street(7, "街道7");//给区县的街道赋值district.getStreets().add(street1);district.getStreets().add(street2);district.getStreets().add(street3);//保存区县session.save(district); //发现 保存了 区县 但是 没有保存对应的街道!transaction.commit();/*** * 发现 没有了 update语句!* Hibernate: select street_.id, street_.name as name1_, street_.districtId as districtId1_ from Street street_ where street_.id=?Hibernate: select street_.id, street_.name as name1_, street_.districtId as districtId1_ from Street street_ where street_.id=?Hibernate: select street_.id, street_.name as name1_, street_.districtId as districtId1_ from Street street_ where street_.id=?Hibernate: insert into District (name, id) values (?, ?)Hibernate: insert into Street (name, districtId, id) values (?, ?, ?)Hibernate: insert into Street (name, districtId, id) values (?, ?, ?)Hibernate: insert into Street (name, districtId, id) values (?, ?, ?)*/}