Hibernate实体关系映射(OneToMany、ManyToOne双边)——完整实例

双边关系是最常见的配置。在多方有一方的引用,一方也有多方的引用。双边关系能够很方便地查询数据。看一个班级与学生的双边关系。

班级(Clazz类)与学生(Student类):一对多关系。班级中有学生属性,学生中有班级属性,二者是双边关系。(Class是关键字,不能用)

分析:Clazz为一方,Student为多方。Clazz中有Student集合属性,Student中也有Clazz类型属性。

环境:MyEclipse10,新建Web Project名为hibernate

    

1、Clazz.java

Clazz类中有一个id主键、一个name属性、一个List<Student>集合代表该班级内的学生。班级与学生关系是一对多,这里使用@OneToMany配置,并用mappedBy属性配置与该List<Student>属性对应的是Student类中的clazz属性。具体的关联配置都在Student的clazz属性上。

双边关系中,控制权一般交给多方,因此这里的@OneToMany没有设置数据库的外键列,而只配置了一个mappedBy属性,值为clazz,告诉hibernate,配置信息要到Student类的clazz属性中找。

package com.hibernate.bean;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Map;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.MapKey;
import javax.persistence.OneToMany;
import javax.persistence.Table;

import org.hibernate.annotations.Cascade;
import org.hibernate.annotations.CascadeType;

@Entity
@Table(name = "tb_class")
public class Clazz {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Integer id;

    private String name;

    @OneToMany(mappedBy = "clazz")
    @Cascade(value = CascadeType.DELETE_ORPHAN)
    private List<Student> students = new ArrayList<Student>();

    // @OneToMany(mappedBy = "clazz")
    // @MapKey(name="name")
    // private Map<String, Student> students = new HashSet<String, Student>();

    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 List<Student> getStudents() {
        return students;
    }

    public void setStudents(List<Student> students) {
        this.students = students;
    }

}

2、Student.java

  Student类中有一个id主键以及name姓名、sex性别两个普通属性,还有一个Clazz类型的属性clazz,代表所在的班级。该属性与Clazz中的List<Student>集合属性是对应的。从逻辑上来讲,某student的clazz属性为某clazz,该clazz的List<Student>中必定还有改student。配置了mappedBy后,hibernate能自动维护这种关系。

  Student与Clazz是多对一的关系,多对一使用@ManyToOne配置,另外用@JoinColumn配置关联的列名。这里用tb_student表的class_id列与tb_class的id主键列连接。这里同时配置了级联保存类型为PERSIST,创建student时,会自动将clazz也写进数据库。

package com.hibernate.bean;

import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;

@Entity
@Table(name = "tb_student")
public class Student {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Integer id;

    @ManyToOne(fetch = FetchType.EAGER, cascade = { CascadeType.PERSIST })
    @JoinColumn(name = "class_id")  //外键为class_id
    private Clazz clazz;

    private String name;

    private String sex;

    public Clazz getClazz() {
        return clazz;
    }

    public void setClazz(Clazz clazz) {
        this.clazz = clazz;
    }

    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 String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }

}

3、hibernate.cfg.xml(src目录下)

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">

<hibernate-configuration>

    <session-factory>
      <property name="show_sql">true</property>
      <property name="format_sql">true</property>
      <property name="connection.driver_class">oracle.jdbc.driver.OracleDriver</property>
      <property name="connection.url">jdbc:oracle:thin:@192.168.1.2:1521:orcl</property>
      <property name="connection.username">daym2</property>
      <property name="connection.password">daym2</property>
      <property name="connection.isolation">2</property>
       <property name="hbm2ddl.auto">create</property>
       <property name="javax.persistence.validation.mode">none</property>

      <!-- SQL方言,这边设定的是Oracle -->
      <property name="dialect">org.hibernate.dialect.Oracle10gDialect</property>

      <property name="current_session_context">thread</property>
      <mapping class="com.hibernate.bean.Cat" />
      <mapping class="com.hibernate.bean.Person" />
      <mapping class="com.hibernate.bean.Email" />
      <mapping class="com.hibernate.bean.Clazz" />
      <mapping class="com.hibernate.bean.Student" />
    </session-factory>
</hibernate-configuration>

4、TestClazzStudent.java

package com.hibernate.bean;
import java.util.List;

import org.hibernate.Session;

import com.hibernate.bean.Clazz;
import com.hibernate.bean.Student;
import com.hibernate.bean.HibernateSessionFactory;

public class TestClazzStudent {

    @SuppressWarnings("all")
    public static void main(String[] args) throws Exception {

        Clazz clazz = new Clazz();
        clazz.setName("三年二班");

        Student student1 = new Student();
        student1.setName("周周");
        student1.setSex("男");

        Student student2 = new Student();
        student2.setName("李四");
        student2.setSex("女");

        Session session = HibernateSessionFactory.getSession();
        session.beginTransaction();

        // 保存进数据库
        session.persist(clazz);
        session.persist(student1);
        session.persist(student2);

        // 设置班级
        student1.setClazz(clazz);
        student2.setClazz(clazz);
        // clazz.getStudents().add(student1);
        // clazz.getStudents().add(student2);

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

        session = HibernateSessionFactory.getSession();
        session.beginTransaction();

        // 查询名为“三年二班”的班级 然后输出学生
        Clazz c = (Clazz) session.createQuery(
                " select c from Clazz c where c.name = :name ").setParameter(
                "name", "三年二班").uniqueResult();

        System.out.println("三年二班 的所有学生:");
        for (Student s : c.getStudents()) {
            System.out.println("\t姓名:" + s.getName() + ", 性别:" + s.getSex());
        }

        // 直接查询班级为“三年二班”的学生
        List<Student> students = session.createQuery(
                " select s from Student s where s.clazz.name = :name ")
                .setParameter("name", "三年二班").list();

        System.out.println("三年二班 的所有学生:");
        for (Student s : students) {
            System.out.println("\t姓名:" + s.getName() + ", 性别:" + s.getSex());
        }

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

    }

}

5、log4j.properties (src目录下)

log4j.rootLogger=INFO,stdout
log4j.category.org.hibernate.tool.hbn2ddl=DEBUG
log4j.category.org.hibernate.SQL=DEBUG
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%-d{yyyy-MM-dd HH\:mm\:ss,SSS} [%c]-[%p] %m%n
时间: 2024-08-01 22:44:19

Hibernate实体关系映射(OneToMany、ManyToOne双边)——完整实例的相关文章

hibernate 实体关系映射笔记

@常用属性说明: @Entity:实体类 @Table:指定对应数据表 @Id:主键,使用可以为null值的类型,如果实体类没有保存到数据库是一个临时状态 @Column:配置普通属性,除了主键外,java基本类型的属性 @Base:普通属性的加载方式 @GeneratedValue:主键生成策略 @Temporal:日期类型(DATE,TIME还是TIMESTAMP),如果属性类型是java.util.Date(是以上3个类的父类)类型时才需要使用该@声明具体的日期类型 @Transient:

JPA总结——实体关系映射(一对多@OneToMany)

JPA总结——实体关系映射(一对多@OneToMany) 并注明来源: http://blog.sina.com.cn/s/blog_49fd52cf0100scql.html 一对多模型(单向)说明:一个客户对应多个地址,通过客户可以获得该客户的多个地址的信息.客户和地址是一对多的关系,并且客户与地址是单向关联的关系. 映射策略# 外键关联:两个表的关系定义在一个表中:# 表关联:两个表的关系单独定义一个表中通过一个中间表来关联.映射策略——外键关联 表结构如下: 1 TABLE custom

hibernate 对象关系映射文件详解

POJO 类和数据库的映射文件*.hbm.xml POJO类和关系数据库之间的映射可以用一个XML文档来定义. 映射文件的扩展名为.hbm.xml 在运行时Hibernate将根据这个映射文件来生成各种SQL语句 通过POJO类的数据库映射文件,Hibernate可以理解持久化类和数据表之间的对应关系,也可以理解持久化类属性与数据库表列之间的对应关系 映射文件说明 hibernate-mapping 类层次:class 主键:id 基本类型:property 实体引用类: many-to-one

持久化API(JPA)系列(六)实体关系映射(ORM)之映射类型

ORM实体关系映射,即将数据库中的数据表及表之间的关系,通过实体Bean及实体Bean之间的关系表现出来,实现通过操作实体Bean来操作数据库. ORM(Object-Relation-Map),其中Object表示实体Bean,Relation表示数据表,Map表示实体Bean与数据表的映射. 由于EJB3中的实体Bean采用JPA框架,因此这里的ORM就是指JPA映射.它的作用也类似于Hibernate.iBATIS.JDO.TopLink等持久化层框架中的实体关系映射. 根据表与表之间的关

hibernate继承关系映射和java反射机制的运用

转:http://blog.csdn.net/derpvailzhangfan/article/details/1957946 ,感谢博主分享 Notes:hibernate元数据的运用:uuid的概念:java的反射机制,“因为抽象类无法new出对象来,所以就要用java反射机制”,“TcommTable tomm = (TcommTable) Class.forName(allName).newInstance();”: hibernate继承关系映射大概有5种,这5种继承关系映射里面,我觉

Hibernate Annotation关系映射, 级联cascade属性

Hibernate Annotation关系映射, 级联cascade属性一. Hibernate Annotation关系映射 1.一对一外键关联映射(单向) 2.一对一外键关联映射(双向) 3.一对一主键关联映射(不重要)在这不演示 在实际中很少用,使用注解@PrimaryKeyJoinColumn 意思是说,我的主键去参考另外一张表中的主键,作为我的主键,但是在我测试使用 注解一对一主键关联映射,在生成表的时候,数据库中并没有生成关联,使用XML 映射可以生成.Annotation注解一对

OrchardNoCMS实体关系映射扩展

在OrchardNoCMS中,默认的系统会把实体关系映射保存到mappings.bin文件中. 如果不进行任何修改,默认的可以自动保存关系映射的model是有很大限制的. 条件是model的命名空间必须是以Orchard开头,以Models结尾.CompositionStrategy.cs中可以看到判断一个类是否需要保存映射关系的代码: 假设我们现在想按照公司的名称为Model的命名空间,加添完Model运行后,你会发现,在数据库中进行增删改查是没有数据的,因为根本没有生成关系映射. 你可以通过

持久化API(JPA)系列(八)实体关系映射(ORM)之单表映射@EmbeddedId

接上文<持久化API(JPA)系列(七)实体关系映射(ORM)之单表映射@IdClass> 本文将介绍<联合主键:使用@EmbeddedId嵌入外部主键> 上文是通过@IdClass引用外部主键,联合主键也可以采用嵌入式主键替代. 1)新建外部主键类Family2.java 设置联合主键man和woman,因此外部主键也需要定义两个相同的变量,并添加一个以两个变量为输入的构造函数,同时添加getter/setter函数. 主键类必须满足: 1.必须实现Serializable接口,

Hibernate之实体关系映射

延迟加载与即时加载 例如Person类和Email类是一对多关系,如果设为即时加载,当加载Person时,会自动加载Email,如果设置为延迟加载,当第一次调用person.getEmails()时才会执行SQL语句加载Email 注解配置时,@OnetToMany(Fetch = FetchType.EAGER)为即时加载,Fetch = FetchType.LAZY为延迟加载 延迟加载和即时加载的策略适用于所有一对多.多对一.多对多等所有的实体关系 一般来说,延迟加载要比即时加载节省资源,但