联合主键的映射
1、类中的每个主键属性都对应到数据表中的每个主键的列
Hibernate要求具有联合主键的类首先要实现Serializable接口,其次要重写hashCode和equals方法,这两个方法可以使用Myeclipse帮助我们自动生成。重写这两个方法的原因在于Hibernate要根据数据库的联合主键来判断某两行记录是否是一样的,如果一样那么就认为是同一个对象,如果不一样,那么就认为是不同的对象。这反映到程序领域中就是根据hashCode与equals方法来判断某两个对象是否能够放到诸如set这样的集合当中。
2、举例:
import java.io.Serializable; public class Student implements Serializable { private String cardId; private String name; private int age; public String getCardId() { return cardId; } public void setCardId(String cardId) { this.cardId = cardId; } 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; } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((cardId == null) ? 0 : cardId.hashCode()); result = prime * result + ((name == null) ? 0 : name.hashCode()); return result; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; Student other = (Student) obj; if (cardId == null) { if (other.cardId != null) return false; } else if (!cardId.equals(other.cardId)) return false; if (name == null) { if (other.name != null) return false; } else if (!name.equals(other.name)) return false; return true; } }
对应的映射文件:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="com.cdtax.hibernate.Student" table="student">
<composite-id>
<key-property name="cardId" column="cardid" type="string"></key-property>
<key-property name="name" column="name" type="string"></key-property>
</composite-id>
<property name="age" column="age" type="integer"></property>
</class>
</hibernate-mapping>
这里使用了<composite-id>联合id,这就是联合主键映射使用的标签。
创建数据库表
create table student (cardid varchar(255) not null, name varchar(255) not null, age integer, primary key (cardid, name))
注意primary key,是两个字段
保存测试:
try { tx = session.beginTransaction(); Student st = new Student(); st.setName("zhangda"); st.setCardId("123456"); st.setAge(20); session.save(st); tx.commit(); }
Hibernate: insert into student (age, cardid, name) values (?, ?, ?)
如果再次执行:
Hibernate: insert into student (age, cardid, name) values (?, ?, ?)
org.hibernate.exception.ConstraintViolationException: Could not execute JDBC batch update
at org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:94)
at org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:66)
at org.hibernate.jdbc.AbstractBatcher.executeBatch(AbstractBatcher.java:275)
at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:266)
at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:167)
at org.hibernate.event.def.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:321)
at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:50)
at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:1028)
at org.hibernate.impl.SessionImpl.managedFlush(SessionImpl.java:366)
at org.hibernate.transaction.JDBCTransaction.commit(JDBCTransaction.java:137)
at com.cdtax.hibernate.HibernateTest.main(HibernateTest.java:42)
Caused by: java.sql.BatchUpdateException: Duplicate entry '123456-zhangda' for key 1
at com.mysql.jdbc.PreparedStatement.executeBatchSerially(PreparedStatement.java:1269)
at com.mysql.jdbc.PreparedStatement.executeBatch(PreparedStatement.java:955)
at org.hibernate.jdbc.BatchingBatcher.doExecuteBatch(BatchingBatcher.java:70)
at org.hibernate.jdbc.AbstractBatcher.executeBatch(AbstractBatcher.java:268)
... 8 more
出现了异常,因为主键重复了。
3、取数据
因为主键是两列了,就不能简单使用以前的get()或load()fang方法了,需要使用get或load的第二种方法
联合主键的实体类实现了serializable接口的原因在于使用get或load方法的时候需要先构建出来该实体的对象,并且将查询依据(联合主键)设置进去,然后作为get或load方法的第二个参数传进去即可。
try { tx = session.beginTransaction(); // Student st = new Student(); // st.setName("zhangda"); // st.setCardId("123456"); // st.setAge(20); // session.save(st); Student studentPrimaryKey = new Student(); studentPrimaryKey.setCardId("123456"); studentPrimaryKey.setName("zhangda"); Student student = (Student)session.get(Student.class, studentPrimaryKey); System.out.println(student.getAge()); System.out.println(studentPrimaryKey.getAge()); tx.commit(); }
Hibernate: select student0_.cardid as cardid0_0_, student0_.name as name0_0_, student0_.age as age0_0_ from student student0_ where student0_.cardid=? and student0_.name=?
20
20
对于studentPrimaryKey.getAge(),我们没有为studentPrimaryKey的age赋值,hibernate也为我们设置进去了。
4、实现联合主键的另一种方法,将主键所对应的属性提取出一个类(称之为主键类),并且主键类需要实现Serializable接口,重写equals方法与hashCode方法,原因与上面一样。
import java.io.Serializable; public class StudentPrimaryKey implements Serializable { private String cardId; private String name; public String getCardId() { return cardId; } public void setCardId(String cardId) { this.cardId = cardId; } public String getName() { return name; } public void setName(String name) { this.name = name; } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((cardId == null) ? 0 : cardId.hashCode()); result = prime * result + ((name == null) ? 0 : name.hashCode()); return result; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; StudentPrimaryKey other = (StudentPrimaryKey) obj; if (cardId == null) { if (other.cardId != null) return false; } else if (!cardId.equals(other.cardId)) return false; if (name == null) { if (other.name != null) return false; } else if (!name.equals(other.name)) return false; return true; } }
import java.io.Serializable; public class Student { private StudentPrimaryKey studentPrimaryKey; private int age; public int getAge() { return age; } public void setAge(int age) { this.age = age; } public StudentPrimaryKey getStudentPrimaryKey() { return studentPrimaryKey; } public void setStudentPrimaryKey(StudentPrimaryKey studentPrimaryKey) { this.studentPrimaryKey = studentPrimaryKey; } }
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="com.cdtax.hibernate.Student" table="student">
<composite-id name="studentPrimaryKey" class="com.cdtax.hibernate.StudentPrimaryKey">
<key-property name="cardId" column="cardid" type="string"></key-property>
<key-property name="name" column="name" type="string"></key-property>
</composite-id>
<property name="age" column="age" type="integer"></property>
</class>
</hibernate-mapping>
生成表:
drop table if exists student
create table student (cardid varchar(255) not null, name varchar(255) not null, age integer, primary key (cardid, name))
try { tx = session.beginTransaction(); Student st = new Student(); st.setAge(20); StudentPrimaryKey spk = new StudentPrimaryKey(); spk.setCardId("1234567"); spk.setName("zhangsan"); st.setStudentPrimaryKey(spk); session.save(st); tx.commit(); }
try { tx = session.beginTransaction(); StudentPrimaryKey spk = new StudentPrimaryKey(); spk.setCardId("1234567"); spk.setName("zhangsan"); Student student = (Student)session.get(Student.class, spk); System.out.println(student.getAge()); tx.commit(); }
20
5、采用component(组件)标签进行映射,这种方式适用于类的成员变量还有另一个类,如学生Student有一个Address属性
import java.io.Serializable; public class Student { private String id; private String name; private Address address; public String getId() { return id; } public void setId(String id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Address getAddress() { return address; } public void setAddress(Address address) { this.address = address; } }
public class Address { private String homeAddress; private String schoolAddress; public String getHomeAddress() { return homeAddress; } public void setHomeAddress(String homeAddress) { this.homeAddress = homeAddress; } public String getSchoolAddress() { return schoolAddress; } public void setSchoolAddress(String schoolAddress) { this.schoolAddress = schoolAddress; } }
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> <hibernate-mapping> <class name="com.cdtax.hibernate.Student" table="student"> <id name="id" column="id" type="string"> <generator class="uuid"></generator> </id> <property name="name" column="name" type="string"></property> <component name="address" class="com.cdtax.hibernate.Address"> <property name="homeAddress" type="string"></property> <property name="schoolAddress" type="string"></property> </component> </class> </hibernate-mapping>对于address的映射,采用了component标签
生成数据库表:
create table student (id varchar(255) not null, name varchar(255), homeAddress varchar(255), schoolAddress varchar(255), primary key (id))
注意homeAddress和schoolAddress在一张表中
测试:保存
try { tx = session.beginTransaction(); Student student = new Student(); Address address = new Address(); address.setHomeAddress("beijing"); address.setSchoolAddress("shanghai"); student.setName("zhangsan"); student.setAddress(address); session.save(student); tx.commit(); }
try { tx = session.beginTransaction(); Student student = (Student)session.get(Student.class, "402881c0424a0d3101424a0d32930001"); System.out.println(student.getName()); System.out.println(student.getAddress().getHomeAddress()); System.out.println(student.getAddress().getSchoolAddress()); tx.commit(); }
import java.util.HashSet;
import java.util.Set;
public class Student
{
private String id;
private String name;
private Set contacts = new HashSet();
public String getId()
{
return id;
}
public void setId(String id)
{
this.id = id;
}
public String getName()
{
return name;
}
public void setName(String name)
{
this.name = name;
}
public Set getContacts()
{
return contacts;
}
public void setContacts(Set contacts)
{
this.contacts = contacts;
}
}
public class Contact
{
private String student_id;
private String method;
private String address;
public String getStudent_id()
{
return student_id;
}
public void setStudent_id(String student_id)
{
this.student_id = student_id;
}
public String getMethod()
{
return method;
}
public void setMethod(String method)
{
this.method = method;
}
public String getAddress()
{
return address;
}
public void setAddress(String address)
{
this.address = address;
}
}
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="com.cdtax.hibernate.Student" table="student">
<id name="id" column="id" type="string">
<generator class="uuid"></generator>
</id>
<property name="name" column="name" type="string"></property>
<set name="contacts" table="contact">
<key column="student_id"></key>
<composite-element class="com.cdtax.hibernate.Contact">
<property name="method" type="string"></property>
<property name="address" type="string"></property>
</composite-element>
</set>
</class>
</hibernate-mapping>
Set是一对多关系,使用以前的配置要使用one-to-many,并且要使用两个配置文件,建议使用,关系看着明晰,这里使用composite-element标签,组合元素
create table contact (student_id varchar(255) not null, method varchar(255), address varchar(255))
create table student (id varchar(255) not null, name varchar(255), primary key (id))
alter table contact add index FK38B7242045A3E36D (student_id), add constraint FK38B7242045A3E36D foreign key (student_id) references student (id)
插入数据
try { tx = session.beginTransaction(); Student student = new Student(); student.setName("zhangsan11"); Contact contact1 = new Contact(); contact1.setMethod("telphone"); contact1.setAddress("123456"); Contact contact2 = new Contact(); contact2.setMethod("address"); contact2.setAddress("beijing"); student.getContacts().add(contact1); student.getContacts().add(contact2); session.save(student); tx.commit(); }
Hibernate: insert into student (name, id) values (?, ?)
Hibernate: insert into contact (student_id, method, address) values (?, ?, ?)
Hibernate: insert into contact (student_id, method, address) values (?, ?, ?)
7、继承映射
(1)、每个子类一张表
public class Person { private String id; private String name; public String getId() { return id; } public void setId(String id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } }
public class Student extends Person { private String cardId; public String getCardId() { return cardId; } public void setCardId(String cardId) { this.cardId = cardId; } }
public class Teacher extends Person { private int salary; public int getSalary() { return salary; } public void setSalary(int salary) { this.salary = salary; } }
映射文件:
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> <hibernate-mapping> <class name="com.cdtax.hibernate.Student" table="student"> <id name="id" column="id" type="string"> <generator class="uuid"></generator> </id> <property name="name" column="name" type="string"></property> <property name="cardId" column="cardid" type="string"></property> </class> </hibernate-mapping>
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> <hibernate-mapping> <class name="com.cdtax.hibernate.Teacher" table="teacher"> <id name="id" column="id" type="string"> <generator class="uuid"></generator> </id> <property name="name" column="name" type="string"></property> <property name="salary" column="salary" type="int"></property> </class> </hibernate-mapping>
create table student (id varchar(255) not null, name varchar(255), cardid varchar(255), primary key (id))
create table teacher (id varchar(255) not null, name varchar(255), salary integer, primary key (id))
保存测试:
try { tx = session.beginTransaction(); Student student = new Student(); student.setCardId("123456"); student.setName("zhangsan"); Teacher teacher = new Teacher(); teacher.setSalary(100); teacher.setName("lisi"); session.save(student); session.save(teacher); tx.commit(); }查询:
try
{
tx = session.beginTransaction();
Query query = session.createQuery("from com.cdtax.hibernate.Person");//多态查询,父类,会查询所有子类
Iterator iter = query.iterate();
while(iter.hasNext())
{
Person p = (Person)iter.next();
System.out.println(p.getName());
}
tx.commit();
}
我们使用HQL进行查询,查询使用的是父类,这是多态查询,hibernate会查询所有继承了Person的子类,这里要注意写上类的全称,就是加上包的名字,如果不加,这样:
from Person,就会出现异常:因为没有Person的映射文件,在没有映射文件的时候,就要写类的全称。
org.hibernate.hql.ast.QuerySyntaxException: Person is not mapped [from Person]
at org.hibernate.hql.ast.util.SessionFactoryHelper.requireClassPersister(SessionFactoryHelper.java:181)
at org.hibernate.hql.ast.tree.FromElementFactory.addFromElement(FromElementFactory.java:110)
at org.hibernate.hql.ast.tree.FromClause.addFromElement(FromClause.java:94)
at org.hibernate.hql.ast.HqlSqlWalker.createFromElement(HqlSqlWalker.java:316)
at org.hibernate.hql.antlr.HqlSqlBaseWalker.fromElement(HqlSqlBaseWalker.java:3228)
at org.hibernate.hql.antlr.HqlSqlBaseWalker.fromElementList(HqlSqlBaseWalker.java:3112)
at org.hibernate.hql.antlr.HqlSqlBaseWalker.fromClause(HqlSqlBaseWalker.java:720)
at org.hibernate.hql.antlr.HqlSqlBaseWalker.query(HqlSqlBaseWalker.java:571)
at org.hibernate.hql.antlr.HqlSqlBaseWalker.selectStatement(HqlSqlBaseWalker.java:288)
at org.hibernate.hql.antlr.HqlSqlBaseWalker.statement(HqlSqlBaseWalker.java:231)
at org.hibernate.hql.ast.QueryTranslatorImpl.analyze(QueryTranslatorImpl.java:254)
at org.hibernate.hql.ast.QueryTranslatorImpl.doCompile(QueryTranslatorImpl.java:185)
at org.hibernate.hql.ast.QueryTranslatorImpl.compile(QueryTranslatorImpl.java:136)
at org.hibernate.engine.query.HQLQueryPlan.<init>(HQLQueryPlan.java:101)
at org.hibernate.engine.query.HQLQueryPlan.<init>(HQLQueryPlan.java:80)
at org.hibernate.engine.query.QueryPlanCache.getHQLQueryPlan(QueryPlanCache.java:94)
at org.hibernate.impl.AbstractSessionImpl.getHQLQueryPlan(AbstractSessionImpl.java:156)
at org.hibernate.impl.AbstractSessionImpl.createQuery(AbstractSessionImpl.java:135)
at org.hibernate.impl.SessionImpl.createQuery(SessionImpl.java:1651)
at com.cdtax.hibernate.HibernateTest.main(HibernateTest.java:49)
执行的结果:
Hibernate: select teacher0_.id as col_0_0_ from teacher teacher0_
Hibernate: select student0_.id as col_0_0_ from student student0_
Hibernate: select teacher0_.id as id1_0_, teacher0_.name as name1_0_, teacher0_.salary as salary1_0_ from teacher teacher0_ where teacher0_.id=?
lisi
Hibernate: select student0_.id as id0_0_, student0_.name as name0_0_, student0_.cardid as cardid0_0_ from student student0_ where student0_.id=?
zhangsan
打印出类的名称:
try { tx = session.beginTransaction(); Query query = session.createQuery("from java.lang.Object");//多态查询,父类,会查询所有子类 Iterator iter = query.iterate(); while(iter.hasNext()) { Person p = (Person)iter.next(); System.out.println(p.getClass().getName()); System.out.println(p.getName()); } tx.commit(); }结果:
Hibernate: select teacher0_.id as col_0_0_ from teacher teacher0_
Hibernate: select student0_.id as col_0_0_ from student student0_
com.cdtax.hibernate.Teacher_$$_javassist_0
Hibernate: select teacher0_.id as id1_0_, teacher0_.name as name1_0_, teacher0_.salary as salary1_0_ from teacher teacher0_ where teacher0_.id=?
lisi
com.cdtax.hibernate.Student_$$_javassist_1
Hibernate: select student0_.id as id0_0_, student0_.name as name0_0_, student0_.cardid as cardid0_0_ from student student0_ where student0_.id=?
zhangsan
可以使用一种极端的情况,HQL中查询Object:from java.lang.Object
结果:
Hibernate: select teacher0_.id as col_0_0_ from teacher teacher0_
Hibernate: select student0_.id as col_0_0_ from student student0_
com.cdtax.hibernate.Teacher_$$_javassist_0
com.cdtax.hibernate.Student_$$_javassist_1
一样查询出来了。
也可以使用接口来查询,所有实现了给定接口的类都会被查询出来。
(2)、一张表存储继承体系中所有类的信息(数据库表实际上是继承体系中所有类的属性的并集所构成的字段)
需要在HBM文件中增加如下一行:
<discriminator column="personType" type="string"></discriminator>
这样在生成的表中增加这样一列。这一列来表明这一行是Teacher或Student。
最后表的结构:
Person、Student、Teacher类如上不变
对应的映射文件:
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> <hibernate-mapping> <class name="com.cdtax.hibernate.Person" table="person"> <id name="id" column="id" type="string"> <generator class="uuid"></generator> </id> <discriminator column="personType" type="string"></discriminator> <property name="name" column="name" type="string"></property> <subclass name="com.cdtax.hibernate.Student" discriminator-value="student"> <property name="cardId" type="string"></property> </subclass> <subclass name="com.cdtax.hibernate.Teacher" discriminator-value="teacher"> <property name="salary" type="int"></property> </subclass> </class> </hibernate-mapping>discriminator标签用来标明增加一列来对每一行是学生还是教师进行区别。
然后要增加subclass标签,来指明Person类的子类,有多少子类就要配置几个。subclasss标签的要有一个discriminator-value属性,其值标明这个子类在数据库表中discriminator字段的值。
产生的数据表:
create table person (id varchar(255) not null, personType varchar(255) not null, name varchar(255), cardId varchar(255), salary integer, primary key (id))
保存数据:
try { tx = session.beginTransaction(); Student student = new Student(); student.setCardId("123456"); student.setName("zhzdsafds"); Teacher teacher = new Teacher(); teacher.setSalary(100); teacher.setName("lisi"); session.save(student); session.save(teacher); tx.commit(); }
Hibernate: insert into person (name, cardId, personType, id) values (?, ?, 'student', ?)
Hibernate: insert into person (name, salary, personType, id) values (?, ?, 'teacher', ?)
数据库数据:
id | personType | name | cardId | salary |
---|---|---|---|---|
402881c0424b61fd01424b61fdec0001 | student | zhzdsafds | 123456 | null |
402881c0424b61fd01424b61fdfc0002 | teacher | lisi | null | 100 |
try { tx = session.beginTransaction(); // Student student = new Student(); // student.setCardId("123456"); // student.setName("zhzdsafds"); // // Teacher teacher = new Teacher(); // teacher.setSalary(100); // teacher.setName("lisi"); // // session.save(student); // session.save(teacher); Query query = session.createQuery("from Person"); Iterator iter = query.iterate(); while (iter.hasNext()) { Person p = (Person) iter.next(); System.out.println(p.getClass().getName()); System.out.println(p.getName()); } tx.commit(); }
Hibernate: select person0_.id as col_0_0_ from person person0_
com.cdtax.hibernate.Person_$$_javassist_0
Hibernate: select person0_.id as id0_0_, person0_.name as name0_0_, person0_.cardId as cardId0_0_, person0_.salary as salary0_0_, person0_.personType as personType0_0_ from person person0_ where person0_.id=?
zhzdsafds
com.cdtax.hibernate.Person_$$_javassist_0
Hibernate: select person0_.id as id0_0_, person0_.name as name0_0_, person0_.cardId as cardId0_0_, person0_.salary as salary0_0_, person0_.personType as personType0_0_ from person person0_ where person0_.id=?
lisi
上面的查询统一转换为Person,不能取得特定子类的特有信息,所以修改一下:
try { tx = session.beginTransaction(); // Student student = new Student(); // student.setCardId("123456"); // student.setName("zhzdsafds"); // // Teacher teacher = new Teacher(); // teacher.setSalary(100); // teacher.setName("lisi"); // // session.save(student); // session.save(teacher); Query query = session.createQuery("from Person"); Iterator iter = query.iterate(); // while (iter.hasNext()) // { // Person p = (Person) iter.next(); // // System.out.println(p.getClass().getName()); // System.out.println(p.getName()); // Object object = iter.next(); // // if(object instanceof Student) // { // System.out.println(((Student)object).getCardId()); // } // } List list = query.list(); for(int i = 0;i < list.size();i++) { if(list.get(i) instanceof Student) { System.out.println(((Student)list.get(i)).getCardId()); } if(list.get(i) instanceof Teacher) { System.out.println(((Teacher)list.get(i)).getSalary()); } } tx.commit(); }
Hibernate: select person0_.id as col_0_0_ from person person0_
Hibernate: select person0_.id as id0_, person0_.name as name0_, person0_.cardId as cardId0_, person0_.salary as salary0_, person0_.personType as personType0_ from person person0_
123456
100
这里将Iterator查询方式屏蔽了是因为使用Iterator延迟加载:
try { tx = session.beginTransaction(); Query query = session.createQuery("from Person"); Iterator iter = query.iterate(); while (iter.hasNext()) { Object object = iter.next(); if(object instanceof Student) { System.out.println(((Student)object).getCardId()); } if(object instanceof Teacher) { System.out.println(((Teacher)object).getSalary()); } }
Hibernate: select person0_.id as col_0_0_ from person person0_
(3)公共信息放在父类表中,独有信息放在子类表中,每个子类对应一张表。
类不变
配置信息:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="com.cdtax.hibernate.Person" table="person">
<id name="id" column="id" type="string">
<generator class="uuid"></generator>
</id>
<property name="name" column="name" type="string"></property>
<joined-subclass name="com.cdtax.hibernate.Student" table="student">
<key column="id"></key>
<property name="cardId" type="string"></property>
</joined-subclass>
<joined-subclass name="com.cdtax.hibernate.Teacher" table="teacher">
<key column="id"></key>
<property name="salary" type="int"></property>
</joined-subclass>
</class>
</hibernate-mapping>
这里使用了joined-subclass,因为是多张表,所以操作时要进行表的连接操作才能完成,所以叫做joined-subclass,对于joined-subclass,需要有key子标签,指明表的外键关联,然后是子类独有的属性映射。
生成的数据库表:
create table person (id varchar(255) not null, name varchar(255), primary key (id))
create table student (id varchar(255) not null, cardId varchar(255), primary key (id))
create table teacher (id varchar(255) not null, salary integer, primary key (id))
alter table student add index FK8FFE823B61610A7D (id), add constraint FK8FFE823B61610A7D foreign key (id) references person (id)
alter table teacher add index FKAA31CBE261610A7D (id), add constraint FKAA31CBE261610A7D foreign key (id) references person (id)
保存数据:
try { tx = session.beginTransaction(); Student student = new Student(); student.setCardId("123456"); student.setName("zhzdsafds"); Teacher teacher = new Teacher(); teacher.setSalary(100); teacher.setName("lisi"); session.save(student); session.save(teacher); tx.commit(); }
Hibernate: insert into person (name, id) values (?, ?)
Hibernate: insert into student (cardId, id) values (?, ?)
Hibernate: insert into person (name, id) values (?, ?)
Hibernate: insert into teacher (salary, id) values (?, ?)
查询:
try { tx = session.beginTransaction(); // // Student student = new Student(); // student.setCardId("123456"); // student.setName("zhzdsafds"); // // Teacher teacher = new Teacher(); // teacher.setSalary(100); // teacher.setName("lisi"); // // session.save(student); // session.save(teacher); Query query = session.createQuery("from Person"); Iterator iter = query.iterate(); while(iter.hasNext()) { Person p = (Person)iter.next(); System.out.println(p.getName()); } tx.commit(); }
Hibernate: select person0_.id as col_0_0_ from person person0_
Hibernate: select person0_.id as id0_0_, person0_.name as name0_0_, person0_1_.cardId as cardId1_0_, person0_2_.salary as salary2_0_, case when person0_1_.id is not null then 1 when person0_2_.id is not null then 2 when person0_.id is not null then 0 end as clazz_0_ from person person0_ left outer join student person0_1_ on person0_.id=person0_1_.id left outer join teacher person0_2_ on person0_.id=person0_2_.id where person0_.id=?
zhzdsafds
Hibernate: select person0_.id as id0_0_, person0_.name as name0_0_, person0_1_.cardId as cardId1_0_, person0_2_.salary as salary2_0_, case when person0_1_.id is not null then 1 when person0_2_.id is not null then 2 when person0_.id is not null then 0 end as clazz_0_ from person person0_ left outer join student person0_1_ on person0_.id=person0_1_.id left outer join teacher person0_2_ on person0_.id=person0_2_.id where person0_.id=?
lisi
Hibernate: select person0_.id as id0_0_, person0_.name as name0_0_, person0_1_.cardId as cardId1_0_, person0_2_.salary as salary2_0_, case when person0_1_.id is not null then 1 when person0_2_.id is not null then 2 when person0_.id is not null then 0 end as clazz_0_ from person person0_ left outer join student person0_1_ on person0_.id=person0_1_.id left outer join teacher person0_2_ on person0_.id=person0_2_.id where person0_.id=?
zhzdsafds
Hibernate: select person0_.id as id0_0_, person0_.name as name0_0_, person0_1_.cardId as cardId1_0_, person0_2_.salary as salary2_0_, case when person0_1_.id is not null then 1 when person0_2_.id is not null then 2 when person0_.id is not null then 0 end as clazz_0_ from person person0_ left outer join student person0_1_ on person0_.id=person0_1_.id left outer join teacher person0_2_ on person0_.id=person0_2_.id where person0_.id=?
lisi