通知 网站从因情语写改为晴雨,这个网站的模板也从calmlog_ex改为 whimurmur

HIBERNATE知识复习记录2-继承关系

2191人浏览 / 0人评论 / | 作者:因情语写  | 分类: hibernate  | 标签: 框架  /  hibernate

作者:因情语写

链接:https://www.qingyu.blue/article/293

声明:请尊重原作者的劳动,如需转载请注明出处


       发现了一篇和我类似的学习尚硅谷视频写的文章,内容如下,比我说的详细全面,可以看一下:

  [原创]java WEB学习笔记87:Hibernate学习之路-- -映射 继承关系(subclass , joined-subclass,union-subclass )

  抄一段对三种继承关系的解释:

  Java类中有继承关系,相应的在hibernate中,也有继承关系,子类反应到数据库中,就有多种实现形式了,子类和父类可以映射到同一张表中,子类也可以单独映射成一张表,但是用不同的标签实现,子类表和父类表的关系也不同。在映射文件中,有三个标签可以实现继承关系,分别是:subclass、joined-subclass、union-subclass,先陈述一下这三个标签的区别:

  subclass标签就是为子类嵌入父类的表中而设计的,而且要指定鉴别器,即用subclass一定要有判断类型的一个列,鉴别器指定记录属于哪个类型。但是subclass也提供了为子类设置单独的表的功能,即join标签。但是不管是内嵌表还是外部表,都得指定鉴别器。

  joined-subclass标签,提供的功能是只能为子类设定外部表,而且没有鉴别器,即子类一张表,父类一张表,子类以父类的主键为外键。父类对应的表中,没有判断类型的列。

  注意:这两个标签不能混用,若是只想要内嵌表,或者是既想要有内嵌表,又想要外部表,又或者是只想要外部表,那么只能使用subclass标签,需要注意的是,不论哪种方式,都要指定鉴别器,即父类对应的表中,一定有一个判断类型的列;而若是只想要外部表,又不想在父类对应的表中,要那个判断类型的列,那么只能使用join-subclass。

  union-subclass是将父类中的属性,添加到子类对应的表中去了。包括父类中的外键。union-class和前两个的区别就在于外键的不同,前两个标签,如果子类有单独对应的表的话,这个表的外键是其父类中的主键,而使用union-class,子类对应的表中的外键则和父类的外键是一样的,因为子类把父类继承的属性,也加到了自己的表当中。这样子类和父类的地位就相当了。不过这不是一种好的理解方式。如果是这样的话,那么就可以把父类设为抽象的类,并且在映射文件中,把父类设置为abstract="true",那么就不会再数据库中生成父类对应的表了,父类就只起到一个抽象的作用了。

  下面看一下简单的例子:

  subclass:

  Person类

package subclass;

public class Person {
    private Integer id;
    private String name;
    private int age;
    
    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 int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
}

  Student类

package subclass;

public class Student extends Person {
    private String school;

    public String getSchool() {
        return school;
    }

    public void setSchool(String school) {
        this.school = school;
    }
}

    Person.hbm.xml

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<!-- Generated 2017-7-23 15:37:20 by Hibernate Tools 3.5.0.Final -->
<hibernate-mapping package="subclass">
    <class name="Person" table="PERSON" discriminator-value="person"> <!-- Person对象对应的辨别者列的值 -->
        <id name="id" type="java.lang.Integer">
            <column name="ID" />
            <generator class="native" />
        </id>
    <!-- 辨别者列 -->
        <discriminator column="TYPE" type="string"></discriminator>
        <property name="name" type="java.lang.String">
            <column name="NAME" />
        </property>
        <property name="age" type="int">
            <column name="AGE" />
        </property>
        
        <subclass name="Student" discriminator-value="student"> <!-- Student对象对应的辨别者列的值 -->
            <property name="school" type="string" column="SCHOOL"></property>
        </subclass>
    </class>
</hibernate-mapping>

  会生成一张表,包括父类和子类的所有字段,用一个辨别者列来区分是父类还是子类的数据,当为父类数据时,相应的子类数据为null。

  HibernateTest类

package subclass;

import java.util.List;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.service.ServiceRegistryBuilder;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

public class HibernateTest {
    private SessionFactory sessionFactory;
    
    private Session session;
    
    private Transaction transaction;
    
    @Before
    public void init()
    {
        System.out.println("init");

        // 1. 创建一个SessionFactory对象
        sessionFactory = null;
        Configuration configuration = new Configuration().configure();
        
        // before 4.0
//        sessionFactory = configuration.buildSessionFactory();
        
        ServiceRegistry serviceRegistry = new ServiceRegistryBuilder().applySettings(configuration.getProperties())
                                                                      .buildServiceRegistry();
        sessionFactory = configuration.buildSessionFactory(serviceRegistry);
        // 2. 创建一个Session 对象
        session = sessionFactory.openSession();
        
        // 3. 开启事务
        transaction = session.beginTransaction();
        
    }
    
    @After
    public void destory()
    {
        System.out.println("destory");
        // 5. 提交事务
        transaction.commit();
        
        // 6. 关闭Session
        session.close();
        
        // 7. 关闭SesssionFactory
        sessionFactory.close();
    }
    
    /**
     * 缺点:
     * 1. 使用了辨别者列
     * 2. 子类独有的字段不能添加非空约束
     * 3. 若继承层次较深,数据表的字段也会较多
     */
    
    /*
     * 插入操作:
     * 1. 对于子类对象只需把记录插入到一张数据表中。
     * 2. 辨别者列有Hibernate自动维护。
     */
    @Test
    public void testSave()
    {
        Person person = new Person();
        person.setAge(11);
        person.setName("AA");
        
        session.save(person);
        
        Student stu = new Student();
        stu.setAge(22);
        stu.setName("BB");
        stu.setSchool("ATGUIGU");
        
        session.save(stu);
    }
    
    /*
     * 查询:
     * 1. 查询父类记录,只需要查询一张数据表
     * 2. 对于子类记录,也只需要查询一张数据表
     */
    @Test
    public void testQuery()
    {
        List<Person> persons = session.createQuery("FROM Person").list();
        System.out.println(persons.size());
        
        List<Student> stus = session.createQuery("FROM Student").list();
        System.out.println(stus.size());
    }
    
}

       joined-subclass:

  Person类

package joinedclass;

public class Person {
    private Integer id;
    private String name;
    private int age;
    
    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 int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
}

  Student类

package joinedclass;

public class Student extends Person {
    private String school;

    public String getSchool() {
        return school;
    }

    public void setSchool(String school) {
        this.school = school;
    }
}

  Person.hbm.xml

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<!-- Generated 2017-7-23 15:37:20 by Hibernate Tools 3.5.0.Final -->
<hibernate-mapping package="joinedclass">
    <class name="Person" table="PERSON">
        <id name="id" type="java.lang.Integer">
            <column name="ID" />
            <generator class="native" />
        </id>

        <property name="name" type="java.lang.String">
            <column name="NAME" />
        </property>
        <property name="age" type="int">
            <column name="AGE" />
        </property>
        
        <joined-subclass name="Student" table="STUDENT">
            <key column="STUDENT_ID"></key>  <!-- 和其父类一样的共有主键 -->
            <property name="school" type="string" column="SCHOOL"></property>
        </joined-subclass>
    </class>
</hibernate-mapping>

  使用joined-subclass会生成两张表, 并且对应的相关记录主键是相同的。  

  HibernateTest类

package joinedclass;

import java.util.List;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.service.ServiceRegistryBuilder;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

public class HibernateTest {
    private SessionFactory sessionFactory;
    
    private Session session;
    
    private Transaction transaction;
    
    @Before
    public void init()
    {
        System.out.println("init");

        // 1. 创建一个SessionFactory对象
        sessionFactory = null;
        Configuration configuration = new Configuration().configure();
        
        // before 4.0
//        sessionFactory = configuration.buildSessionFactory();
        
        ServiceRegistry serviceRegistry = new ServiceRegistryBuilder().applySettings(configuration.getProperties())
                                                                      .buildServiceRegistry();
        sessionFactory = configuration.buildSessionFactory(serviceRegistry);
        // 2. 创建一个Session 对象
        session = sessionFactory.openSession();
        
        // 3. 开启事务
        transaction = session.beginTransaction();
        
    }
    
    @After
    public void destory()
    {
        System.out.println("destory");
        // 5. 提交事务
        transaction.commit();
        
        // 6. 关闭Session
        session.close();
        
        // 7. 关闭SesssionFactory
        sessionFactory.close();
    }
    
    /**
     * 优点:
     * 1.不需要使用辨别者列,
     * 2.子列独有的字段能添加非空约束
     * 3.没有冗余的字段 
     */
    
    /*
     * 插入操作:
     * 1. 对于子类对象至少需要插入到两张表中
     */
    @Test
    public void testSave()
    {
        Person person = new Person();
        person.setAge(11);
        person.setName("CC");
        
        session.save(person);
        
        Student stu = new Student();
        stu.setAge(22);
        stu.setName("DD");
        stu.setSchool("1-ATGUIGU");
        
        session.save(stu);
    }
    
    /*
     * 查询:
     * 1. 查询父类记录,做一个左外连接查询
     * 2. 对于子类记录,做一个内连接查询
     */
    @Test
    public void testQuery()
    {
        List<Person> persons = session.createQuery("FROM Person").list();
        System.out.println(persons.size());
        
        List<Student> stus = session.createQuery("FROM Student").list();
        System.out.println(stus.size());
    }
    
}

  union-subclass:

  Person类

package unionclass;

public class Person {
    private Integer id;
    private String name;
    private int age;
    
    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 int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
}

  Student类

package unionclass;

public class Student extends Person {
    private String school;

    public String getSchool() {
        return school;
    }

    public void setSchool(String school) {
        this.school = school;
    }
}

  Person.hbm.xml

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<!-- Generated 2017-7-23 15:37:20 by Hibernate Tools 3.5.0.Final -->
<hibernate-mapping package="unionclass">
    <class name="Person" table="PERSON">
        <id name="id" type="java.lang.Integer">
            <column name="ID" />
            <generator class="hilo" />
        </id>

        <property name="name" type="java.lang.String">
            <column name="NAME" />
        </property>
        <property name="age" type="int">
            <column name="AGE" />
        </property>
        
        <union-subclass name="Student" table="STUDENT">
            <property name="school" column="SCHOOL" type="string"></property>
        </union-subclass>
    </class>
</hibernate-mapping>

  使用union-subclass会生成两张表,子表包含父表的所有信息,两张表没有关联,但子表会包含父表中的列,产生大量的重复列。

  HibernateTest类

package unionclass;

import java.util.List;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.service.ServiceRegistryBuilder;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

public class HibernateTest {
    private SessionFactory sessionFactory;
    
    private Session session;
    
    private Transaction transaction;
    
    @Before
    public void init()
    {
        System.out.println("init");

        // 1. 创建一个SessionFactory对象
        sessionFactory = null;
        Configuration configuration = new Configuration().configure();
        
        // before 4.0
//        sessionFactory = configuration.buildSessionFactory();
        
        ServiceRegistry serviceRegistry = new ServiceRegistryBuilder().applySettings(configuration.getProperties())
                                                                      .buildServiceRegistry();
        sessionFactory = configuration.buildSessionFactory(serviceRegistry);
        // 2. 创建一个Session 对象
        session = sessionFactory.openSession();
        
        // 3. 开启事务
        transaction = session.beginTransaction();
        
    }
    
    @After
    public void destory()
    {
        System.out.println("destory");
        // 5. 提交事务
        transaction.commit();
        
        // 6. 关闭Session
        session.close();
        
        // 7. 关闭SesssionFactory
        sessionFactory.close();
    }
    
    /**
     * 优点:
     * 1.不需要使用辨别者列,
     * 2.子列独有的字段能添加非空约束
     * 缺点:
     * 1. 存在冗余的字段
     * 2. 若更新父表的字段,更新的效率较低
     */
    
    /*
     * 插入操作:
     * 1. 对于子类对象需要插入到一张表中
     */
    @Test
    public void testSave()
    {
        Person person = new Person();
        person.setAge(11);
        person.setName("CC");
        
        session.save(person);
        
        Student stu = new Student();
        stu.setAge(22);
        stu.setName("DD");
        stu.setSchool("1-ATGUIGU");
        
        session.save(stu);
    }
    
    /*
     * 查询:
     * 1. 查询父类记录,需把父表和子表记录汇总到一起
     * 2. 对于子类记录,只需要查询一张数据表
     */
    @Test
    public void testQuery()
    {
        List<Person> persons = session.createQuery("FROM Person").list();
        System.out.println(persons.size());
        
        List<Student> stus = session.createQuery("FROM Student").list();
        System.out.println(stus.size());
    }
    
    @Test
    public void testUpdate()
    {
        String hql = "UPDATE Person p SET p.age = 20";
        session.createQuery(hql).executeUpdate();
    }
}

 


自己写的文章声明标题示例:


点赞(0) 打赏

全部评论

还没有评论!