首页 > 代码库 > 学习hibernate笔记

学习hibernate笔记

       曾经学习java的时候,一開始就学习了hibernate,那时候总认为ssh很高大上,所以就急忙看了下相关视频。只是由于实际须要不高,所以后来一直没有使用上hibernate组件。如今一年过去了,也疯狂学习了java一段时间了,做过几个不大的项目,可是总算对java有些了解。如今參加了工作,公司使用的就是ssh,所以这两天又又一次開始捣鼓hibernate。这次学习直接使用editplus,直接开发。看了官网的demo,发现英语也没有想象中那么困难。哈哈,把自己的学习记录下来吧。这里主要记录三个方面:

       1.怎样搭建hibernate

       2.几种经常使用映射关系(one - to -one,one - to - many, many - to - one, many - to - many)


搭建hibernate(直接使用文本编辑器)

第一步:这个过程也不复杂,主要是下载到hibernate相关jar包,然后将必要的jar引入到classpath中,详细什么是classpath,大家能够百度下。假设不导入到classpath中,会出现不能找到类的异常。为什么会出现这样的情况呢?大家能够百度下,java 的类载入过程。

第二步:编写hibernate.cfg.xml文件。这个大家不用手写,直接去hibernate文章中copy一个就可以。以下给出我的代码

<?xml version='1.0' encoding='utf-8' ?>
<!DOCTYPE hibernate-configuration PUBLIC 
      "-//Hibernate/Hibernate Configuration DTD 3.0//EN"  
      "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">

<hibernate-configuration>
     
	 <session-factory>  
           <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>  
           <property name="hibernate.connection.url">jdbc:mysql://localhost:3306/hibernate_demo</property>  
           <property name="hibernate.connection.username">root</property>  
           <property name="hibernate.connection.password">root</property>  
           <property name="dialect">org.hibernate.dialect.MySQLDialect</property>  
           <property name="hibernate.show_sql">true</property>  
		   <!--if the value=http://www.mamicode.com/'create, means create table, every time open hibernate, if will drop the old scheme'-->>第三步:開始制作一个工具类,用来初始化hibernate组件。因为难度不高,直接给出代码,这些在文章中都已经有了,大家能够自己下载document看看。以下是代码:

import java.io.*;
import org.hibernate.*;
import org.hibernate.cfg.*;

/**
 * that is a hibernate config util
 * */
public class HibernateConfigurationUtil{
    
	private static HibernateConfigurationUtil singleton = new HibernateConfigurationUtil("hibernate.cfg.xml");
    private static SessionFactory factory;

	/**
	 * singleton pattern
	 * */
	private HibernateConfigurationUtil(String configXml){
	    init(configXml);
	}
    
	public void init(String configXml){
	     Configuration cfg = new Configuration().configure(new File("hibernate.cfg.xml"));
		 factory = cfg.buildSessionFactory();   // build the session factory
	}
    
	public static SessionFactory getSessionFactory(){
	    if(factory == null) return null;
		return factory;
	}

    /**
	 * open a new Session
	 *
	 * */
	public static Session openSession(){
	    Session session = factory.openSession();
		return session;
	}

}

注意下,这个类使用单例设计模式,由于hibernate组建在启动Configuration时,是很耗时的,并且这个对象在启动之后不能改变,所以每一个project中,启动一次就可以。

第三步:编写BaseHibernateDao,这个类注意是封装了save, delete, update, load这四个方法。

import java.io.*;
import org.hibernate.*;
import org.hibernate.cfg.*;

/**
 * that is the base hibernate dao,
 * it define a series of method to access database
 * if you want to 'delete, update a object, the object must exists in hibernate memery'
 *
 * @author luohong
 * @date 2014-08-07 
 * */
public class BaseHibernateDao{
	public BaseHibernateDao(){
	}

    /**
	 * try to save a object
	 * */
	public void save(Object object){
	    Session session = HibernateConfigurationUtil.openSession();
		// open transaction
		Transaction transaction = session.beginTransaction();
		session.save(object);
		// commint transaction
		transaction.commit();

	}

	/**
	 * try to update a object
	 * */
	public void update(Object object){
	    Session session = HibernateConfigurationUtil.openSession();
		// open transaction
		Transaction transaction = session.beginTransaction();
		session.update(object);
		// commint transaction
		transaction.commit();
	}
    
    /**
	 * try to delete a object
	 * */
	public void delete(Object object){
	    Session session = HibernateConfigurationUtil.openSession();
		// open transaction
		Transaction transaction = session.beginTransaction();
		session.delete(object);
		// commint transaction
		transaction.commit();
	}
    
	/**
	 * try to load a object from database by className and id
	 * */
	public Object load(Class<?> className, Serializable id){
		Session session = HibernateConfigurationUtil.openSession();
        // there is no need for transaction
		return session.load(className, id);
	}

}

注意:在save, update, delete方法中,仅仅用了Transaction,要开启事务,否则数据库找不到相关记录。

第四步:到了这里之后,就很easy了,仅仅须要针对详细的类,扩展BaseHibernateDao就可以。以下给出一个一对多的样例。模拟情景:用户(User)拥有多个住址(Address)首先给出两个类:

import java.util.*;


public class User{
	private int id;
	private String password;
	private String name;
    private Set<Address> addressSet;

	public void setAddressSet(Set<Address> addressSet){
	    this.addressSet = addressSet;
	}

	public Set<Address> getAddressSet(){
	    return addressSet;
	}

	public void setName(String name){
	    this.name = name;
	}

	public String getName(){
	    return name;
	}

	public void setId(int id){
	    this.id = id;
	}

	public int getId(){
	    return id;
	}

	public void setPassword(String password){
	    this.password = password;
	}

	public String getPassword(){
	    return password;
	}

	public String toString(){
	    return "id = " + id + ", name = " + name + ", password = " 
			+ password + ", addressSet = " + addressSet;
	}
}

/**
 * that is the user address
 * a user have many address, but a adress belong to a user
 * It is the classical 1 * n relationship
 * @author luohong
 * @date 2014-08-07
 * */
 public class Address {

//=====================properties=============================
	 private int id;
	 //private User belongTo;
	 private String code;
	 private String city;
	 private String street;
	 private String homeNumber;


//===================setter and getter========================
	 public void setId(int id){
	     this.id = id;
	 }

	 public int getId(){
	     return id;
	 }
/*
	 public void setBelongTo(User user){
	     this.belongTo = belongTo;
	 }

	 public User getBelongTo(){
	     return belongTo;
	 }
*/

	 public void setCode(String code){
	     this.code = code;
	 }

	 public String getCode(){
	     return code;
	 }

	 public void setCity(String city){
	     this.city = city;
	 }

	 public String getCity(){
	     return city;
	 }

	 public void setHomeNumber(String homeNumber){
	     this.homeNumber = homeNumber;
	 }

	 public String getHomeNumber(){
		 return homeNumber;
	 }

	 public String getStreet(){
	     return street;
	 }

	 public void setStreet(String street){
         this.street = street;
	 }

//========================toString================================
	 public String toString(){
	     return "id = " + id + ", city = " + city + ", street = " + street + ", homeNumber = " + homeNumber 
			 + ", code = " + code;// + ", belongTo = " + belongTo;
	 } 

     
 }

给出相关的User.xml, Address.xml;这个样例使用的是单向一对多。

<?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>

	<class name="User" table="user">
		<id name="id">
			<generator class="increment"/>
		</id>
		 
		<property name="password"/>

		<property name="name"/>
		
		<!--one to many-->
		<set name="addressSet" cascade="all">
		    <!--define the foreight column name-->
		    <key column="user_id"/>
			<!--define the foreight table name-->
			<one-to-many class="Address"/> 
		</set>
	</class>

</hibernate-mapping>  

<?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>

	<class name="Address" table="address">
		<id name="id">
			<generator class="increment"/>
		</id>
		<property name="code"/>

		<property name="city"/>

		<property name="street"/>
		<property name="homeNumber"/>

	</class>

</hibernate-mapping>  


然后编写一个UserDao,继承BaseHibernateDao,也非常easy,哈哈,一看就懂,这就是hibernate的厉害之处。

import java.util.*;
import org.hibernate.*;
/**
 * user dao extends BaseHibernateDao
 * you can add new functions to the custom dao
 * 
 * 
 * @author luohong
 * @date 2014-08-07
 * */
public class UserDao extends BaseHibernateDao{
    /**
	 * delete a user by userId
	 *
	 * */
	public void deleteById(String id){
		if (id == null) return;  // do nothing

		String hql = "delete User where id=?";
		// 1 open session
	    Session session = HibernateConfigurationUtil.openSession(); 
		// 2 create a query
		Query query = session.createQuery(hql);
		// 3 set the parameter to query
		query.setString(1, id);
		// 4 execute query
		query.executeUpdate();
	}
    
	/**
	 * find all user from database
	 * */
	public List<User> findAllUsers(){
	    String hql = "from User";
		Session session = HibernateConfigurationUtil.openSession();
		Query query = session.createQuery(hql);
		List userList = query.list();
		return (List<User>)userList;
	}
}

剩下的就是測试啦,come on...

import java.io.*;
import java.util.*;

/**
 * hibernate orm 框架demo
 * @author luohong
 * @date 2014-08-06 
 * 
 * */
public class HibernateDemo{
	public static void main(String[] args) throws Exception{
	    
		UserDao userDao = new UserDao();
        
		User user = new User();
		user.setName("luohong");
		user.setPassword("luohong");
        
		Set<Address> addressSet = new HashSet<Address>();
		for(int i=0; i<3; i++){
			Address address = new Address();
			address.setCode("111");
			address.setCity("hongkang");
			address.setStreet("universal street");
			address.setHomeNumber("a-2846");
			//address.setBelongTo(user);
			
			addressSet.add(address);
		}

		user.setAddressSet(addressSet);

		userDao.save(user);
	}
}


以下是程序的执行结果:

Hibernate: select max(id) from user
Hibernate: select max(id) from address
Hibernate: insert into user (password, name, id) values (?, ?, ?)
Hibernate: insert into address (code, city, street, homeNumber, user_id, id) values (?, ?, ?, ?, ?, ?)
Hibernate: insert into address (code, city, street, homeNumber, user_id, id) values (?, ?, ?, ?, ?, ?)
Hibernate: insert into address (code, city, street, homeNumber, user_id, id) values (?, ?, ?, ?, ?, ?)
<span style="color:#ff0000;">Hibernate: update address set user_id=? where id=?
Hibernate: update address set user_id=? where id=?
Hibernate: update address set user_id=? where id=?</span>

从执行结果我们能够看到,在这样的一对多关系中,这样的配置方式须要执行的sql是比較多的,由于hibernate是先分别插入两个表的数据,然后在更新多表一方的id值,就假设上面红色语句部分。这事实上是没有必要的,那么我们应该怎么办呢?没错,在配置一对多一的一方时,指定好 inverse="true":然后在代码里面主动设置address与user的关联,也就是address.setBelongTo(user);

                <set name="addressSet" inverse="true" cascade="all">
		    <key column="user_id" not-null="true"/>
			<one-to-many class="Address"/> 
		</set>
这就代表:address讲主动获取user对象的id值,在插入前就已经获得了user的id值了,仅仅须要插入数据就可以。而没有设置inverse="true"时,则直接插入new出来的address对象,然后再更新值。

以下是增加了inverse="true"的hibernate运行语句:

Hibernate: select max(id) from user
Hibernate: select max(id) from address
Hibernate: insert into user (password, name, id) values (?, ?, ?)
Hibernate: insert into address (code, city, street, homeNumber, user_id, id) values (?, ?, ?, ?, ?, ?)
Hibernate: insert into address (code, city, street, homeNumber, user_id, id) values (?, ?, ?, ?, ?, ?)
Hibernate: insert into address (code, city, street, homeNumber, user_id, id) values (?, ?, ?, ?, ?, ?)





上面的样例是基于单向的一对多,以下给出双向配置,事实上也非常easy,仅仅须要在多的一方增加:

<many-to-one name="belongTo" class="User" column="user_id" cascade="save-update" insert="false" update="false">
		</many-to-one>
在这里面,我们能够看到,无非就是指定关联的column,以及关联的表,而且配置级联关系。


作为一对多,另一种典型的一对多关系,那就是自关联啦。

样例:

<?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>
    <class name="Category" table="category">
        <id name="id">
			<generator class="increment"/>
		</id>
		
		<property name="name"/>
		
		<set name="categories" cascade="all">
		    <key column="parent_id"></key>
		    <one-to-many class="Category"></one-to-many>
		</set>
		
		<many-to-one name="parent" class="Category" cascade="save-update" column="parent_id">
		</many-to-one>
    </class>

</hibernate-mapping>  


以下使用hibernate来配置多对多...

实体类:

package net.itaem.hibernate.entity;

import java.util.HashSet;
import java.util.Set;

/**
 * 建立多对多
 * */
public class Student {

	private Integer id;
	private String name;
	private String number;
	private Set<Teacher> teachers = new HashSet<Teacher>();
	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 String getNumber() {
		return number;
	}
	public void setNumber(String number) {
		this.number = number;
	}
	public Set<Teacher> getTeachers() {
		return teachers;
	}
	public void setTeachers(Set<Teacher> teachers) {
		this.teachers = teachers;
	}
	
	@Override
	public String toString() {
		return "Student [id=" + id + ", name=" + name + ", number=" + number + "]";
	}
	
	
}

package net.itaem.hibernate.entity;

import java.util.HashSet;
import java.util.Set;

public class Teacher {
	private Integer id;
	private String name;
	private String number;
	private Set<Student> students = new HashSet<Student>();
	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 String getNumber() {
		return number;
	}
	public void setNumber(String number) {
		this.number = number;
	}
	public Set<Student> getStudents() {
		return students;
	}
	public void setStudents(Set<Student> students) {
		this.students = students;
	}
	@Override
	public String toString() {
		return "Teacher [id=" + id + ", name=" + name + ", number=" + number
				 + "]";
	}
	
	
	
}

以下是xml的配置:

<?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>
   
	<class name="net.itaem.hibernate.entity.Student" table="student">
		<id name="id">
			<generator class="increment"/>
		</id>
		 
		<property name="name"></property>

		<property name="number"></property>
		
		<!-- 配置多对多 -->
		<set name="teachers" cascade="all" table="student_teacher">
		    <!-- 指定外键关联 -->
		    <key column="student_id"/>
			<!-- 指定关联类属性 -->
			<many-to-many class="net.itaem.hibernate.entity.Teacher" column="teacher_id"/> 
		</set>
		
	</class>
</hibernate-mapping>  

<?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>
   
	<class name="net.itaem.hibernate.entity.Teacher" table="teacher">
		<id name="id">
			<generator class="increment"/>
		</id>
		 
		<property name="name"></property>

		<property name="number"></property>
		
		<!-- 配置多对多 -->
		<set name="students" inverse="true" cascade="all" table="student_teacher">
		    <!-- 指定外键关联 -->
		    <key column="teacher_id"/>
			<!-- 指定关联类属性 -->
			<many-to-many class="net.itaem.hibernate.entity.Student" column="student_id"/> 
		</set>
		
	</class>
</hibernate-mapping>  

然后是測试类:

package net.itaem.hibernate.dao;

import java.util.HashSet;
import java.util.Set;

import net.itaem.hibernate.entity.Student;
import net.itaem.hibernate.entity.Teacher;

public class StudentDao extends BaseHibernateDao{
    public static void main(String[] args) {
		Student student = new Student();
		student.setName("student");
		student.setNumber("201111701222");
		
		Set<Teacher> teachers = new HashSet<Teacher>();
		for(int i=0; i<10; i++){
			Teacher t = new Teacher();
			t.setName("teacher" + i);
			t.setNumber("20111170122" + i);
			teachers.add(t);
		}
		
		student.setTeachers(teachers);
		
		new StudentDao().save(student);
		System.out.println(((Student)new StudentDao().load(Student.class, new Integer(1))).getTeachers());
	}
}

输出结果:

Hibernate: select max(id) from student
Hibernate: select max(id) from teacher
Hibernate: insert into student (name, number, id) values (?, ?, ?)
Hibernate: insert into teacher (name, number, id) values (?, ?, ?)
Hibernate: insert into teacher (name, number, id) values (?, ?, ?)
Hibernate: insert into teacher (name, number, id) values (?, ?, ?)
Hibernate: insert into teacher (name, number, id) values (?, ?, ?)
Hibernate: insert into teacher (name, number, id) values (?, ?, ?)
Hibernate: insert into teacher (name, number, id) values (?, ?, ?)
Hibernate: insert into teacher (name, number, id) values (?, ?, ?)
Hibernate: insert into teacher (name, number, id) values (?, ?, ?)
Hibernate: insert into teacher (name, number, id) values (?, ?, ?)
Hibernate: insert into teacher (name, number, id) values (?, ?, ?)
Hibernate: insert into student_teacher (student_id, teacher_id) values (?, ?)
Hibernate: insert into student_teacher (student_id, teacher_id) values (?, ?)
Hibernate: insert into student_teacher (student_id, teacher_id) values (?, ?)
Hibernate: insert into student_teacher (student_id, teacher_id) values (?, ?)
Hibernate: insert into student_teacher (student_id, teacher_id) values (?, ?)
Hibernate: insert into student_teacher (student_id, teacher_id) values (?, ?)
Hibernate: insert into student_teacher (student_id, teacher_id) values (?, ?)
Hibernate: insert into student_teacher (student_id, teacher_id) values (?, ?)
Hibernate: insert into student_teacher (student_id, teacher_id) values (?, ?)
Hibernate: insert into student_teacher (student_id, teacher_id) values (?, ?)
Hibernate: select student0_.id as id1_2_0_, student0_.name as name2_2_0_, student0_.number as number3_2_0_ from student student0_ where student0_.id=?
Hibernate: select teachers0_.student_id as student_1_2_0_, teachers0_.teacher_id as teacher_2_3_0_, teacher1_.id as id1_4_1_, teacher1_.name as name2_4_1_, teacher1_.number as number3_4_1_ from student_teacher teachers0_ inner join teacher teacher1_ on teachers0_.teacher_id=teacher1_.id where teachers0_.student_id=?
Hibernate: select students0_.teacher_id as teacher_2_4_0_, students0_.student_id as student_1_3_0_, student1_.id as id1_2_1_, student1_.name as name2_2_1_, student1_.number as number3_2_1_ from student_teacher students0_ inner join student student1_ on students0_.student_id=student1_.id where students0_.teacher_id=?
Hibernate: select students0_.teacher_id as teacher_2_4_0_, students0_.student_id as student_1_3_0_, student1_.id as id1_2_1_, student1_.name as name2_2_1_, student1_.number as number3_2_1_ from student_teacher students0_ inner join student student1_ on students0_.student_id=student1_.id where students0_.teacher_id=?
Hibernate: select students0_.teacher_id as teacher_2_4_0_, students0_.student_id as student_1_3_0_, student1_.id as id1_2_1_, student1_.name as name2_2_1_, student1_.number as number3_2_1_ from student_teacher students0_ inner join student student1_ on students0_.student_id=student1_.id where students0_.teacher_id=?
Hibernate: select students0_.teacher_id as teacher_2_4_0_, students0_.student_id as student_1_3_0_, student1_.id as id1_2_1_, student1_.name as name2_2_1_, student1_.number as number3_2_1_ from student_teacher students0_ inner join student student1_ on students0_.student_id=student1_.id where students0_.teacher_id=?
Hibernate: select students0_.teacher_id as teacher_2_4_0_, students0_.student_id as student_1_3_0_, student1_.id as id1_2_1_, student1_.name as name2_2_1_, student1_.number as number3_2_1_ from student_teacher students0_ inner join student student1_ on students0_.student_id=student1_.id where students0_.teacher_id=?
Hibernate: select students0_.teacher_id as teacher_2_4_0_, students0_.student_id as student_1_3_0_, student1_.id as id1_2_1_, student1_.name as name2_2_1_, student1_.number as number3_2_1_ from student_teacher students0_ inner join student student1_ on students0_.student_id=student1_.id where students0_.teacher_id=?
Hibernate: select students0_.teacher_id as teacher_2_4_0_, students0_.student_id as student_1_3_0_, student1_.id as id1_2_1_, student1_.name as name2_2_1_, student1_.number as number3_2_1_ from student_teacher students0_ inner join student student1_ on students0_.student_id=student1_.id where students0_.teacher_id=?
Hibernate: select students0_.teacher_id as teacher_2_4_0_, students0_.student_id as student_1_3_0_, student1_.id as id1_2_1_, student1_.name as name2_2_1_, student1_.number as number3_2_1_ from student_teacher students0_ inner join student student1_ on students0_.student_id=student1_.id where students0_.teacher_id=?
Hibernate: select students0_.teacher_id as teacher_2_4_0_, students0_.student_id as student_1_3_0_, student1_.id as id1_2_1_, student1_.name as name2_2_1_, student1_.number as number3_2_1_ from student_teacher students0_ inner join student student1_ on students0_.student_id=student1_.id where students0_.teacher_id=?
Hibernate: select students0_.teacher_id as teacher_2_4_0_, students0_.student_id as student_1_3_0_, student1_.id as id1_2_1_, student1_.name as name2_2_1_, student1_.number as number3_2_1_ from student_teacher students0_ inner join student student1_ on students0_.student_id=student1_.id where students0_.teacher_id=?
这样子,双向的多对多也就配置完毕了。

学习hibernate笔记