java 代码
- 一、many-to-one关系在数据库中如何体现,在JavaBean中如何体现,在Hibernate中如何映射many-to-one关系。
- 1、数据库中:一个表的主健对应另一个表的外健。
- 2、javaBean中:一个对象包含另一个对象的一个引用,另一个对象包含这个对象的一组(集合,用set)引用。
- 3、在hibernate中:用set.key指定具体列。
- 我们以订单Order(一方)和订单项Item(多方)为例:
- a、Order.hbm.xml的写法:
- <class name="Order" table="ec_order">
- <id name="id" column="id" type="integer">
- <generator class="native" />
- </id>
- <property name="owner" column="owner" type="string" />
- <property name="phone" column="phone" type="string" />
- <property name="address" column="address" type="string" />
- <set name="items" cascade="all-delete-orphan" inverse="true">
- <key column="orderid" />
- <one-to-many class="Item" />
- </set>
- </class>
- 注:inverse=“true”表示忽略集合一端的变化。
- cascade="all-delete-orphan":这个比较麻烦一点,我们先来看看把cascade设为all的情况:在我们调用session.delete(order)时,会删除order下所有的item,但是如果调用order.getItems().remove(item),然后调用session.update(order)则不会删除此item,只会把 ec_item表中该条item记录的order_id设置为null。因此,如果想通过order.getItems.remove(item)删除对象,需要在已有级联的基础上加上“delete-orphan”。
- b、Item.hbm.xml的写法
- <class name="Item" table="ec_item">
- <id name="id" column="id" type="integer">
- <generator class="native" />
- </id>
- <property name="product" column="product" type="string" />
- <property name="amount" column="amount" type="integer" />
- <many-to-one name="order" class="Order" column="orderid"/>
- </class>
- inverse="true"就是在设置如果在内存中的修改或添加了这个集合中的某一个或某几个对象他不会将全部集合的信息同步到数据库,
- 而是只将集合中被修改的对象重新同步到数据库。
- cascade属性是设置级联操作的也就是在操作一端的数据如果影响到多端数据时会进行级联操作,
- cascade="none",cascade="save-update",cascade="delete",cascade="all" cascade="persist"
- cascade="delete-orphan",cascade属性的值常用的设置为以上五项:
- none就是不使用级联操作,默认级联是none。
- save-update也就是只有对象保存操作(持久化操作)或者是持久化对象的更新操作,才会级联操作关联对象(子对象)。
- persist就只是将级联对象也持久化到数据库。
- delete对持久化对象的删除操作时会进行级联操作关联对象(子对象)。
- all对持久化对象的所有操作都会级联操作关联对象(子对象)。
- all-delete-orphan,在多端进行删除操作时,会再多端表中留下null空纪录,设置了级联操作为delete之会将表中表示关联的外键id置成null,
- 不会将这条纪录也删除掉,而把级联设置成delete-orphan就不会留有空纪录,而是级联的把相关纪录删除掉。
- batch-size这个属性只能够写在set标签中,这个属性带表批量加载,也就是在加载一端的集合属性时会一次加载指定的数量的对象,
- 而不是默认的一个一个的加载,会提高效率,批量加载只能用于延迟加载和立即加载策略,也就是(lazy="true"或者lazy="false")。
- lazy="true" 延迟加载,所谓的延迟加载,就是对一端的集合属性的加载策略,就是在不使用到集合中的对象的数据就不会真正的加载集合
- 中的对象数据,而是家在一个代理对象就相当于的一个空的容器。这也就是会出现LazyInitializationException异常,也就是没有初始化
- 这个代理的集合对象,在事先查询到了集合中的对象就会初始化这个对象,如果Session没有关闭就会在查询加载集合中的对象信息,如果
- 提前关闭了Session,当使用集合中的对象信息时就会有这个异常。
- fetch="join",这就是使用了预先抓取策略,也就是针对关联的对象的加载策略,在使用到关联对象的信息时会再发送sql语句,如果不使
- 用fetch="join",就会不使用表连接而是先查出一端的关联id再一条一条的发送sql语句查询到关联对象信息,使用了fetch="join"就会使
- 用表连接将关联对象信息直接查寻出来的。fetch="lazy"这个是默认的设置。
- 注意:
- 在使用fetch="join"要区分开他和外连接的区别,他不会忽略配置文件中的加载策略,而使用了外连接就会忽略配置文件中使用了外连接的
- 一端的所有加载策略,而替之为立即加载。
- 例:班级 tream,身份证 Certigicate 学生 student
- 身份证和学生是一对一关系,班级和学生是一对多的关系。学生对身份证的加载策略是预先抓取,学生对班级是预先抓取,但是班级对学生
- 是延迟加载。
- 现在使用了外连接
- Query q=session.createQuery("from Student as s left join s.team");
- as 的语法是取别名的语法。
- 也就是使用了外连接的来查寻班级,这样就会忽略,学生对象对其所有属性除了使用外连接查寻的属性,而其余都会使用立即加载。
- <property name="" column="" type="" not-null="true">,这样也就会使这个属性不能够为空值
- 查询对象,可以使用get()和load()方法,不过前提是必须知道该对象持久化时的唯一标识,也就是id,和这个对象的类对象。
- 二、多对多的映射实现(many-to-many)
- 一般多对多关联会拆分成两个一对多的关系来实现多对多关系,也可以通过hibernate提供的解决方案来实现。其实hibernate的实现方式是通过中间表间接的实现了多对多关系,实际上也是将多对多拆分成两个双向的一对多关系。
- 多对多关系XML文件的配置
- <hibernate-mapping>
- <class name="Course" table="course">
- <set name="clazz" table="class_course" inverse="true"><!--设置中间表的表名-->
- <key column="courseid">
- <many-to-many column="classid" class="Clazz"/>
- </set>
- </class>
- </hibernate-mapping>
- <hibernate-mapping>
- <class name="Clazz" table="class">
- <set name="course" table="class_course" cascade="save-update">
- <key column="classid"/>
- <many-to-many column="courseid" class="Course"/>
- </set>
- </class>
- </hibernate-mapping>
- Hibernate知识点小记
- 一、cascade
- cascade属性是设置级联操作的也就是在操作一端的数据如果影响到多端数据时会进行级联操作,一对一的时候直接写在标签上,其他的要写在set标签上
- cascade="none|save-update|all|all-delete-orphan"
- none 就是不使用级联操作,默认级联是none。
- save-update 也就是只有对象保存操作(持久化操作)或者是持久化对象的更新操作,才会级联操作关联对象(子对象)。
- all 对持久化对象的所有操作都会级联操作关联对象(子对象)。
- all-delete-orphan,在多端进行删除操作时,会再多端表中留下null空纪录,设置了级联操作为delete之会将表中表示关联的外键id置成null,不会将这条纪录也删除掉,而把级联设置成delete-orphan就不会留有空纪录,而是级联的把相关纪录删除掉。
- 二、inverse
- inverse="true"就是在设置如果在内存中的修改或添加了这个集合中的某一个或某几个对象他不会将全部集合的信息同步到数据库,而是只将集合中被修改的对象重新同步到数据库
- 三、lazy
- lazy=“true”
- 延迟加载,所谓的延迟加载,就是对一端的集合属性的加载策略,就是在不使用到集合中的对象的数据就不会真正的加载集合中的对象数据,而是家在一个代理对象就相当于的一个空的容器。
- 这也就是会出现LazyInitializationException异常,也就是没有初始化这个代理的集合对象,在事先查询到了集合中的对象就会初始化这个对象,如果Session没有关闭就会在查询加载集合中的对象信息,如果提前关闭了Session,当使用集合中的对象信息时就会有这个异常。
- 四、fetch
- fetch=“join”,这就是使用了预先抓取策略,也就是针对关联的对象的加载策略,在使用到关联对象的信息时会再发送sql语句,如果不使用fetch=“join”,就会不使用表连接而是先查出一端的关联id再一条一条的发送sql语句查询到关联对象信息,使用了fetch=“join”就会使用表连接将关联对象信息直接查寻出来的。fetch=“lazy”这个是默认的设置。
- 五、多对多
- 写配置文件的时候要紧记一个原则就不会错了:
- <key column =””>总是和本身类的主键id对应
- <column=””>总是和关联类的主键id相对应
- 比如:
- <set name="courses" table="enrollments " inverse="true" cascade="save-update">
- <key column="sid"/>
- <many-to-many class="Course" column="cid" />
- </set>