hibernate单向多对一映射

来源:互联网 发布:淘宝存在隐形降权吗 编辑:程序博客网 时间:2024/06/11 02:50

在实际的开发中,数据库表之间的关系有很多都是多对一的关联关系,这种情况的业务,在hibernate中该怎么处理呢?今天我们就来学习一下hibernate的单向多对一映射关系。


新建一个java项目,名称为:08hibernate_many_to_one

项目结构如图:



需要的jar包和如何从hibernate官网获得,请参见《Hibernate环境搭建和配置


实体类Grade代码如下:

package com.robert.pojo;/** * 年级类 */public class Grade {private int id ;private String name ;//年级名称public int getId() {return id;}public void setId(int id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}}

Student类代码如下:

package com.robert.pojo;/** * 学生类 */public class Student {private int id ;private String name ;//姓名private int age ;    //年龄private Grade grade ;//年级public int getId() {return id;}public void setId(int id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}public Grade getGrade() {return grade;}public void setGrade(Grade grade) {this.grade = grade;}}

实体类Grade对应的配置文件Grade.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="com.robert.pojo"><class name="Grade"><id name="id"><generator class="native"></generator></id><property name="name"></property></class></hibernate-mapping>


实体类Student对应的配置文件Student.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="com.robert.pojo"><class name="Student"><id name="id"><generator class="native"></generator></id><property name="name"></property><property name="age"></property><!-- 多对一name:属性名;class:属性对应的类;column:数据库表中的列名; --><many-to-one name="grade" class="Grade" column="grade_id" /></class></hibernate-mapping>

hibernate.cfg.xml配置文件代码:

<!DOCTYPE hibernate-configuration PUBLIC"-//Hibernate/Hibernate Configuration DTD 3.0//EN""http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd"><hibernate-configuration><session-factory><!-- 配置数据库连接信息 --><property name="connection.driver_class">com.mysql.jdbc.Driver</property><property name="connection.url">jdbc:mysql:///hibernate4</property><property name="connection.username">root</property><property name="connection.password">root</property><!-- 数据库方言 --><property name="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect</property><!-- 是否打印sql语句 --><property name="show_sql">true</property><!-- 格式化sql语句 --><property name="format_sql">true</property><!-- 数据库更新方式: 1、create:每次更新都先把原有数据库表删除,然后创建该表;2、create-drop:使用create-drop时,在显示关闭SessionFacroty时(sessionFactory.close()),将drop掉数据库Schema(表) 3、validate:检测;4、update(常用):如果表不存在则创建,如果存在就不创建--><property name="hbm2ddl.auto">update</property><!-- 加载Score实体类对应的配置文件 --><mapping resource="com/robert/pojo/Grade.hbm.xml" /><mapping resource="com/robert/pojo/Student.hbm.xml" /></session-factory></hibernate-configuration>

封装的工具类HibernateUtil类的代码如下:

package com.robert.util;import org.hibernate.Session;import org.hibernate.SessionFactory;import org.hibernate.boot.registry.StandardServiceRegistryBuilder;import org.hibernate.cfg.Configuration;/** * hibernate工具类 */public class HibernateUtil {private static Configuration cfg = null;private static SessionFactory factory = null;private static Session session = null ;static {init();}/** * 初始化获得Configuration和SessionFacroty对象 */public static void init() {cfg = new Configuration().configure();factory = cfg.buildSessionFactory(new StandardServiceRegistryBuilder().applySettings(cfg.getProperties()).build());}/** * 获得Session对象 * @return */public static Session getSession() {if (factory != null){return session = factory.openSession();}init();return session = factory.openSession();}/** * 关闭Session */public static void closeSession() {if(session!=null && session.isOpen())session.close();}}

测试类HibernateTest代码如下:

package com.robert.test;import java.io.IOException;import java.sql.SQLException;import javax.sql.rowset.serial.SerialException;import org.hibernate.HibernateException;import org.hibernate.Session;import org.hibernate.Transaction;import org.hibernate.cfg.Configuration;import org.hibernate.tool.hbm2ddl.SchemaExport;import org.junit.Test;import com.robert.pojo.Grade;import com.robert.pojo.Student;import com.robert.util.HibernateUtil;public class HibernateTest {/** * 根据*.hbm.xml文件对应的生成数据库表 */@Testpublic void testCreateDB() {Configuration cfg = new Configuration().configure();SchemaExport se = new SchemaExport(cfg);// 第一个参数:是否生成ddl脚本// 第二个参数:是否执行到数据库中se.create(true, true);}/** * 保存数据 * @throws HibernateException * @throws SerialException * @throws SQLException * @throws IOException */@Testpublic void testSave() throws HibernateException, SerialException,SQLException, IOException {Session session = null;Transaction tx = null;try {session = HibernateUtil.getSession();tx = session.beginTransaction();Grade grade = new Grade();grade.setName("基础") ;session.save(grade);Student student = new Student() ;student.setName("张三") ;student.setAge(22) ;student.setGrade(grade) ;session.save(student);tx.commit();} catch (HibernateException e) {if (tx != null) {tx.rollback();}e.printStackTrace();throw e;} finally {HibernateUtil.closeSession();}}}

使用Junit4运行testCreateDB方法,生成数据库表




使用Junit4执行testSave方法,将数据保存到数据库表中



数据库表数据如图:




补充知识:

多对一(many-to-one)知识:

通过many-to-one元素,可以定义一种常见的与另一个持久化类的关联。 这种关系模型是多对一关联(实际上是一个对象引用-译注):这个表的一个外键引用目标表的 主键字段。 


<many-to-one        name="propertyName"        column="column_name"        class="ClassName"        cascade="cascade_style"        fetch="join|select"        update="true|false"        insert="true|false"        property-ref="propertyNameFromAssociatedClass"        access="field|property|ClassName"        unique="true|false"        not-null="true|false"        optimistic-lock="true|false"        lazy="proxy|no-proxy|false"        not-found="ignore|exception"        entity-name="EntityName"        formula="arbitrary SQL expression"        node="element-name|@attribute-name|element/@attribute|."        embed-xml="true|false"        index="index_name"        unique_key="unique_key_id"        foreign-key="foreign_key_name"        />

name: 属性名。

column (可选): 外间字段名。它也可以通过嵌套的 <column>元素指定。

class (可选 - 默认是通过反射得到属性类型): 关联的类的名字。

cascade(级联) (可选): 指明哪些操作会从父对象级联到关联的对象。

fetch (可选 - 默认为 select): 在外连接抓取(outer-join fetching)和序列选择抓取(sequential select fetching)两者中选择其一。

update, insert (可选 - 默认为 true) 指定对应的字段是否包含在用于UPDATE 和/或 INSERT 的SQL语句中。如果二者都是false,则这是一个纯粹的 “外源性(derived)”关联,它的值是通过映射到同一个(或多个)字段的某些其他属性得到 或者通过trigger(触发器)、或其他程序生成。

property-ref: (可选) 指定关联类的一个属性,这个属性将会和本外键相对应。 如果没有指定,会使用对方关联类的主键。

access (可选 - 默认是 property): Hibernate用来访问属性的策略。

unique (可选): 使用DDL为外键字段生成一个唯一约束。此外, 这也可以用作property-ref的目标属性。这使关联同时具有 一对一的效果。

not-null (可选): 使用DDL为外键字段生成一个非空约束。

optimistic-lock (可选 - 默认为 true): 指定这个属性在做更新时是否需要获得乐观锁定(optimistic lock)。 换句话说,它决定这个属性发生脏数据时版本(version)的值是否增长。

lazy (可选 - 默认为 proxy): 默认情况下,单点关联是经过代理的。lazy="no-proxy"指定此属性应该在实例变量第一次被访问时应该延迟抓取(fetche lazily)(需要运行时字节码的增强)。 lazy="false"指定此关联总是被预先抓取。

not-found (可选 - 默认为 exception): 指定外键引用的数据不存在时如何处理: ignore会将行数据不存在视为一个空(null)关联。

entity-name (可选): 被关联的类的实体名。

formula (可选): SQL表达式,用于定义computed(计算出的)外键值。


cascade属性设置为除了none以外任何有意义的值, 它将把特定的操作传递到关联对象中。这个值就代表着Hibernate基本操作的名称, persist, merge, delete, save-update, evict, replicate, lock, refresh, 以及特别的值delete-orphan和all,并且可以用逗号分隔符 来组合这些操作,例如,cascade="persist,merge,evict"或 cascade="all,delete-orphan"。更全面的解释请参考第 10.11 节 “传播性持久化(transitive persistence)”. 注意,单值关联 (many-to-one 和 one-to-one 关联) 不支持删除孤儿(orphan delete,删除不再被引用的值).

一个典型的简单many-to-one定义例子:

<many-to-one name="product" class="Product" column="PRODUCT_ID"/>
property-ref属性只应该用来对付遗留下来的数据库系统, 可能有外键指向对方关联表的是个非主键字段(但是应该是一个惟一关键字)的情况下。 这是一种十分丑陋的关系模型。比如说,假设Product类有一个惟一的序列号, 它并不是主键。(unique属性控制Hibernate通过SchemaExport工具进行的DDL生成。)

<property name="serialNumber" unique="true" type="string" column="SERIAL_NUMBER"/>
那么关于OrderItem 的映射可能是:

<many-to-one name="product" property-ref="serialNumber" column="PRODUCT_SERIAL_NUMBER"/>
当然,我们决不鼓励这种用法。

如果被引用的唯一主键由关联实体的多个属性组成,你应该在名称为<properties>的元素 里面映射所有关联的属性。

假若被引用的唯一主键是组件的属性,你可以指定属性路径:

<many-to-one name="owner" property-ref="identity.ssn" column="OWNER_SSN"/>







原创粉丝点击