Hibernate学习之一对多和多对一(一)

前言:最近上班工作不忙,随手写了几个demo,贴出来,供初学者学习一下

一.hibernate 简介:


        hibernate是一个开源框架,它是对象关联关系映射的框架,它对JDBC做了轻量级的封装,而我们java程序员可以使用面向对象的思想来操纵数据库。

        Hibernate是一个基于JDBC的主流持久化框架,是一个优秀的ORM实现。简化DAO层的编码工作

        Hibernate的底层也是使用的sql代码实现的。

二.新建项目的步骤


    A.第一步,导入项目所需的jar包。

Hibernate学习之一对多和多对一(一)_第1张图片

导入新下载的jar\hibernate-release-5.3.0.Final\hibernate-release-5.3.0.Final\lib\required下的所有的jar文件即可

Hibernate学习之一对多和多对一(一)_第2张图片

B.新建hibernate核心配置文件hibernate.cfg.xml(放在src目录下,文件位置固定)



    
		
			
			com.mysql.jdbc.Driver
			jdbc:mysql:///mydb3
			root
			000000
			
			
				
			4
				
			true
				
			true
				
			update
				
			org.hibernate.dialect.MySQL5InnoDBDialect
			
			thread
			
			
			
					
		    
    
    

C.新建实体类,模拟人和车之间的关系。一个人可以有多个车,一个车只能属于一个人。多---》车,一---》人

1.Car实体类

package com.ies.entity;

/*
 * car
 */
public class Car {
	
	private Integer cid;
	private String cname;
	private String cage;
	
	private People people;

	public Integer getCid() {
		return cid;
	}

	public void setCid(Integer cid) {
		this.cid = cid;
	}

	public String getCname() {
		return cname;
	}

	public void setCname(String cname) {
		this.cname = cname;
	}

	public String getCage() {
		return cage;
	}

	public void setCage(String cage) {
		this.cage = cage;
	}

	public People getPeople() {
		return people;
	}

	public void setPeople(People people) {
		this.people = people;
	}

	@Override
	public String toString() {
		return "Car [cname=" + cname + ", cage=" + cage + "]";
	}
}

2.People.java

package com.ies.entity;

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

/*
 * people
 */
public class People {
	
	private Integer pid;
	private String pname;
	private String page;
	
	private Set setCar = new HashSet<>();
	
	public Integer getPid() {
		return pid;
	}
	public void setPid(Integer pid) {
		this.pid = pid;
	}
	public Set getSetCar() {
		return setCar;
	}
	public void setSetCar(Set setCar) {
		this.setCar = setCar;
	}
	public String getPname() {
		return pname;
	}
	public void setPname(String pname) {
		this.pname = pname;
	}
	public String getPage() {
		return page;
	}
	public void setPage(String page) {
		this.page = page;
	}
	@Override
	public String toString() {
		return "People [pname=" + pname + ", page=" + page + "]";
	}
}

D.配置两个实体类的文件。

1.Car.hbm.xml



    
    	
    		
    			
    		
    		
    		
    		
			
    	
    

2.People.hbm.xml



    
    	
    		
    			
    		
    		
    		
    		
    		
    			
    			
    			
    		
    	
    

E.编写工具类,用来放回hibernate中sessionFactory对象和session对象

package com.ies.util;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;

public class HibnernateUtil {
	private static SessionFactory sessionFactory = null;
	static {
		Configuration  cfg = new Configuration();
		cfg.configure();
		/**
		 * 创建session的对象
		 * 读取核心配置文件的内容。
		 * 会根据映射关系,在数据库里把表创建
		 */
		sessionFactory = cfg.buildSessionFactory();
	}
	
	public  static SessionFactory getSessionFactory() {
		return sessionFactory;
	}
	
	public static Session openSession() {
		return sessionFactory.openSession();
	}
		
	public static Session currentSession() {
		return sessionFactory.getCurrentSession();
	}

	public static void main(String[] args) {
		
	}
}

 在这里说明一下,hibernate 中核心配置文件中update这句话的意义。

在hibernate核心配置文件加载时,会产生sessionFactory对象,sessionFactory会自动检测数据库中是否有需要创建的表,若没有则创建。也就是说,当我们运行HibnernateUtil.java这个类的时候,会在数据库中创建两个表以及他们之间的关系。

F.编写测试类

package com.ies.test;


import java.util.Iterator;
import java.util.List;
import java.util.Set;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.query.Query;
import org.junit.Test;

import com.ies.entity.Car;
import com.ies.entity.People;
import com.ies.util.HibnernateUtil;

public class OneToManyTest {

	private SessionFactory sessionFactory = null;
	
	private Session  session  = null;
	private Transaction transaction = null;
	
	/*
	 * add
	 */
	@Test
	public void addCar() {
		try {
			sessionFactory = HibnernateUtil.getSessionFactory();
			session = sessionFactory.openSession();
			transaction = session.beginTransaction();
			
			People people = new People();
			people.setPname("tom");
			people.setPage("2222");
			
			Car car = new Car();
			car.setCname("car1");
			car.setCage("1111");
			people.getSetCar().add(car);
//			car.setPeople(people);
			Car car2 = new Car();
			car2.setCname("car2");
			car2.setCage("2222");
//			car2.setPeople(people);
			
			people.getSetCar().add(car);
//			session.save(car);
//			session.save(car2)
			session.save(people);
			
			transaction.commit();
		}catch (Exception e) {
			if(transaction!=null) {
				transaction.rollback();
			}
			e.printStackTrace();
		}finally {
			session.close();
			sessionFactory.close();
		}
	}
	/*
	 * 删
	 */
	@Test
	public void testDelete() {
		try {
			sessionFactory = HibnernateUtil.getSessionFactory();
			session = sessionFactory.openSession();
			transaction = session.beginTransaction();
			/*
			 * 先查后删
			 */
			People people = session.get(People.class, 2);
			session.delete(people);
			transaction.commit();
		}catch (Exception e) {
			transaction.rollback();
			e.printStackTrace();
		}finally {
			session.close();
			sessionFactory.close();
		}
	}
	
	/*
	 * update
	 */
	@Test
	public void testUpdate() {
		try {
			sessionFactory = HibnernateUtil.getSessionFactory();
			session = sessionFactory.openSession();
			transaction = session.beginTransaction();
			/*
			 * 先查后改
			 */
			People people = session.get(People.class, 8);
			
			Set setCar = people.getSetCar();
			Car car = new Car();
			car.setCname("car3");
			car.setCage("2222");
			setCar.add(car);
			/*
			 * 在session中查询出来的对象都是持久态的对象,会创建对象的副本也就是快照
			 * 当执行transaction.commit时,堆内存数据和快照比较,若不同则执行update的方法。
			 */
			//session.update(people);
			transaction.commit();
		}catch (Exception e) {
			e.printStackTrace();
		}finally {
			session.close();
			sessionFactory.close();
		}
	}
	
	/*
	 *select  
	 */
	@Test
	public void testSelect1() {
		try {
			sessionFactory = HibnernateUtil.getSessionFactory();
			session = sessionFactory.openSession();
			transaction =  session.beginTransaction();
			People people = session.get(People.class, 8);
			/*
			 * 当调用session.get()方法时,hibernate 会立即发送请求到数据库查询。
			 */
			Set cars = people.getSetCar();
			Iterator iterator = cars.iterator();
			while (iterator.hasNext()) {
				Car car = iterator.next();
				System.out.println(car.getCname() +"==" +car.getCage());
			}
			
			transaction.commit();
		}catch (Exception e) {
			e.printStackTrace();
		}finally {
			session.close();
			sessionFactory.close();
		}
	}
	
	@Test
	public void testSelect2() {
		try {
			sessionFactory = HibnernateUtil.getSessionFactory();
			session = sessionFactory.openSession();
			transaction = session.beginTransaction();
			
			People people = session.load(People.class, 8);
			/*
			 * 当调用session.load()方法时,hibernate不会立即发送请求,而是等用到该对象的数据源时区数据库中查询
			 * 也就是hibernate的懒加载机制。
			 */
			Set cars = people.getSetCar();
			Iterator iterator = cars.iterator();
			while (iterator.hasNext()) {
				Car car = iterator.next();
				System.out.println(car.getCname() +"==" +car.getCage());
			}
			
			transaction.commit();
		}catch (Exception e) {
			transaction.rollback();
			e.printStackTrace();
		}finally {
			session.close();
			sessionFactory.close();
		}
	}
	
	
	/*
	 * hql查询
	 */
	@Test
	public void testhql() {
		try {
			sessionFactory = HibnernateUtil.getSessionFactory();
			session = sessionFactory.openSession();
			transaction = session.beginTransaction();
			String hql="FROM People";
			Query createQuery = session.createQuery(hql, People.class);
			List list = createQuery.list();
			System.out.println(list.get(0).toString());
			
			transaction.commit();
		}catch (Exception e) {
			e.printStackTrace();
		}finally {
			session.close();
			sessionFactory.close();
		}
	}
}

对以上代码有以下几点说明,

1.对添加people的操作,我们可以直接添加上people以及所属的car。这样就是有两种实现方式,第一种就是双方都维护关系,即:people的set设置上car,car中的people设置上所属的people。session要同时保存car和people对象。第二种就是一方维护关系,需要在的少的一方配置,表示少的一方维护关系。这样话,就只需要people的set设置上car集合,保存的时候只保存people对象即可。

2.在add操作时,我们可以看出hibernate运行时序,首先是对两个类对象保存在硬盘上,然后更新,将car的外键指people的主键,这对初学者了解即可。

Hibernate学习之一对多和多对一(一)_第3张图片

3.关于session.get()与session.load()方式查询说明。

      session.get()方式查询,hibernate会立刻向数据库发送请求,获取数据。

     session.load()方式查询,hiebrnate不会立刻向数据库发送请求,而是等到程序需要使用数据中查出的对象时,hibernate才会向数据库发送查询请求。

两者之间请求时间差问题,体现了文件hibernate的优化。

4.hibenate中对象的三种状态:即:持久态(persistent),游离态(detached),瞬时态(transient)

       持久态:一般只session.get()和session.load()方式获取到的对象。

       瞬时态:session.add()方法之前,对象都是瞬时态。

      游离态:session.update()和session.delete()方法调用之后,事务提交之前,属于游离态。

5.hibernate一级缓存

hibernate一级缓存是基于session 对象的,默认是开启状态,它的生命周期就是session的声明周期。session查询对象时,向一级缓存放入数据时,同时复制一份数据放入到Hibernate快照中,当使用commit()方法提交事务时,会清理Session的一级缓存,将一级缓存中的对象和快照中的对象是否一致,如果两个对象中的属性发生变化,则执行update语句,将一级缓存的对象同步到数据库,并更新快照;如果一致,则不执行update语句。

6.解释了4和5两条内容,终于到了重点了。那么我们现在来解释一下session.update()方法的 ,我们在更新之前,一定会调用查询方法,得到结果对象,此时对象是持久态的对象。在缓存区和快照区均有此对象。所以当我们改变对象的属性后,不使用session.update()方法直接提交事务,也会实现update的功能。

7.调用session.delete()方法时,我们可以看出是将两者之间的关系先解除后分别删除。session删除的时候是根据id删除的,所以即使我们的对象不是持久态的对象,一样可以实现删除。

Hibernate学习之一对多和多对一(一)_第4张图片

G:源码下载地址:hibernate多对一demo下载

今天呢,小编就先讲解到这里。后续小编会继续写hibernate的其他内容。

你可能感兴趣的:(Hibernate,java)