什么是Hibernate Hibernate是一个开放源代码的对象关系映射框架,它对JDBC进行了非常轻量级的对象封装,它将POJO与数据库表建立映射关系,是一个全自动的orm框架,hibernate可以自动生成SQL语句,自动执行,使得Java程序员可以随心所欲的使用对象编程思维来操纵数据库。 Hibernate可以应用在任何使用JDBC的场合,既可以在Java的客户端程序使用,也可以在Servlet/JSP的Web应用中使用,最具革命意义的是,Hibernate可以在应用EJB的J2EE架构中取代CMP,完成数据持久化的重任。
此案例用于理解脏检查,以及Hibernate关系映射的配置 pom.xml 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 <?xml version="1.0" encoding="UTF-8" ?> <project xmlns ="http://maven.apache.org/POM/4.0.0" xmlns:xsi ="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation ="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" > <modelVersion > 4.0.0</modelVersion > <groupId > com</groupId > <artifactId > HibernateCase</artifactId > <version > 1.0-SNAPSHOT</version > <dependencies > <dependency > <groupId > org.hibernate</groupId > <artifactId > hibernate-core</artifactId > <version > 5.2.12.Final</version > </dependency > <dependency > <groupId > com.oracle</groupId > <artifactId > ojdbc6</artifactId > <version > 12.1.0.2</version > </dependency > </dependencies > </project >
数据库的关系 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 CREATE TABLE depa( ID NUMBER NOT NULL , NAME NVARCHAR2 (50 ) NOT NULL ); CREATE TABLE emp( ID NUMBER NOT NULL , NAME NVARCHAR2 (50 ) NOT NULL , depa_id NUMBER NOT NULL ); CREATE TABLE post( ID NUMBER NOT NULL , NAME NVARCHAR2 (50 ) NOT NULL ); CREATE TABLE emp_post( emp_id NUMBER NOT NULL , post_id NUMBER NOT NULL );
emp_post
职员职位表为中间表,实体类可以不存在
实体类 Depa 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 package com.entity;import java.util.HashSet;import java.util.Set;public class Depa { private Integer id; private String name; private Set<Emp> emps = new HashSet <Emp>(); @Override public String toString () { return "Depa{" + "id=" + id + ", name='" + name + '\'' + '}' ; } public Set<Emp> getEmps () { return emps; } public void setEmps (Set<Emp> emps) { this .emps = emps; } public Integer getId () { return id; } public void setId (Integer id) { this .id = id; } public String getName () { return name; } public void setName (String name) { this .name = name; } }
Emp 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 package com.entity;import java.util.HashSet;import java.util.Set;public class Emp { private Integer id; private String name; private Depa depaid; private Set<Post> posts = new HashSet <Post>(); @Override public String toString () { return "Emp{" + "id=" + id + ", name='" + name + '\'' + '}' ; } public Set<Post> getPosts () { return posts; } public void setPosts (Set<Post> posts) { this .posts = posts; } public Integer getId () { return id; } public void setId (Integer id) { this .id = id; } public String getName () { return name; } public void setName (String name) { this .name = name; } public Depa getDepaid () { return depaid; } public void setDepaid (Depa depaid) { this .depaid = depaid; } }
Post 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 package com.entity;import java.util.HashSet;import java.util.Set;public class Post { private Integer id; private String name; private Set<Emp> emps = new HashSet <Emp>(); @Override public String toString () { return "Post{" + "id=" + id + ", name='" + name + '\'' + '}' ; } public Set<Emp> getEmps () { return emps; } public void setEmps (Set<Emp> emps) { this .emps = emps; } public Integer getId () { return id; } public void setId (Integer id) { this .id = id; } public String getName () { return name; } public void setName (String name) { this .name = name; } }
Emp
实体类 和 Post
实体类 都有对方的 Set<?>
集合,这也是操作中间表 emp_post
的关键属性
对实体类关系映射配置 depa.hbm.xml 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 <?xml version="1.0" ?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd" > <hibernate-mapping package ="com.entity" > <class name ="Depa" table ="depa" > <id name ="id" > <generator class ="increment" /> </id > <property name ="name" /> <set name ="emps" table ="emp" cascade ="all" inverse ="true" > <key column ="depa_id" > </key > <one-to-many class ="Emp" /> </set > </class > </hibernate-mapping >
emp.hbm.xml 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 <?xml version="1.0" ?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd" > <hibernate-mapping package ="com.entity" > <class name ="Emp" table ="emp" > <id name ="id" > <generator class ="increment" /> </id > <property name ="name" /> <many-to-one name ="depaid" class ="Depa" column ="depa_id" /> <set name ="posts" table ="emp_post" cascade ="save-update" > <key column ="emp_id" > </key > <many-to-many class ="Post" column ="post_id" /> </set > </class > </hibernate-mapping >
post.hbm.xml 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 <?xml version="1.0" ?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd" > <hibernate-mapping package ="com.entity" > <class name ="Post" table ="post" > <id name ="id" > <generator class ="increment" /> </id > <property name ="name" /> <set name ="emps" table ="emp_post" cascade ="save-update" > <key column ="post_id" > </key > <many-to-many class ="Emp" column ="emp_id" /> </set > </class > </hibernate-mapping >
将实体类的 XML
映射到 hibernate.cfg.xml 配置
hibernate.cfg.xml 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 <?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd" > <hibernate-configuration > <session-factory > <property name ="connection.url" > jdbc:oracle:thin:@localhost:1521:orcl</property > <property name ="connection.username" > system</property > <property name ="connection.password" > simon</property > <property name ="connection.driver_class" > oracle.jdbc.driver.OracleDriver</property > <property name ="current_session_context_class" > thread</property > <property name ="show_sql" > true</property > <property name ="format_sql" > true</property > <mapping resource ="com/entity/depa.hbm.xml" /> <mapping resource ="com/entity/emp.hbm.xml" /> <mapping resource ="com/entity/post.hbm.xml" /> </session-factory > </hibernate-configuration >
Hibernate工具类 HibernateUtil 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 package com.util;import org.hibernate.Session;import org.hibernate.SessionFactory;import org.hibernate.cfg.Configuration;public class HibernateUtil { private static Configuration configuration; private static final SessionFactory factory; static { configuration = new Configuration ().configure("hibernate.cfg.xml" ); factory = configuration.buildSessionFactory(); } public static Session getSession () { return factory.getCurrentSession(); } }
测试类 Test 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 package com.test;import com.entity.Depa;import com.entity.Emp;import com.entity.Post;import com.util.HibernateUtil;import org.hibernate.Session;import org.hibernate.Transaction;public class Test { public static void main (String[] args) { Session session = HibernateUtil.getSession(); Transaction transaction = session.beginTransaction(); System.out.println("查询ID为1的职员数据" ); Emp emp = session.get(Emp.class, 1 ); System.out.println(emp); System.out.println("通过职员得到中间表emp_post数据" ); for (Post post : emp.getPosts()) { System.out.println(post); } System.out.println("清除职员中间表emp_post的数据" ); emp.getPosts().clear(); System.out.println("查询ID为2的职位数据" ); Post post = session.get(Post.class, 2 ); System.out.println(post); System.out.println("将查到的职位给职员新增中间表emp_post数据" ); emp.getPosts().add(post); System.out.println("查询ID为1的职员数据" ); emp = session.get(Emp.class, 1 ); System.out.println(emp); System.out.println("通过职员得到中间表emp_post数据" ); for (Post temp : emp.getPosts()) { System.out.println(temp); } System.out.println("通过职员得到部门表depa数据" ); System.out.println(emp.getDepaid()); System.out.println("查询ID为1的部门数据" ); Depa depa = session.get(Depa.class, 1 ); System.out.println(depa); System.out.println("将查到的部门depa给职员emp利用脏检查修改" ); emp.setDepaid(depa); System.out.println("查询ID为1的职员数据" ); emp = session.get(Emp.class, 1 ); System.out.println(emp); System.out.println("通过职员得到部门表depa数据" ); System.out.println(emp.getDepaid()); System.out.println("查询ID为2的部门数据" ); depa = session.get(Depa.class, 2 ); System.out.println(depa); System.out.println("得到部门对象所属职员" ); for (Emp e : depa.getEmps()) { System.out.println(e); } System.out.println("利用脏检查删除部门对象所属的ID为1的职员" ); depa.getEmps().remove(emp); System.out.println("查询ID为2的部门数据" ); depa = session.get(Depa.class, 2 ); System.out.println(depa); System.out.println("得到部门对象所属职员" ); for (Emp e : depa.getEmps()) { System.out.println(e); } } }
控制台输出 看看测试类代码对数据库的数据进行了哪些操作
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 查询ID为1的职员数据 Hibernate: select emp0_.id as id1_1_0_, emp0_.name as name2_1_0_, emp0_.depa_id as depa_id3_1_0_ from emp emp0_ where emp0_.id=? Emp{id=1, name='张三'} 通过职员得到中间表emp_post数据 Hibernate: select posts0_.emp_id as emp_id1_2_0_, posts0_.post_id as post_id2_2_0_, post1_.id as id1_3_1_, post1_.name as name2_3_1_ from emp_post posts0_ inner join post post1_ on posts0_.post_id=post1_.id where posts0_.emp_id=? Post{id=1, name='职员'} 清除职员中间表emp_post的数据 查询ID为2的职位数据 Hibernate: select post0_.id as id1_3_0_, post0_.name as name2_3_0_ from post post0_ where post0_.id=? Post{id=2, name='主管'} 将查到的职位给职员新增中间表emp_post数据 查询ID为1的职员数据 Emp{id=1, name='张三'} 通过职员得到中间表emp_post数据 Post{id=2, name='主管'} 通过职员得到部门表depa数据 Hibernate: select depa0_.id as id1_0_0_, depa0_.name as name2_0_0_ from depa depa0_ where depa0_.id=? Depa{id=2, name='美工部'} 查询ID为1的部门数据 Hibernate: select depa0_.id as id1_0_0_, depa0_.name as name2_0_0_ from depa depa0_ where depa0_.id=? Depa{id=1, name='销售部'} 将查到的部门depa给职员emp利用脏检查修改 查询ID为1的职员数据 Emp{id=1, name='张三'} 通过职员得到部门表depa数据 Depa{id=1, name='销售部'} 查询ID为2的部门数据 Depa{id=2, name='美工部'} 得到部门对象所属职员 Hibernate: select emps0_.depa_id as depa_id3_1_0_, emps0_.id as id1_1_0_, emps0_.id as id1_1_1_, emps0_.name as name2_1_1_, emps0_.depa_id as depa_id3_1_1_ from emp emps0_ where emps0_.depa_id=? Emp{id=1, name='张三'} 利用脏检查删除部门对象所属的ID为1的职员 查询ID为2的部门数据 Depa{id=2, name='美工部'} 得到部门对象所属职员
案例为重新整理的, MySQL连接为主, 字段名进行了修改, 整体区别不大