本次学习是在hibernate3环境下,没有结合struts2和Spring,测试是直接用java类的main方法在控制台输出。java
oracle数据库(其余数据库也能够,都是类似的)、hibernate3.jar等架包。sql
a.建立工程,引入hibernate和驱动开发包数据库
b.在src下添加hibernate.cfg.xml主配置服务器
c.根据数据表建立Entity实体类session
d.编写实体类和数据表的映射文件xxx.hbm.xmloracle
e.利用Hibernate API实现增删改查操做app
1、在src下添加hibernate.cfg.xml主配置,配置内容以下:函数
<!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="hibernate.connection.driver_class">oracle.jdbc.driver.OracleDriver</property> <!-- 链接数据库的地址--> <property name="hibernate.connection.url">jdbc:oracle:thin:@localhost :1521:orcl</property> <!-- 链接数据库的用户名--> <property name="hibernate.connection.username">hr</property> <!-- 链接数据库的密码--> <property name="hibernate.connection.password">orcl</property>
<property name="hibernate.connection.pool.size">20 </property> <property name="hibernate.show_sql">true </property> <property name="jdbc.fetch_size">50 </property> <property name="jdbc.batch_size">23 </property> <property name="jdbc.use_scrollable_resultset">false </property> <property name="Connection.useUnicode">true </property>
<!--hibernate.dialect 只是Hibernate使用的数据库方言,就是要用Hibernate链接那种类型的数据库服务器。--> <property name="hibernate.dialect">org.hibernate.dialect.OracleDialect </property>
<!--指定映射文件--> <mapping resource="com/neusoft/test/entity/User.hbm.xml" /> </session-factory> </hibernate-configuration> |
2、根据数据表建立Entity实体类,com/neusoft/test/entity/User.java,代码以下:
package com.neusoft.test.entity;
public class User { private int id; private String userName; private String password; public int getId() { return id; } public void setId(int id) { this.id = id; } public String getuserName() { return userName; } public void setuserName(String userName) { this.userName = userName; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } } |
须要注意的是实体类定义的字段最好与数据库(oracle不区分大小写)中的字段一致,若是不一致会麻烦一些,且配置容易出错。
3、编写实体类和数据表的映射文件com/neusoft/test/entity/User.hbm.xml,该配置文件存放的位置不是固定的,可是要与hibernate.cfg.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">
<hibernate-mapping package="com.neusoft.test.entity"> <class name="User" table="demo_user_t"> <id name="id"> <column name="id"></column> <!--主键生成策略,sequence是oracle自增策略,别的数据库要使用各自适用的 --> <generator /> </id> <property name="userName" column="userName"/> <property name="password" /> </class> </hibernate-mapping> |
name属性对应的是实体类中的属性字段,必须是一致的(区分大小写),若是该字段与数据库表中的字段是一致的,则不须要column;若是不一致,则须要column指明该字段是与数据库中哪一个字段是对应的。
数据库的表名为demo_user_t,含有字段id、userName、password。
4、测试,进行增删改查。新建一个test1.java。代码以下:
package com.neusoft.test.action;
import java.util.List; import org.hibernate.*; import com.neusoft.test.entity.User; import com.neusoft.test.utils.HibernateUtil;
public class test1 { /** * main函数,选择要执行的动做 */ public static void main(String args[]) { testFindAll(); }
/** * 测试添加操做 */ public static void testAdd() { Session session = HibernateUtil.getSession(); // 开启事务 Transaction tx = session.beginTransaction(); User user = new User(); user.setId(1);// user.setId()要根据主键生成策略而定 user.setuserName("1"); user.setPassword("1"); session.save(user);// 保存 tx.commit();// 提交事务 session.close();// 关闭session }
/** * 测试更新操做 */ public static void testUpdate() { Session session = HibernateUtil.getSession(); Transaction tx = session.beginTransaction(); // 按ID=1主键作条件查询 User user = (User) session.load(User.class, 1); user.setuserName("11"); user.setPassword("11"); session.update(user); tx.commit(); session.close(); }
/** * 测试删除操做 */ public static void testDelete() { Session session = HibernateUtil.getSession(); Transaction tx = session.beginTransaction(); User user = new User(); user.setId(1); // User user = (User)session.get(User.class, 1); session.delete(user);// 执行一个delete语句,按ID作条件删除 tx.commit(); session.close(); }
/** * 测试查询操做 */ @SuppressWarnings("unchecked") public static void testFindAll() { Session session = HibernateUtil.getSession(); // 利用Query执行一个HQL查询语句 Query query = session.createQuery("from User"); List<User> list = query.list(); for (User u : list) { System.out.println(u.getId() + " " + u.getuserName() + " " + u.getPassword()); } session.close(); }
public static void testFindById() { Session session = HibernateUtil.getSession(); // 利用Query执行一个HQL查询语句 User user = (User) session.get(User.class, 1); System.out.println(user.getId() + " " + user.getuserName() + " " + user.getPassword()); session.close(); }
@SuppressWarnings("unchecked") public static void testFindByName() { Session session = HibernateUtil.getSession(); // 利用Query执行一个HQL查询语句 Query query = session.createQuery("from User where userName='1'"); List<User> list = query.list(); for (User u : list) { System.out.println(u.getId() + " " + u.getuserName() + " " + u.getPassword()); } session.close(); } } |
须要一个自定义的hibernate工具类HibernateUtil,代码以下:
package com.neusoft.test.utils;
import org.hibernate.Session; import org.hibernate.SessionFactory; import org.hibernate.cfg.Configuration;
public class HibernateUtil { // static SessionFactory sessionFactory= new Configuration().configure().buildSessionFactory(); static SessionFactory sessionFactory = new Configuration().configure( "hibernate.cfg.xml").buildSessionFactory(); static Session session = sessionFactory.openSession();
public static Session getSession() { return session; }
public static void closeSession() { // TODO Auto-generated method stub session.close(); } } |
首先要说明,有多个实例化类时,能够定义定义多个映射文件xxx.hbm.xml,而后在主配文件hibernate.cfg.xml中指定全部映射文件;也能够只定义一个映射文件,在映射文件中定义多个实例化类(class的定义)。
还有一点要注意,一个实例化类只能被映射文件定义一次。若是要对同一个表进行不一样功能的操做,则建多个与之对应的实例化类,而后在映射文件中定义不一样功能的实例化类。
每次作完一个小test要将数据库表内的数据清空,不然会对其余的测试产生影响,有可能报错。
1 、 映射集合属性
(1)List集合映射:
数据库表students
schools
映射文件中添加以下配置:
<class name="Student" table="students"> <id name="id"> <column name="id"></column> <generator /> </id> <property name="name" /> <property name="age" /> <list name="schools" table="schools"> <!-- 外键,对应该表的某个字段,默认参考上面定义的id --> <key column="student_id" not-null="true"></key> <list-index column="list_order"></list-index> <element type="string" column="school_name"></element> </list> </class> |
实例化类以下:
package com.neusoft.test.entity;
import java.util.ArrayList; import java.util.List;
@SuppressWarnings("unchecked") public class Student { private int id; private String name; private int age; private List<String> schools = new ArrayList(); 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 List getSchools() { return schools; } public void setSchools(List schools) { this.schools = schools; } } |
测试类以下:
package com.neusoft.test.action;
import java.util.ArrayList; import java.util.List;
import org.hibernate.Query; import org.hibernate.Session; import org.hibernate.Transaction;
import com.neusoft.test.entity.Student; import com.neusoft.test.utils.HibernateUtil;
public class TestListStudent { @SuppressWarnings("unchecked") public static void main(String args[]) { Session session = HibernateUtil.getSession(); // 开启事务 Transaction tx = session.beginTransaction();
//添加 Student student = new Student(); student.setAge(12); student.setName("aqq"); List list = new ArrayList(); list.add("zqas"); list.add("zxxdfg"); list.add("zaadfg"); student.setSchools(list); session.save(student); tx.commit();// 提交事务
//查询 Query query = session.createQuery("from Student"); List<Student> list1 = query.list(); for (Student s : list1) { System.out.print("id:" + s.getId() + " 姓名:" + s.getName() + " 年龄:" + s.getAge() + " 上过的学校:"); List<String> list2 = s.getSchools(); for (String str : list2) { System.out.print(str + " "); } System.out.println(); } session.close();// 关闭session } } |
(2)Set集合映射
映射文件配置:
<class name="Student_set" table="students"> <id name="id"> <column name="id"></column> <generator /> </id> <property name="name" /> <property name="age" /> <set name="schools" table="schools"> <key column="student_id" not-null="true"></key> <element type="string" column="school_name"></element> </set> </class> |
实例化类以下:
package com.neusoft.test.entity;
import java.util.HashSet; import java.util.Set;
@SuppressWarnings("unchecked") public class Student_set { private int id; private String name; private int age; private Set<String> schools=new HashSet();
public Set<String> getSchools() { return schools; } public void setSchools(Set<String> schools) { this.schools = schools; } 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; } } |
测试类以下:
package com.neusoft.test.action;
import java.util.HashSet; import java.util.List; import java.util.Set;
import org.hibernate.Query; import org.hibernate.Session; import org.hibernate.Transaction;
import com.neusoft.test.entity.Student_set; import com.neusoft.test.utils.HibernateUtil;
public class TestSetStudent { @SuppressWarnings("unchecked") public static void main(String args[]) { Session session = HibernateUtil.getSession(); // 开启事务 Transaction tx = session.beginTransaction(); Student_set student = new Student_set(); student.setAge(20); student.setName("mm"); Set set = new HashSet(); set.add("zxc1"); set.add("zxc2"); student.setSchools(set); session.save(student); tx.commit();// 提交事务
Query query = session.createQuery("from Student_set"); List<Student_set> list = query.list(); for (Student_set s : list) { System.out.print("id:" + s.getId() + " 姓名:" + s.getName() + " 年龄:" + s.getAge() + " 上过的学校:"); Set<String> list2 = s.getSchools(); for (String str : list2) { System.out.print(str + " "); } System.out.println(); } session.close();// 关闭session } } |
(3)Map集合属性
新建数据库表scores
映射文件配置:
<class name="Student_map" table="students"> <id name="id"> <column name="id"></column> <generator /> </id> <property name="name" /> <property name="age" /> <map name="scores" table="scores"> <key column="student_id" not-null="true"></key> <map-key type="string" column="course"></map-key> <element type="integer" column="score"></element> </map> </class> |
实例化类:
package com.neusoft.test.entity;
import java.util.HashMap; import java.util.Map;
@SuppressWarnings("unchecked") public class Student_map { private int id; private String name; private int age; private Map scores = new HashMap();
public Map getScores() { return scores; } public void setScores(Map scores) { this.scores = scores; } 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; } } |
测试类:
package com.neusoft.test.action;
import java.util.HashMap; import java.util.List; import java.util.Map;
import org.hibernate.Query; import org.hibernate.Session; import org.hibernate.Transaction;
import com.neusoft.test.entity.Student_map; import com.neusoft.test.utils.HibernateUtil;
public class TestMapStudent { @SuppressWarnings("unchecked") public static void main(String args[]) { Session session = HibernateUtil.getSession(); // 开启事务 Transaction tx = session.beginTransaction(); Student_map student = new Student_map(); student.setAge(18); student.setName("yuiu"); Map map=new HashMap(); map.put("数学",85); map.put("语文",95); map.put("英语",89); student.setScores(map); session.save(student); tx.commit();// 提交事务
Query query = session.createQuery("from Student_map"); List<Student_map> list = query.list(); for (Student_map s : list) { System.out.print("id:" + s.getId() + " 姓名:" + s.getName() + " 年龄:" + s.getAge() + " 成绩:"); Map map1 = s.getScores();
// 第一种Map遍历 // Iterator it = map.entrySet().iterator(); // while (it.hasNext()) { // Map.Entry entry = (Map.Entry) it.next(); // Object key = entry.getKey(); // Object value = entry.getValue(); // System.out.print(key + ":" + value + " "); // }
// 第二种Map遍历 for (Object o : map1.keySet()) { System.out.print(o + ":" + map1.get(o) + " "); } // 第三种Map遍历 // for (Iterator i = map.keySet().iterator(); i.hasNext();) { // Object obj = i.next(); // System.out.print(obj +":" + map.get(obj) + " "); // } System.out.println(); } session.close();// 关闭session } } |
(4)映射组件属性
组件属性的意思是持久化类的属性既不是基本数据类型,也不是 String 字符串,而是某个组件变量,该组件属性的类型能够是自定义类。
显然没法直接用 property 映射 name 属性。为了映射组件属性, Hibernate 提供了 component 元素。每一个 component 元素映射一个组件属性,组件属性必须指定该属性的类型,component 元素中的 class 属性用于肯定组件的类型。
新建数据库表worker_table
映射文件配置:
<class name="Worker" table="worker_table"> <id name="id"> <column name="id"></column> <generator /> </id> <property name="age" /> <component name="name"> <property name="last" /> <property name="first" /> </component> </class> |
实例化类:
package com.neusoft.test.entity;
public class Worker { private int id; private int age; private Name name;
public Name getName() { return name; } public void setName(Name name) { this.name = name; } public int getId() { return id; } public void setId(int id) { this.id = id; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } } |
辅助类:
package com.neusoft.test.entity;
public class Name { private String last; private String first;
public String getLast() { return last; } public void setLast(String last) { this.last = last; } public String getFirst() { return first; } public void setFirst(String first) { this.first = first; } } |
测试类:
package com.neusoft.test.action;
import java.util.List;
import org.hibernate.Query; import org.hibernate.Session; import org.hibernate.Transaction;
import com.neusoft.test.entity.Name; import com.neusoft.test.entity.Worker; import com.neusoft.test.utils.HibernateUtil;
public class TestWorker { @SuppressWarnings("unchecked") public static void main(String args[]) { Session session = HibernateUtil.getSession(); // 开启事务 Transaction tx = session.beginTransaction(); Worker worker=new Worker(); Name name= new Name(); name.setLast("Cloze"); name.setFirst("Tom"); worker.setAge(25); worker.setName(name); session.save(worker); tx.commit();// 提交事务
Query query = session.createQuery("from Worker"); List<Worker> worker1 = query.list(); for (Worker w : worker1) { System.out.println("id:" + w.getId() + " 姓名:" + w.getName().getLast() + " " + w.getName().getFirst() + " 年龄:" + w.getAge()); } session.close();// 关闭session }
} |
(5)集合组件属性映射
集合除了存放 String 字符串之外,还能够存放组件类型。实际上,更多状况下,集合组件存放的都是组件类型。
新建数据库表company_table
映射文件配置:
<class name="Worker2" table="worker_table"> <id name="id"> <column name="id"></column> <generator /> </id> <property name="age" /> <component name="name"> <property name="last" /> <property name="first" /> </component> <list name="company" table="company_table"> <key column="id" not-null="true"/> <list-index column="list_order"/> <composite-element> <property name="name"></property> <property name="address"></property> </composite-element> </list> </class> |
实例化类:
package com.neusoft.test.entity;
import java.util.ArrayList; import java.util.List;
@SuppressWarnings("unchecked") public class Worker2 { private int id; private int age; private Name name; private List<Company> company = new ArrayList();
public List<Company> getCompany() { return company; } public void setCompany(List<Company> company) { this.company = company; } public Name getName() { return name; } public void setName(Name name) { this.name = name; } public int getId() { return id; } public void setId(int id) { this.id = id; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } } |
辅助类:
package com.neusoft.test.entity;
public class Company { private String name; private String address;
public String getName() { return name; } public void setName(String name) { this.name = name; } public String getAddress() { return address; } public void setAddress(String address) { this.address = address; } } |
测试类:
package com.neusoft.test.action;
import java.util.ArrayList; import java.util.List;
import org.hibernate.Query; import org.hibernate.Session; import org.hibernate.Transaction;
import com.neusoft.test.entity.Company; import com.neusoft.test.entity.Name; import com.neusoft.test.entity.Worker2; import com.neusoft.test.utils.HibernateUtil;
public class TestWorkerAndCompany { @SuppressWarnings("unchecked") public static void main(String args[]) { Session session = HibernateUtil.getSession(); // 开启事务 Transaction tx = session.beginTransaction(); List list = new ArrayList(); Worker2 worker=new Worker2(); worker.setAge(22); Name name= new Name(); name.setLast("Cloze"); name.setFirst("Tom"); worker.setName(name); Company company=new Company(); company.setName("aaa"); company.setAddress("aaaaaaaaaa"); list.add(company); Company company2=new Company(); company2.setName("bbbb"); company2.setAddress("bbbbbbbbbb"); list.add(company2); Company company3=new Company(); company3.setName("ccc"); company3.setAddress("ccccccc"); list.add(company3); worker.setCompany(list); session.save(worker); tx.commit();// 提交事务
Query query = session.createQuery("from Worker2"); List<Worker2> worker1 = query.list(); for (Worker2 w : worker1) { System.out.println("id:" + w.getId() + " 姓名:" + w.getName().getLast() + " " + w.getName().getFirst() + " 年龄:" + w.getAge() + " 工做过的公司:"); for(Company c :w.getCompany()){ System.out.println(c.getName()+" "+c.getAddress()); } System.out.println(); } session.close();// 关闭session } } |
2 、 关联关系映射
(1)单向 N-1
单向 N-1 关联只需从 N 的一端能够访问 1 的一端。模型:多我的(Person)对应同一个地址(Address)。只须要从人实体端找到相应的地址实体。无须关心从某个地址找到所有住户。
Person 端增长了 Address 属性,该属性不是一个普通的组件属性,而是引用了另一个持久化类,使用 many-to-one 元素映射 N-1 的持久化属性。
many-to-one 元素的做用相似于 property 元素,用于映射持久化类的某个属性,区别是改元素映射的是关联持久化类。与 property 元素相似,many-to-one 元素也必须拥有 name 属性,用于肯定该属性的名字,column 属性肯定外键列的列名.
新建数据库表person_table
address_table
映射配置:
<class name="Person" table="person_table"> <id name="personid"> <column name="personid"></column> <generator /> </id> <property name="name" /> <property name="age" /> <!-- 多对一,column是Address在该表中的外键列名 --> <many-to-one name="address" column="addressid"></many-to-one> </class> <class name="Address" table="address_table"> <id name="addressid"> <column name="addressid"></column> <generator /> </id> <property name="addressdetail" /> </class> |
实例化类1:
package com.neusoft.test.entity;
public class Person { private int personid; private String name; private int age; private Address address;
public int getPersonid() { return personid; } public void setPersonid(int personid) { this.personid = personid; } 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 Address getAddress() { return address; } public void setAddress(Address address) { this.address = address; } } |
实例化类2:
package com.neusoft.test.entity;
public class Address { private int addressid; private String addressdetail; private int personid;
public int getPersonid() { return personid; } public void setPersonid(int personid) { this.personid = personid; } public int getAddressid() { return addressid; } public void setAddressid(int addressid) { this.addressid = addressid; } public String getAddressdetail() { return addressdetail; } public void setAddressdetail(String addressdetail) { this.addressdetail = addressdetail; } } |
测试类:
package com.neusoft.test.action;
import java.util.List;
import org.hibernate.Query; import org.hibernate.Session; import org.hibernate.Transaction;
import com.neusoft.test.entity.Address; import com.neusoft.test.entity.Person; import com.neusoft.test.utils.HibernateUtil;
public class AddManyToOne { @SuppressWarnings("unchecked") public static void main(String args[]) { Session session = HibernateUtil.getSession(); // 开启事务 Transaction tx = session.beginTransaction(); Person person=new Person(); person.setName("aa"); person.setAge(22); Address address=new Address();
// 新建一个地址,而后添加给person address.setAddressdetail("wqesdasdasd"); person.setAddress(address); session.save(address);
// 直接添加已有的地址 // address.setAddressid(1); // person.setAddress(address);
session.save(person); tx.commit();// 提交事务
Query query = session.createQuery("from Person"); List<Person> list = query.list(); for (Person p : list) { System.out.println("id:" + p.getPersonid() + " 姓名:" + p.getName() + " 年龄:" + p.getAge() + " 地址:" + p.getAddress().getAddressdetail()); } session.close();// 关闭session } } |
(2)基于外键的单向 1-1
单向 1-1,POJO 与 N-1 没有丝毫区别。
基于外键的单向 1-1 映射文件:只须要在原有的 many-to-one 元素添加 unique=“true”,用以表示 N 的一端必须惟一便可,N的一端增长了惟一约束, 即成为单向 1-1。
(3)基于主键的单向 1-1
基于主键关联的持久化类不能拥有本身的主键生成器,它的主键由关联类负责生成。增长one-to-one元素来映射关联属性,必须为one-to-one元素增长constrained="true"属性,代表该类的主键由关联类生成。
映射配置:
<class name="Person2" table="person_table"> <id name="personid"> <column name="personid"></column> <!-- 基于主键关联时,主键生成策略是foreign,代表根据关联类生成主键 --> <generator> <!-- 关联持久化类的属性名 --> <param name="property">address</param> </generator> </id> <property name="name" /> <property name="age" /> <!-- 关联映射 基于主键 1-1 --> <one-to-one name="address" constrained="true"></one-to-one> </class> <class name="Address" table="address_table"> <id name="addressid"> <column name="addressid"></column> <generator /> </id> <property name="addressdetail" /> </class> |
实例化类:
package com.neusoft.test.entity;
public class Person2 { private int personid; private String name; private int age; private Address address;
public int getPersonid() { return personid; } public void setPersonid(int personid) { this.personid = personid; } 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 Address getAddress() { return address; } public void setAddress(Address address) { this.address = address; } } |
测试类:
package com.neusoft.test.action;
import java.util.List;
import org.hibernate.Query; import org.hibernate.Session; import org.hibernate.Transaction;
import com.neusoft.test.entity.Address; import com.neusoft.test.entity.Person2; import com.neusoft.test.utils.HibernateUtil;
public class AddOneToOne { @SuppressWarnings("unchecked") public static void main(String args[]) { Session session = HibernateUtil.getSession(); // 开启事务 Transaction tx = session.beginTransaction(); Person2 person=new Person2(); person.setName("aa"); person.setAge(22); Address address=new Address();
// 新建一个地址,而后添加给person address.setAddressdetail("wqesdasdasd"); person.setAddress(address); session.save(address);
session.save(person); tx.commit();// 提交事务
Query query = session.createQuery("from Person2"); List<Person2> list = query.list(); for (Person2 p : list) { System.out.println("id:" + p.getPersonid() + " 姓名:" + p.getName() + " 年龄:" + p.getAge() + " 地址:" + p.getAddress().getAddressdetail()); } session.close();// 关闭session } } |
(4)单向的 1-N
单向 1-N 关联的 POJO 须要使用集合属性。由于一的一端须要访问 N 的一端,而 N 的一端将以集合的形式表现。
不推荐使用单向的 1-N 关联:使用 1 的一端控制关联关系时,会额外多出 update 语句。插入数据时没法同时插入外键列,于是没法为外键列添加非空约束
映射配置:
<class name="Person3" table="person_table"> <id name="personid"> <column name="personid"></column> <generator /> </id> <property name="name" /> <property name="age" /> <!-- 单向1-N --> <set name="address" table="address_table"> <key column="personid"></key> <one-to-many /> </set> </class> <class name="Address" table="address_table"> <id name="addressid"> <column name="addressid"></column> <generator /> </id> <property name="addressdetail" /> </class> |
实例化类:
package com.neusoft.test.entity;
import java.util.Set;
public class Person3 { private int personid; private String name; private int age; private Set<Address> address;
public int getPersonid() { return personid; } public void setPersonid(int personid) { this.personid = personid; } 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 Set<Address> getAddress() { return address; } public void setAddress(Set<Address> address) { this.address = address; } } |
测试类:
package com.neusoft.test.action;
import java.util.HashSet; import java.util.List; import java.util.Set;
import org.hibernate.Query; import org.hibernate.Session; import org.hibernate.Transaction;
import com.neusoft.test.entity.Address; import com.neusoft.test.entity.Person3; import com.neusoft.test.utils.HibernateUtil;
public class TestOneToMany{ @SuppressWarnings("unchecked") public static void main(String args[]) { Session session = HibernateUtil.getSession(); // 开启事务 Transaction tx = session.beginTransaction(); Person3 person=new Person3(); person.setName("gfg"); person.setAge(35); Set set=new HashSet();
Address address=new Address(); address.setAddressdetail("zxcvzxc"); session.save(address); set.add(address);
Address address2=new Address(); address2.setAddressdetail("esdasd"); session.save(address2); set.add(address2);
Address address3=new Address(); address3.setAddressid(105); set.add(address3); person.setAddress(set); session.save(person); tx.commit();// 提交事务
Query query = session.createQuery("from Person3"); List<Person3> list = query.list(); for (Person3 p : list) { System.out.println("id:" + p.getPersonid() + " 姓名:" + p.getName() + " 年龄:" + p.getAge() + " 地址:" ); Set<Address> address1=p.getAddress(); for(Address a: address1){ System.out.println(a.getAddressdetail()); } } session.close();// 关闭session } } |
(5)单向的 N-N
与映射集合属性相似,必须为set,list等集合元素添加 key 子元素,用以映射关联的外键列。与集合映射不一样的是,创建 N-N 关联时,集合中的元素使用 many-to-many,而不是使用 element 子元素
N-N 的关联必须使用链接表。
新建数据库表person_address_table
映射配置:
<class name="Person4" table="person_table"> <id name="personid"> <column name="personid"></column> <generator /> </id> <property name="name" /> <property name="age" /> <!-- 单向N-N --> <!-- person_address_table为额外的表,表列必须含有key对应的字段和elt,其中elt是固定的 --> <set name="address" table="person_address_table"> <key column="personid" /> <many-to-many/> </set> </class> <class name="Address" table="address_table"> <id name="addressid"> <column name="addressid"></column> <generator /> </id> <property name="addressdetail" /> </class> |
实例化类:
package com.neusoft.test.entity;
import java.util.Set;
public class Person4 { private int personid; private String name; private int age; private int addressid; private Set<Address> address;
public int getAddressid() { return addressid; } public void setAddressid(int addressid) { this.addressid = addressid; } public int getPersonid() { return personid; } public void setPersonid(int personid) { this.personid = personid; } 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 Set<Address> getAddress() { return address; } public void setAddress(Set<Address> address) { this.address = address; } } |
测试类:
package com.neusoft.test.action;
import java.util.HashSet; import java.util.List; import java.util.Set;
import org.hibernate.Query; import org.hibernate.Session; import org.hibernate.Transaction;
import com.neusoft.test.entity.Address; import com.neusoft.test.entity.Person4; import com.neusoft.test.utils.HibernateUtil;
public class TestManyToMany { @SuppressWarnings("unchecked") public static void main(String args[]) {
Address address1=new Address(); address1.setAddressdetail("zxcvzxc");
Address address2=new Address(); address2.setAddressdetail("esdasd");
Set set_address=new HashSet(); set_address.add(address1); set_address.add(address2);
Person4 person1=new Person4(); person1.setName("gfg"); person1.setAge(35); person1.setAddress(set_address);
Person4 person2=new Person4(); person2.setName("gfg"); person2.setAge(35); person2.setAddress(set_address);
Session session = HibernateUtil.getSession(); // 开启事务 Transaction tx = session.beginTransaction();
session.save(address1); session.save(address2); session.save(person1); session.save(person2);
tx.commit();// 提交事务
Query query = session.createQuery("from Person4"); List<Person4> list = query.list(); for (Person4 p : list) { System.out.println("id:" + p.getPersonid() + " 姓名:" + p.getName() + " 年龄:" + p.getAge() + " 地址:" ); Set<Address> address=p.getAddress(); for(Address a: address){ System.out.println(a.getAddressdetail()); } } session.close();// 关闭session } } |
(6)双向 1-N和N-1
对于 1-N 的关联,Hibernate 推荐使用双向关联,并且不要让 1 的一端控制关联关系,而是使用 N 的一端控制关联关系。
双向 1-N 与 N-1 是彻底相同的。
1 的一端须要使用集合属性元素来映射关联关系。集合属性元素一样须要增长 key 元素,还须要使用 one-to-many 元素来映射关联属性。
N 的一端须要增长 many-to-one 元素来映射关联属性。
映射配置:
<hibernate-mapping package="com.neusoft.test.entity"> <class name="Person" table="person_table"> <id name="personid"> <column name="personid"></column> <generator /> </id> <property name="name" /> <property name="age" /> <!-- 双向1-N(N-1) cascade级联关系 inverse=true:将控制权抛出(给双向的另外一方) --> <set name="address" table="address_table" cascade="save-update" inverse="true"> <key column="personid"></key> <one-to-many/> </set> </class>
<class name="Address" table="address_table"> <id name="addressid"> <column name="addressid"></column> <generator /> </id> <property name="addressdetail" /> <many-to-one name="person" column="personid"></many-to-one> </class> </hibernate-mapping> |
注意:在上面的配置文件中,两个持久化类的配置文件都须要指定外键列的列名,此时不能够省略。由于不使用链接表的1-N关联的外键,而外键只保存在N一端的表中,若是两边指定的外键列名不一样,将致使关联映射出错。若是不指定外键列的列名,该列名由系统自动生成,而系统很难保存自动生成的两个列名相同。
实例化类1:
package com.neusoft.test.entity;
import java.util.Set;
public class Person { private int personid; private String name; private int age; private Set<Address> address;
public int getPersonid() { return personid; } public void setPersonid(int personid) { this.personid = personid; } 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 Set<Address> getAddress() { return address; } public void setAddress(Set<Address> address) { this.address = address; } } |
实例化类2:
package com.neusoft.test.entity;
public class Address { private int addressid; private String addressdetail; private Person person;
public Person getPerson() { return person; } public void setPerson(Person person) { this.person = person; } public int getAddressid() { return addressid; } public void setAddressid(int addressid) { this.addressid = addressid; } public String getAddressdetail() { return addressdetail; } public void setAddressdetail(String addressdetail) { this.addressdetail = addressdetail; } }
|
测试类:
package com.neusoft.test.action;
import java.util.HashSet; import java.util.List; import java.util.Set;
import org.hibernate.Query; import org.hibernate.Session; import org.hibernate.Transaction;
import com.neusoft.test.entity.Address; import com.neusoft.test.entity.Person; import com.neusoft.test.utils.HibernateUtil;
public class test { @SuppressWarnings("unchecked") public static void main(String args[]) { Person person = new Person(); person.setName("ghgh"); person.setAge(33);
Address address = new Address(); address.setAddressdetail("gdsfasg"); address.setPerson(person);
Address address2 = new Address(); address2.setAddressdetail("rtyrtyt"); address2.setPerson(person);
Set set = new HashSet(); set.add(address); set.add(address2); person.setAddress(set);
Session session = HibernateUtil.getSession(); // 开启事务 Transaction tx = session.beginTransaction(); session.save(person); session.save(address); session.save(address2); tx.commit();// 提交事务
//从1的一段query Query query = session.createQuery("from Person"); List<Person> list = query.list(); for (Person p : list) { System.out.println("id:" + p.getPersonid() + " 姓名:" + p.getName() + " 年龄:" + p.getAge() + " 地址:"); Set<Address> address1 = p.getAddress(); for (Address a : address1) { System.out.println(a.getAddressdetail()); } }
//从N的一段query Query query1 = session.createQuery("from Address"); List<Address> list1 = query1.list(); for (Address a : list1) { System.out .println(" 地址id:" + a.getAddressid() + " 详情:" + a.getAddressdetail() + " 人id:" + a.getPerson().getPersonid() + " 人名:" + a.getPerson().getName() + " 年龄:" + a.getPerson().getAge()); } session.close();// 关闭session } } |
(7)inverse
只有集合标记(set、map、list、array、bag)才有inverse属性。
在 Hibernate 中,inverse 指定了关联关系的方向。关联关系中 inverse = false 的为主动方,由主动方负责维护关联关系。
在没有设置 inverse=true 的状况下,父子两边都维护父子关系 。
在 1-N 关系中,将 many 方设为主控方(inverse = false) 将有助于性能改善(若是要国家元首记住全国人民的名字,不是太可能,但要让全国人民知道国家元首,就容易的多);若将 1 方设为主控方会额外多出 update 语句。插入数据时没法同时插入外键列,于是没法为外键列添加非空约束。
(8)cascade
只有关系标记才有cascade属性:many-to-one,one-to-one ,set(map, bag, idbag, list, array) + one-to-many(many-to-many)
级联指的是当主控方执行操做时,关联对象(被动方)是否同步执行同一操做。
pojo和它的关系属性的关系就是“主控方 -- 被动方”的关系,若是关系属性是一个set,那么被动方就是set中的每个元素。一个操做因级联cascade可能触发多个关联操做。前一个操做叫“主控操做”,后一个操做叫“关联操做”。
inverse 指的是关联关系的控制方向,而cascade指的是层级之间的连锁操做。
cascade属性的可选值:
all : 全部状况下均进行关联操做。
none:全部状况下均不进行关联操做。这是默认值。
save-update:在执行save/update/saveOrUpdate时进行关联操做。
delete:在执行delete时进行关联操做
delete-orphan:表示删除孤儿,delete-orphan在前者的基础上增长了一点,针对持久化对象,若是它和它所关联的对象的引用关系不存在了,则进行级联删除。
all-delete-orphan:包含all和delete-orphan的行为
(9)双向N-N关联
双向N-N关联须要两端都使用集合属性,两端都增长对集合属性的访问。双向N-N关联也必须使用链接表。
双向N-N的关联映射须要在两边增长集合元素,用于映射集合属性。集合属性应增长key子元素用以映射外键列,集合元素里还应增长many-to-many子元素关联实体类
注意:在双向N-N关联的两边都需定链接表的表名及外键列的列名。两个集合元素set的table元素的值必须指定,并且必须相同。set元素的两个子元素:key和many-to-many都必须指定column属性,其中,key和many-to-many分别指定本持久化类和关联类在链接表中的外键列名,因
此两边的key与many-to-many的column属性交叉相同。也就是说,一边的set元素的key的cloumn值为a,many-to-many的column为b;则另外一边的set元素的key的column值b,many-to-many的column值为a.
映射配置:
<class name="Person2" table="person_table"> <id name="personid"> <column name="personid"></column> <generator /> </id> <property name="name" /> <property name="age" /> <!-- 双向N-N --> <!-- person_address_table为额外的表,表列必须含有key对应的字段和elt,其中elt是固定的 --> <set name="address" table="person_address_table"> <key column="personid" /> <many-to-many column="addressid"/> </set> </class> <class name="Address2" table="address_table"> <id name="addressid"> <column name="addressid"></column> <generator /> </id> <property name="addressdetail" /> <!-- 双向N-N --> <!-- person_address_table为额外的表,表列必须含有key对应的字段和elt,其中elt是固定的 --> <set name="person" inverse="true" table="person_address_table"> <key column="addressid" /> <many-to-many column="personid"/> </set> </class> |
实例化类1:
package com.neusoft.test.entity;
import java.util.Set;
public class Person2 { private int personid; private String name; private int age; private Set<Address2> address;
public int getPersonid() { return personid; } public void setPersonid(int personid) { this.personid = personid; } 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 Set<Address2> getAddress() { return address; } public void setAddress(Set<Address2> address) { this.address = address; } }
|
实例化类2:
package com.neusoft.test.entity;
import java.util.Set;
public class Address2 { private int addressid; private String addressdetail; private Set<Person2> person;
public Set<Person2> getPerson() { return person; } public void setPerson(Set<Person2> person) { this.person = person; } public int getAddressid() { return addressid; } public void setAddressid(int addressid) { this.addressid = addressid; } public String getAddressdetail() { return addressdetail; } public void setAddressdetail(String addressdetail) { this.addressdetail = addressdetail; } } |
测试类:
package com.neusoft.test.action;
import java.util.HashSet; import java.util.List; import java.util.Set;
import org.hibernate.Query; import org.hibernate.Session; import org.hibernate.Transaction;
import com.neusoft.test.entity.Address2; import com.neusoft.test.entity.Person2; import com.neusoft.test.utils.HibernateUtil;
public class test2 { @SuppressWarnings("unchecked") public static void main(String args[]) {
Address2 address1 = new Address2(); address1.setAddressdetail("zxcvzxc");
Address2 address2 = new Address2(); address2.setAddressdetail("esdasd");
Person2 person1 = new Person2(); person1.setName("gfg"); person1.setAge(35);
Person2 person2 = new Person2(); person2.setName("gfg"); person2.setAge(35);
Set set_address = new HashSet(); set_address.add(address1); set_address.add(address2);
Set set_person = new HashSet(); set_person.add(person1); set_person.add(person2);
person1.setAddress(set_address); person2.setAddress(set_address); address1.setPerson(set_person); address2.setPerson(set_person);
Session session = HibernateUtil.getSession(); // 开启事务 Transaction tx = session.beginTransaction();
session.save(address1); session.save(address2); session.save(person1); session.save(person2);
tx.commit();// 提交事务
Query query = session.createQuery("from Person2"); List<Person2> list = query.list(); for (Person2 p : list) { System.out.println("id:" + p.getPersonid() + " 姓名:" + p.getName() + " 年龄:" + p.getAge() + " 地址:"); Set<Address2> address = p.getAddress(); for (Address2 a : address) { System.out.println(a.getAddressdetail()); } }
Query query1 = session.createQuery("from Address2"); List<Address2> list1 = query1.list(); for (Address2 a : list1) { System.out.println(" 地址id:" + a.getAddressid() + " 地址详细:" + a.getAddressdetail()); Set<Person2> person = a.getPerson(); for (Person2 p : person) { System.out.println(" 人id:" + p.getPersonid() + " 姓名:" + p.getName() + " 年龄:" + p.getAge()); } } session.close();// 关闭session } } |
(10)双向1-1关联
单向的1-1关联有三种映射策略:基于主键,基于外键和使用链接表。双向的1-1关联一样有这三种映射策略。
双向的1-1关联须要修改POJO类,让两边都增长对关联类的访问
基于外键的双向1-1关联
映射配置:
<!-- 双向1-1主实体 --> <class name="Person3" table="person_table"> <id name="personid"> <column name="personid"></column> <generator /> </id> <property name="name" /> <property name="age" /> <one-to-one name="address" cascade="all" property-ref="person"></one-to-one> </class> <!-- 双向1-1从属实体 --> <class name="Address3" table="address_table"> <id name="addressid"> <column name="addressid"></column> <generator /> </id> <property name="addressdetail" /> <!-- unique="true" 肯定是双向的1-1 --> <many-to-one name="person" column="personid" unique="true"></many-to-one> </class> |
实例化类1:
package com.neusoft.test.entity;
public class Person3 { private int personid; private String name; private int age; private Address3 address;
public int getPersonid() { return personid; } public void setPersonid(int personid) { this.personid = personid; } 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 Address3 getAddress() { return address; } public void setAddress(Address3 address) { this.address = address; } } |
实例化类2:
package com.neusoft.test.entity;
public class Address3 { private int addressid; private String addressdetail; private Person3 person;
public Person3 getPerson() { return person; } public void setPerson(Person3 person) { this.person = person; } public int getAddressid() { return addressid; } public void setAddressid(int addressid) { this.addressid = addressid; } public String getAddressdetail() { return addressdetail; } public void setAddressdetail(String addressdetail) { this.addressdetail = addressdetail; } } |
测试类:
package com.neusoft.test.action;
import java.util.List;
import org.hibernate.Query; import org.hibernate.Session; import org.hibernate.Transaction;
import com.neusoft.test.entity.Address3; import com.neusoft.test.entity.Person3; import com.neusoft.test.utils.HibernateUtil;
@SuppressWarnings("unchecked") public class test3 { public static void main(String args[]) { Session session = HibernateUtil.getSession(); // 开启事务 Transaction tx = session.beginTransaction(); Person3 person=new Person3(); person.setName("uytua"); person.setAge(28); Address3 address=new Address3();
// 新建一个地址,而后添加给person address.setAddressdetail("wqesdasdasd"); address.setPerson(person); person.setAddress(address);
session.save(address); session.save(person); tx.commit();// 提交事务
Query query = session.createQuery("from Person3"); List<Person3> list = query.list(); for (Person3 p : list) { System.out.println("id:" + p.getPersonid() + " 姓名:" + p.getName() + " 年龄:" + p.getAge() + " 地址:" + p.getAddress().getAddressdetail()); } session.close();// 关闭session } } |
基于主键的双向1-1关联
基于主键的映射策略:指一端的主键生成器使用foreign略,代表根据对方的主键来生成本身的主键,本身并不能独立生成主键。
任意一边均可以采用foreign主键生成器,代表根据对方主键生成本身的主键。
采用foreign主键生成器策略的一端增长one-to-one元素映射关联属性,其one-to-one属性还应增长constrained=“true”属性;另外一端增长one-to-one元素映射关联属性。
constrained(约束) :代表该类对应的表对应的数据库表,和被关联的对象所对应的数据库表之间,经过一个外键引用对主键进行约束。
映射配置:
<!-- 基于主键的双向1-1关联 --> <class name="Person4" table="person_table"> <id name="personid"> <column name="personid"></column> <generator /> </id> <property name="name" /> <property name="age" /> <one-to-one name="address" cascade="all"></one-to-one> </class> <class name="Address4" table="address_table"> <id name="addressid"> <column name="addressid"></column> <generator> <param name="property">person</param> </generator> </id> <property name="addressdetail" /> <one-to-one name="person" constrained="true"></one-to-one> </class> |
实例化类1:
package com.neusoft.test.entity;
public class Person4 { private int personid; private String name; private int age; private Address4 address;
public int getPersonid() { return personid; } public void setPersonid(int personid) { this.personid = personid; } 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 Address4 getAddress() { return address; } public void setAddress(Address4 address) { this.address = address; } } |
实例化类2:
package com.neusoft.test.entity;
public class Address4 { private int addressid; private String addressdetail; private Person4 person;
public Person4 getPerson() { return person; } public void setPerson(Person4 person) { this.person = person; } public int getAddressid() { return addressid; } public void setAddressid(int addressid) { this.addressid = addressid; } public String getAddressdetail() { return addressdetail; } public void setAddressdetail(String addressdetail) { this.addressdetail = addressdetail; } } |
测试类:
package com.neusoft.test.action;
import java.util.List;
import org.hibernate.Query; import org.hibernate.Session; import org.hibernate.Transaction;
import com.neusoft.test.entity.Address4; import com.neusoft.test.entity.Person4; import com.neusoft.test.utils.HibernateUtil;
@SuppressWarnings("unchecked") public class test4 { public static void main(String args[]) { Session session = HibernateUtil.getSession(); // 开启事务 Transaction tx = session.beginTransaction(); Person4 person=new Person4(); person.setName("uytua"); person.setAge(28); Address4 address=new Address4();
// 新建一个地址,而后添加给person address.setAddressdetail("wqesdasdasd"); address.setPerson(person); person.setAddress(address);
session.save(address); session.save(person); tx.commit();// 提交事务
Query query = session.createQuery("from Person4"); List<Person4> list = query.list(); for (Person4 p : list) { System.out.println("id:" + p.getPersonid() + " 姓名:" + p.getName() + " 年龄:" + p.getAge() + " 地址:" + p.getAddress().getAddressdetail()); } session.close();// 关闭session } } |
3 、继承映射
对于面向对象的程序设计语言而言,继承和多态是两个最基本的概念。Hibernate 的继承映射能够理解持久化类之间的继承关系。例如:人和学生之间的关系。学生继承了人,能够认为学生是一个特殊的人,若是对人进行查询,学生的实例也将被获得。
Hibernate支持三种继承映射策略:
每一个具体类一张表(table per concrete class) 将域模型中的每个实体对象映射到一个独立的表中,也就是说不用在关系开数据模型中考虑域模型中的继承关系和多态。
每一个类分层结构一张表(table per class hierarchy) 对于继承关系中的子类使用同一个表,这就须要在数据库表中增长额外的区分子类类型的字段。
每一个子类一张表(table per subclass) 域模型中的每一个类映射到一个表,经过关系数据模型中的外键来描述表之间的继承关系。这也就至关于按照域模型的结构来创建数据库中的表,并经过外键来创建表之间的继承关系。
( 1 ) subclass 继承映射 ( 单表继承 )
采用 subclass 元素的继承映射能够实现对于继承关系中的子类使用同一个表。(全部父类和子类都映射同一个表)
在这种映射策略下,整个继承树的全部实例都保保存在同一个表内。由于父类和子类的实例所有保存在同一个表中,所以须要在该表内增长一列,使用该列来区分每行记录到低是哪一个类的实例----这个列被称为辨别者列(discriminator)。
在这种映射策略下,使用 subclass 来映射子类,使用 discriminator-value 指定辨别者列的值。
新建数据库表person_table
映射配置:
<hibernate-mapping package="com.neusoft.test.entity"> <class name="Person" table="person_table" lazy="false"> <id name="personid"> <generator /> </id> <discriminator column="type" type="string" /> <property name="name" /> <property name="age" /> <subclass name="Student" discriminator-value="Student"> <property name="school_name" /> </subclass> <subclass name="Worker" discriminator-value="Worker"> <property name="company_name" /> </subclass> </class> </hibernate-mapping> |
实体类1:
package com.neusoft.test.entity;
public class Person { private int personid; private String name; private int age;
public int getPersonid() { return personid; } public void setPersonid(int personid) { this.personid = personid; } 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; } } |
实体类2:
package com.neusoft.test.entity;
public class Student extends Person { private String school_name;
public String getSchool_name() { return school_name; } public void setSchool_name(String schoolName) { school_name = schoolName; } } |
实体类3:
package com.neusoft.test.entity;
public class Worker extends Person { private String company_name;
public String getCompany_name() { return company_name; } public void setCompany_name(String companyName) { company_name = companyName; } } |
测试类:
package com.neusoft.test.action;
import java.util.Iterator; import java.util.List;
import org.hibernate.Session; import org.hibernate.Transaction;
import com.neusoft.test.entity.Person; import com.neusoft.test.entity.Student; import com.neusoft.test.entity.Worker; import com.neusoft.test.utils.HibernateUtil;
public class test { @SuppressWarnings("unchecked") public static void main(String args[]) { Session session = HibernateUtil.getSession(); // 开启事务 Transaction tx = session.beginTransaction();
Person person = new Person(); person.setName("小丽"); person.setAge(22); Student student = new Student(); student.setName("小明"); student.setAge(19); student.setSchool_name("清华"); Worker worker = new Worker(); worker.setName("小王"); worker.setAge(26); worker.setCompany_name("neusoft");
session.save(person); session.save(student); session.save(worker); tx.commit();// 提交事务
List personList = session.createQuery("from Person").list(); for (Iterator iter = personList.iterator(); iter.hasNext();) { Person a = (Person)iter.next(); System.out.print(" 姓名:"+a.getName()+" 年龄:"+a.getAge()+" 职业:"); //可以正确鉴别出正直的类型,HQL是支持多态查询的。 if (a instanceof Student) { System.out.print("Student"); Student s=(Student)a; System.out.println(" 学校:"+s.getSchool_name()); } else if (a instanceof Worker) { System.out.print("Worker"); Worker w=(Worker)a; System.out.println(" 公司:"+w.getCompany_name()); }else System.out.println("什么都不是"); }
// List list = session.createQuery("from java.lang.Object").list(); // for (Iterator iter = list.iterator(); iter.hasNext();){ // Object o =iter.next(); // if (o instanceof Student) { // Student s=(Student)o; // System.out.print(" 姓名:"+s.getName()+" 年龄:"+s.getAge()+" 职业:"); // System.out.print("Student"); // System.out.println(" 学校:"+s.getSchool_name()); // } else if (o instanceof Worker) { // Worker w=(Worker)o; // System.out.print(" 姓名:"+w.getName()+" 年龄:"+w.getAge()+" 职业:"); // System.out.print("Worker"); // System.out.println(" 公司:"+w.getCompany_name()); // }else{ // Person p=(Person)o; // System.out.print(" 姓名:"+p.getName()+" 年龄:"+p.getAge()+" 职业:"); // System.out.println("什么都不是"); // } // } session.close();// 关闭session } } |
( 2 ) joined-subclass 继承映射 (具体表继承)
采用 joined-subclass 元素的继承映射,每一个类映射一个表。(父类映射一个表,每一个子类也映射各自的表,子类表字段不是彻底的)
对象模型不用变化,存储模型须要变化。
采用这种映射策略时,父类实例保存在父类表中,子类实例由父类表和子类表共同存储。由于子类实例也是一个特殊的父类实例,所以必然也包含了父类实例的属性。因而将子类和父类共有的属性保存在父类表中,子类增长的属性,则保存在子类表中。
在这种映射策略下,无须使用鉴别者列,但须要为每一个子类使用 key 元素映射共有主键,该主键必须与父类标识属性的列名相同。但若是继承树的深度很深,可能查询一个子类实例时,须要跨越多个表,由于子类的数据一次保存在多个父类中。
子类增长的属性能够添加非空约束。由于子类的属性和父类的属性没有保存在同一个表中
新建数据库表person_table
student_table
worker_table
映射配置:
<class name="Person2" table="person_table"> <id name="personid"> <generator/> </id> <property name="name" /> <property name="age" /> <!--<joined-subclass>标签:继承映射 每一个类映射成一个表 --> <joined-subclass name="Student2" table="student_table"> <!-- <key>标签:会在相应的表(当前映射的表)里,加入一个外键 , 参照指向当前类的父类(当前Class标签对象的表)--> <key column="id"/> <property name="school_name"/> </joined-subclass> <joined-subclass name="Worker2" table="worker_table"> <key column="id"/> <property name="company_name"/> </joined-subclass> </class> |
实体类1:
package com.neusoft.test.entity;
public class Person2 { private int personid; private String name; private int age;
public int getPersonid() { return personid; } public void setPersonid(int personid) { this.personid = personid; } 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; } } |
实体类2:
package com.neusoft.test.entity;
public class Student2 extends Person2 { private String school_name;
public String getSchool_name() { return school_name; } public void setSchool_name(String schoolName) { school_name = schoolName; } } |
实体类3:
package com.neusoft.test.entity;
public class Worker2 extends Person2 { private String company_name;
public String getCompany_name() { return company_name; } public void setCompany_name(String companyName) { company_name = companyName; } } |
测试类:
package com.neusoft.test.action;
import java.util.Iterator; import java.util.List;
import org.hibernate.Session; import org.hibernate.Transaction;
import com.neusoft.test.entity.*; import com.neusoft.test.utils.HibernateUtil;
public class test2 { @SuppressWarnings("unchecked") public static void main(String args[]) { Session session = HibernateUtil.getSession(); // 开启事务 Transaction tx = session.beginTransaction();
Person2 person = new Person2(); person.setName("小丽"); person.setAge(22); Student2 student = new Student2(); student.setName("小明"); student.setAge(19); student.setSchool_name("清华"); Worker2 worker = new Worker2(); worker.setName("小王"); worker.setAge(26); worker.setCompany_name("neusoft");
session.save(person); session.save(student); session.save(worker); tx.commit();// 提交事务
List personList = session.createQuery("from Person2").list(); for (Iterator iter = personList.iterator(); iter.hasNext();) { Person2 a = (Person2)iter.next(); System.out.print(" 姓名:"+a.getName()+" 年龄:"+a.getAge()+" 职业:"); //可以正确鉴别出正直的类型,HQL是支持多态查询的。 if (a instanceof Student2) { System.out.print("Student"); Student2 s=(Student2)a; System.out.println(" 学校:"+s.getSchool_name()); } else if (a instanceof Worker2) { System.out.print("Worker"); Worker2 w=(Worker2)a; System.out.println(" 公司:"+w.getCompany_name()); }else System.out.println("什么都不是"); } session.close();// 关闭session } } |
采用 union-subclass 元素能够实现将每个实体对象映射到一个独立的表中。(父类映射一个表,每一个子类映射各自的表,子类表的字段是彻底的)
union-subclass 与 joined-subclass 映射策略相似:子类增长的属性也能够有非空约束 --- 即父类实例的数据保存在父表中,而子类实例的数据保存在子类表中。
与 joined-subclass 不一样的是,子类实例的数据仅保存在子类表中,而在父类表中没有任何记录。
在这种映射策略下,子类表的字段会比父类表的映射字段要多,由于子类表的字段等于父类表的字段加子类增长属性的总和
在这种映射策略下,既不须要使用鉴别者列,也无须使用 key 元素来映射共有主键.
新建数据库表person_table
student_table
worker_table
映射配置:
<class name="Person3" table="person_table"> <id name="personid"> <generator/> </id> <property name="name" /> <property name="age" /> <!-- 使用<union-subclass>标签来映射"每一个具体类映射成一张表"的映射关系 --> <union-subclass name="Student3" table="student_table"> <property name="school_name"/> </union-subclass> <union-subclass name="Worker3" table="worker_table"> <property name="company_name"/> </union-subclass> </class> |
实体类1:
package com.neusoft.test.entity;
public class Person3 { private int personid; private String name; private int age;
public int getPersonid() { return personid; } public void setPersonid(int personid) { this.personid = personid; } 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; } } |
实体类2:
package com.neusoft.test.entity;
public class Student3 extends Person3 { private String school_name;
public String getSchool_name() { return school_name; } public void setSchool_name(String schoolName) { school_name = schoolName; } } |
实体类3:
package com.neusoft.test.entity;
public class Worker3 extends Person3 { private String company_name;
public String getCompany_name() { return company_name; } public void setCompany_name(String companyName) { company_name = companyName; } } |
测试类:
package com.neusoft.test.action;
import java.util.Iterator; import java.util.List;
import org.hibernate.Session; import org.hibernate.Transaction;
import com.neusoft.test.entity.Person3; import com.neusoft.test.entity.Student3; import com.neusoft.test.entity.Worker3; import com.neusoft.test.utils.HibernateUtil;
public class test3 { @SuppressWarnings("unchecked") public static void main(String args[]) { Session session = HibernateUtil.getSession(); // 开启事务 Transaction tx = session.beginTransaction();
Person3 person = new Person3(); person.setName("小丽"); person.setAge(22); Student3 student = new Student3(); student.setName("小明"); student.setAge(19); student.setSchool_name("清华"); Worker3 worker = new Worker3(); worker.setName("小王"); worker.setAge(26); worker.setCompany_name("neusoft");
session.save(person); session.save(student); session.save(worker); tx.commit();// 提交事务
List personList = session.createQuery("from Person3").list(); for (Iterator iter = personList.iterator(); iter.hasNext();) { Person3 a = (Person3)iter.next(); System.out.print(" 姓名:"+a.getName()+" 年龄:"+a.getAge()+" 职业:"); //可以正确鉴别出正直的类型,HQL是支持多态查询的。 if (a instanceof Student3) { System.out.print("Student"); Student3 s=(Student3)a; System.out.println(" 学校:"+s.getSchool_name()); } else if (a instanceof Worker3) { System.out.print("Worker"); Worker3 w=(Worker3)a; System.out.println(" 公司:"+w.getCompany_name()); }else System.out.println("什么都不是"); } session.close();// 关闭session } } |
(4)三种继承关联映射的比较:
1、 第一种:它把全部的数据都存入一个表中,优势:效率好(操做的就是一个表);缺点:存在庸于字段,若是将庸于字段设置为非空,则就没法存入数据;
2、 第二种:井井有条,缺点:效率很差(表间存在关联表)
3、 第三种:主键字段不能够设置为自增主键生成策略。
建议使用第一种