hibernate inheritance mapping

In the domain model, in addition to association between class and class relations, and aggregation relationships, inheritance can also there is the next domain model shown, Deparment class and the Employee class as the one to many two-way association between relationship, Employee class There are two sub-categories: Skiller class and Sales category. Because Java allows only one class up to a direct parent class, Employee class, Skiller class and Sales category constitutes an inheritance tree.
hibernate inheritance mapping

In the category of object-oriented, there is the concept of multi-state, multi-state founded on the basis of inheritance. Simple to understand, polymorphism means that when a Java application variable is declared as Employee class, this variable can refer to it in fact has its own instance of the Employee class, Skiller instance of the class, it can refer to Sales class. Department class getEmps () method through the Hibernate API to retrieve from the database out of all the Employee objects. getEmps () method returns a collection of both the Employee class can contain its own instance, Skiller instance of the class, it can refer to Sales class. This query is called polymorphic queries. Database table does not exist between the inheritance, then how the inheritance relationship between domain model mapped to the relational data model as well? There are three ways hibernate mapping:

Inheritance tree root which corresponds to a table: on the relational data model, unconventional design, the table in the database by adding additional areas of the field of molecular type. In this way, relational data model can support inheritance and polymorphism.

Inheritance tree for each class corresponds to a table: in the relational data model used to represent the foreign key reference to inheritance relations.

Inheritance tree for each class corresponds to a specific table: relational data models do not support the domain model of inheritance and polymorphism.

1. Inheritance tree root which corresponds to a table employee (the entire inheritance tree a table):

employee of the table structure is as follows:

mysql> desc employee;
+------------+--------------+------+-----+-------- -+----------------+
| Field | Type | Null | Key | Default | Extra |
+------------+--------------+------+-----+-------- -+----------------+
| Id | int (11) | NO | PRI | NULL | auto_increment |
| Type | int (11) | NO | | NULL | |
| Name | varchar (255) | YES | UNI | NULL | |
| Depart_id | int (11) | YES | MUL | NULL | |
| Skill | varchar (255) | YES | | NULL | |
| SaleAmount | int (11) | YES | | NULL | |
+------------+--------------+------+-----+-------- -+----------------+

Department and Employee entity class please refer to my previous article, Skiller and Sales were as follows:

package com.reiyen.hibernate.domain;

public class Skiller extends Employee {

        private String skill;
//setter And the getter method
}
package com.reiyen.hibernate.domain;
public class Sales extends Employee {

        private int saleAmount;
//setter And the getter method
}

Employee.hbm.xml mapping file as follows:

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="com.reiyen.hibernate.domain">
        <class name="Employee" discriminator-value="0">
                <id name="id">
                        <generator />
                </id>
                <!--discriminator( The discriminator  ): The default type is specified as a string, here  int Type   -->
                <discriminator column="type" type="int"></discriminator>
                <property name="name" unique="true"/>
                <!-- name="department"  This name must match the properties of the Employee name in the  .  Sets the column = "depart_id", by default it will go to the  department The ID found in the  depart_id The value of the object if you want to find.  name The value of the object is equal to depart_id  , You can set the  property-ref="name" -->
                <many-to-one name="department" column="depart_id" />
                <subclass name="Skiller" discriminator-value="1">
                        <property name="skill" />
                </subclass>
                <subclass name="Sales" discriminator-value="2">
                        <property name="saleAmount" />
                </subclass>
        </class>
</hibernate-mapping>

Test class is as follows:

public class Many2One {

        public static void main(String[] args) {
                add();
                 query(1);//1
        }

        static void query(int empId) {
                Session s = null;
                Transaction tx = null;
                try {
                        s = HibernateUtil.getSession();
                        tx = s.beginTransaction();
                        Employee emp = (Employee) s.get(Employee.class, empId);//2
                        System.out.println(emp.getClass());
                        tx.commit();
                } finally {
                        if (s != null)
                                s.close();
                }
        }

        static void add() {
                Session s = null;
                Transaction tx = null;
                try {
                        Department depart = new Department();
                        depart.setName("department name");

                        Employee employee1 = new Employee();
                        employee1.setDepartment(depart); //1  Object model  : The establishment of two objects of the Association
                        employee1.setName("employee1 name1");

                        Skiller employee2 = new Skiller();
                        employee2.setDepartment(depart); //2  Object model  : The establishment of two objects of the Association
                        employee2.setName("employee2 name2");
                        employee2.setSkill("j2se");

                        Sales employee3 = new Sales();
                        employee3.setDepartment(depart); //2  Object model  : The establishment of two objects of the Association
                        employee3.setName("employee3 name3");
                        employee3.setSaleAmount(1000);

                        s = HibernateUtil.getSession();
                        tx = s.beginTransaction();
                        s.save(depart);
                        s.save(employee1);
                        s.save(employee2);
                        s.save(employee3);
                        tx.commit();
                } finally {
                        if (s != null)
                                s.close();
                }
        }
}

Program runs, the console print information as follows:

Hibernate: insert into Department (name) values (?)
Hibernate: insert into Employee (name, depart_id, type) values (?,?, 0)
Hibernate: insert into Employee (name, depart_id, skill, type) values (?,?,?, 1)
Hibernate: insert into Employee (name, depart_id, saleAmount, type) values (?,?,?, 2)
Hibernate: select employee0_.id as id1_0_, employee0_.name as name1_0_, employee0_.depart_id as depart4_1_0_, employee0_.skill as skill1_0_, employee0_.saleAmount as saleAmount1_0_, employee0_.type as type1_0_ from Employee employee0_ where employee0_.id =?
class com.reiyen.hibernate.domain.Employee

employee table in the record as follows:

mysql> select * from employee;
+----+------+-----------------+-----------+------- +------------+
| Id | type | name | depart_id | skill | saleAmount |
+----+------+-----------------+-----------+------- +------------+
| 1 | 0 | employee1 name1 | 1 | NULL | NULL |
| 2 | 1 | employee2 name2 | 1 | j2se | NULL |
| 3 | 2 | employee3 name3 | 1 | NULL | 1000 |
+----+------+-----------------+-----------+------- +------------+
3 rows in set (0.00 sec)

Will test the code comments as a statement with:

query(2);

To run the console printing class as follows: class com.reiyen.hibernate.domain.Skiller

Print or query as shown above has not changed.

Based on the above changes, then test the code into the statement of 2 comments:

Employee emp = (Employee) s.get(Skiller.class, empId);

To run, then the console to print query is:

Hibernate: select skiller0_.id as id1_0_, skiller0_.name as name1_0_, skiller0_.depart_id as depart4_1_0_, skiller0_.skill as skill1_0_ from Employee skiller0_ where skiller0_.id =? And skiller0_.type = 1
class com.reiyen.hibernate.domain.Skiller

Advantages: high efficiency operation

Disadvantages: If additional sub-categories to the employee, then you must modify the table structure, add a field to the table structure; while the corresponding subclass tables in the field can not have non-empty constraint.

2. Inheritance tree for each subclass corresponds to a table (joined-subclass), table structure as follows:

hibernate inheritance mapping

Modify Employee.hbm.xml mapping file as follows:

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="com.reiyen.hibernate.domain">
        <class name="Employee">
                <id name="id">
                        <generator />
                </id>
                <property name="name" unique="true"/>
                <!-- name="department"  This name must match the properties of the Employee name in the  .  Sets the column = "depart_id", by default it will go to the  department The ID found in the  depart_id The value of the object if you want to find.  name The value of the object is equal to depart_id  , You can set the  property-ref="name" -->
                <many-to-one name="department" column="depart_id" />
                <joined-subclass name="Skiller" table="skiller">
                 <key column="employee_id" />
                 <property name="skill" />
                </joined-subclass>
                <joined-subclass name="Sales" table="sales">
                 <key column="employee_id" />
                 <property name="saleAmount" column="sale_amount" />
                </joined-subclass>
        </class>
</hibernate-mapping>

Test class the same, but will test the code comments as a statement with:

query(2);

The console to print the information as follows:

Hibernate: insert into Department (name) values (?)
Hibernate: insert into Employee (name, depart_id) values (?,?)
Hibernate: insert into Employee (name, depart_id) values (?,?)
Hibernate: insert into skiller (skill, employee_id) values (?,?)
Hibernate: insert into Employee (name, depart_id) values (?,?)
Hibernate: insert into sales (sale_amount, employee_id) values (?,?)
Hibernate: select employee0_.id as id1_0_, employee0_.name as name1_0_, employee0_.depart_id as depart3_1_0_, employee0_1_.skill as skill2_0_, employee0_2_.sale_amount as sale2_3_0_, case when employee0_1_.employee_id is not null then 1 when employee0_2_.employee_id is not null then 2 when employee0_.id is not null then 0 end as clazz_0_ from Employee employee0_ left outer join skiller employee0_1_ on employee0_.id = employee0_1_.employee_id left outer join sales employee0_2_ on employee0_.id = employee0_2_.employee_id where employee0_.id =?
class com.reiyen.hibernate.domain.Skiller
The SQL statement from the print can be seen at this time, if saved is a subclass of Employee instance of an object, then, will have to keep records in two tables; if the query is sub-class object, then, is associated with a table for three query.

Based on the above changes, then test the code into the statement of 2 comments:

Employee emp = (Employee) s.get(Skiller.class, empId);

To run, then the console to print query is:

Hibernate: select skiller0_.employee_id as id1_0_, skiller0_1_.name as name1_0_, skiller0_1_.depart_id as depart3_1_0_, skiller0_.skill as skill2_0_ from skiller skiller0_ inner join Employee skiller0_1_ on skiller0_.employee_id = skiller0_1_.id where skiller0_.employee_id =?
At this point only two tables related inquiries.

Database table records as follows:

mysql> select * from employee;
+----+-----------------+-----------+
| Id | name | depart_id |
+----+-----------------+-----------+
| 1 | employee1 name1 | 1 |
| 2 | employee2 name2 | 1 |
| 3 | employee3 name3 | NULL |
+----+-----------------+-----------+
3 rows in set (0.00 sec)

mysql> select * from skiller;
+-------------+-------+
| Employee_id | skill |
+-------------+-------+
| 2 | j2se |
+-------------+-------+
1 row in set (0.00 sec)

mysql> select * from sales;
+-------------+-------------+
| Employee_id | sale_amount |
+-------------+-------------+
| 3 | 1000 |
+-------------+-------------+
1 row in set (0.00 sec)

3. Mixed with the assumption that many if Sales of property, and property Skiller little time to mixed use, "a class system in a form of succession" and "each sub-class of a table", table structure as follows:

hibernate inheritance mapping

Employee.hbm.xml mapping file as follows:

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="com.reiyen.hibernate.domain">
        <class name="Employee" discriminator-value="0">
                <id name="id">
                        <generator />
                </id>
                <discriminator column="type" type="int" />
                <property name="name" unique="true" />
                <!-- name="department"  This name must match the properties of the Employee name in the  .  Sets the column = "depart_id", by default it will go to the  department The ID found in the  depart_id The value of the object if you want to find.  name The value of the object is equal to depart_id  , You can set the  property-ref="name" -->
                <many-to-one name="department" column="depart_id" />
<!-- If discriminator-value is not explicitly given a value,  , The value of the name attribute is consistent  , That is, to  Skiller -->
<subclass name="Skiller" discriminator-value="1">
                        <property name="skill" />
                </subclass>
                <subclass name="Sales" discriminator-value="2">
                        <join table="sales">
                                <key column="employee_id" />
                                <property name="saleAmount" column="sale_amount" />
                        </join>
                </subclass>
        </class>
</hibernate-mapping>

At this time the same test class, but will test the code in the comment as a statement with:

query(2);

Then run the original basis of the above procedures, the console will print the following exception message:

Hibernate: insert into Department (name) values (?)
Hibernate: insert into Employee (name, depart_id, type) values (?,?, 0)
Exception in thread "main" org.hibernate.exception.SQLGrammarException: could not insert: [com.reiyen.hibernate.domain.Employee]

Caused by: com.mysql.jdbc.exceptions.MySQLSyntaxErrorException: Unknown column 'type' in 'field list'

This is because I configured in the hibernate.cfg.xml configuration file has this:

<property name="hbm2ddl.auto">create</property>

So the program is running, it will delete the database in the employee table, sales table, while the employee table have skiller table foreign key association, it can not remove the employee table, so throw the above exception. At this point you then view the database tables, as follows:

mysql> select * from employee;
+----+-----------------+-----------+
| Id | name | depart_id |
+----+-----------------+-----------+
| 1 | employee1 name1 | 1 |
| 2 | employee2 name2 | 1 |
| 3 | employee3 name3 | 1 |
+----+-----------------+-----------+
3 rows in set (0.00 sec)

mysql> select * from skiller;
+-------------+-------+
| Employee_id | skill |
+-------------+-------+
| 2 | j2se |
+-------------+-------+
1 row in set (0.00 sec)

mysql> select * from sales;
Empty set (0.00 sec)

Therefore, the data must first manually remove the skiller table, and then run the program again:

If Employee.hbm.xml profile

<subclass name="Skiller" >

Not configured discriminator-value = "1", will throw the following exceptions:

java.lang.ExceptionInInitializerError

Caused by: org.hibernate.MappingException: Could not format discriminator value to SQL string

If the discriminator-value is not explicitly given value, then the value of the property with the name remain the same, that is, Skiller, so it throws above exception!

4. Inheritance tree for each concrete class corresponds to a table (union-subclass)

Table structure is as follows:

hibernate inheritance mapping

Employee.hbm.xml mapping file as follows:

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="com.itcast.hibernate.domain">
        <class name="Employee">
                <id name="id">
                        <generator />
                </id>
                <property name="name" unique="true" />
                <many-to-one name="department" column="depart_id" />
                <union-subclass name="Skiller" table="skiller">
                 <property name="skill" />
                </union-subclass>
                <union-subclass name="Sales" table="sales">
                 <property name="saleAmount" column="sale_amount" />
                </union-subclass>
        </class>
</hibernate-mapping>

Growth is no longer the primary key at this time are:

<generator />

If using the native form, then three will have the same id value, so that when the time under the Employee id query will be wrong. So if you configured the following native exception will be thrown (because the corresponding Employee entity class id is int, so this use hilo (high and low places) primary key generation method):

org.hibernate.MappingException: Cannot use identity column key generation with <union-subclass> mapping for: com.reiyen.hibernate.domain.Skiller

Run the test program, then print the information on the console as follows:

Hibernate: insert into Department (name) values (?)
Hibernate: insert into Employee (name, depart_id, id) values (?,?,?)
Hibernate: insert into skiller (name, depart_id, skill, id) values (?,?,?,?)
Hibernate: insert into sales (name, depart_id, sale_amount, id) values (?,?,?,?)
Hibernate: select employee0_.id as id1_0_, employee0_.name as name1_0_, employee0_.depart_id as depart3_1_0_, employee0_.skill as skill2_0_, employee0_.sale_amount as sale1_3_0_, employee0_.clazz_ as clazz_0_ from (select id, null as sale_amount, depart_id, null as skill, name, 0 as clazz_ from Employee union select id, null as sale_amount, depart_id, skill, name, 1 as clazz_ from skiller union select id, sale_amount, depart_id, null as skill, name, 2 as clazz_ from sales) employee0_ where employee0_.id =?
class com.reiyen.hibernate.domain.Skiller

Implementation of the query, the first to use a subquery in the sub-query using the union will be the result of all three tables into a table, and then in the synthesis of a query result set.

If the Employee is an abstract class, you do not want in the data table corresponding to the corresponding data table, you can set abstract = "true". As follows:

<class name="Employee" abstract="true" >

In addition, if the inheritance relationship with interfaces, you can treat it as an abstract class.

Comparison of three mapping and selection of three ways for the convenience of explanation for the label in order to [1] the entire inheritance tree a table; [2] corresponds to a table for each subclass (joined-subclass); [4] for each specific which corresponds to a table (union-subclass).
1, complexity:

[1] simple;
[2] table between the more and the foreign key constraint;

[4] contains duplicate field;
2, the query performance:

[1] and high efficiency;
[2] need to form connections or left outer join;

[Four] if the query need to check all parent subclass table;
3, Serviceability:

[1] only a modification of a table;
[2] If a class attribute changes only modify the class corresponding to the table;

[4] If changes need to modify the properties of the parent class of all sub-categories corresponding to the table;
In summary, the choice, you can refer to the following principles:
1, sub-class of property is not a very long time, priority [1], because of its best performance.
2, sub-class of property is very large, and not very demanding on the performance, the priority consideration [2]

分类:Java 时间:2010-04-08 人气:443
分享到:
blog comments powered by Disqus

相关文章

  • The Oracle architecture - database table space instances Introduction 2010-10-29

    First, the database Database suggests that it is a collection of data, but Oracle is the management of these data collection software system, it is an object-relational database management system. Second, the table space Oracle table space is related

  • Database table field relationship!!! 2011-06-12

    Database table field relationships! ! !

  • View all oracle database table's primary foreign key relationship 2010-11-01

    In daily data maintenance, often delete data, if the data where the table has a foreign key association, not set to cascade delete then you need to empty the child table related data. To find out all of the primary foreign key association is a more d

  • Database table structure 2010-06-03

    Database table structure and design of the original documents the relationship between entities can be one to one, one to many, many to many relationship. In general, they are one to one relationship: the one and only original documents corresponding

  • Vocabulary database table 2010-08-27

    1. Access method (access method): This step, from document storage and retrieval of records. 2. Alias (alias): another name for an attribute. In SQL, you can replace the table with the alias name. 3. Alternate keys (spare key, ER / relationship model

  • Database table design 2010-10-19

    1. Original documents and the relationship between entities is one to one, many, many to many relationship. In general, they are one to one relationship: the one and only original documents corresponds to a corresponding entity. In exceptional circum

  • Library management system database table structure (a) 2010-10-18

    I.1 Description This is done by using a database modeling tool PowerDesign export documentation, library management system is the ER model description. Figure library management system design requirements That is, at least three entities, each entity

  • DatabaseMetaData usage (transfer) method to obtain the database table structure 2010-03-10

    DatabaseMetaData usage (transfer) 2008-08-07 at 12:25 1. Be an instance of this object Connection con; con = DriverManager.getConnection (url, userName, password); DatabaseMetaData dbmd = con.getMetaData (); 2. Methods getTables usage <br /> prototy

  • UCHome brief description of the database table structure 2010-03-23

    UCHome brief description of the database table structure 1: uchome_member / / uchome Member List uid, username, password Serial number, user name, password 2: uchome_ad / / Advertising adid, available, title, pagetype, adcode, system Serial number, i

  • ORACLE database table partition 2010-05-06

    1.1 Partition Table PARTITION table ORACLE in the table if they are particularly large, you can use partition table to change its application performance. 1.1.1 Establishment of the partition table: A company's annual sales record of a huge, DBA reco

iOS 开发

Android 开发

Python 开发

JAVA 开发

开发语言

PHP 开发

Ruby 开发

搜索

前端开发

数据库

开发工具

开放平台

Javascript 开发

.NET 开发

云计算

服务器

Copyright (C) codeweblog.com, All Rights Reserved.

CodeWeblog.com 版权所有 黔ICP备15002463号-1

processed in 0.652 (s). 12 q(s)