hibernate的CRUD操作

本文简单总结一下hibernate的具有映射关系CRUD操作,主要使用到了cascade和fetch,其中cascade针对的是CUD操作,表示级联关系,fetch针对的是R操作,表示级联加载方式。

1.先看下javaEE的API中关于cascade的描述

javax.persistence

Enum CascadeType

java.lang.Object
  java.lang.Enum<CascadeType>
      javax.persistence.CascadeType
All Implemented Interfaces:
Serializable,
Comparable<CascadeType>

public enum CascadeType
extends Enum<CascadeType>

Defines the set of cascadable operations that are propagated to the associated entity. The value
cascade=ALL is equivalent to cascade={PERSIST, MERGE, REMOVE, REFRESH}.

Since:
Java Persistence 1.0


Enum Constant Summary
ALL           Cascade all operations
MERGE           Cascade merge operation
PERSIST           Cascade persist operation
REFRESH           Cascade refresh operation
REMOVE           Cascade remove operation
Method Summary
static CascadeType valueOf(String name)           Returns the enum constant of this
type with the specified name.
static CascadeType[] values()           Returns an array containing the constants of this enum type, in the order they‘re declared.
Methods inherited from class java.lang.Enum
clone,
compareTo, equals, getDeclaringClass, hashCode, name, ordinal, toString, valueOf
Methods inherited from class java.lang.Object
finalize,
getClass, notify, notifyAll, wait, wait, wait

具体的使用方式,以annotation为例,例如@ManyToOne(cascade=CascadeType.ALL),其中cascade的值可以是一个数组。

2.再看下javaEE的API中关于fetch的描述

javax.persistence Enum FetchType

java.lang.Object
  java.lang.Enum<FetchType>
      javax.persistence.FetchType
All Implemented Interfaces:
Serializable,
Comparable<FetchType>

public enum FetchType
extends Enum<FetchType>

Defines strategies for fetching data from the database. The EAGER strategy is a requirement on the persistence provider runtime that data must be eagerly fetched. The
LAZY strategy is a hint to the persistence provider runtime that data should be fetched lazily when it is first accessed. The implementation is permitted to eagerly fetch data for which the
LAZY strategy hint has been specified. In particular, lazy fetching might only be available for
Basic mappings for which property-based access is used.

   Example:
   @Basic(fetch=LAZY)
   protected String getName() { return name; }
 
Since:
Java Persistence 1.0

Enum Constant Summary
EAGER

Defines that data must be eagerly fetched

LAZY

Defines that data can be lazily fetched

Method Summary
static FetchType valueOf(String name)

Returns the enum constant of this type with the specified name.

static FetchType[] values()

Returns an array containing the constants of this enum type, in the order they‘re declared.

Methods inherited from class java.lang.Enum
clone,
compareTo, equals, getDeclaringClass, hashCode, name, ordinal, toString, valueOf
Methods inherited from class java.lang.Object
finalize,
getClass, notify, notifyAll, wait, wait, wait

具体的使用方式,以annotation为例,例如@ManyToOne(fetch=FetchType.EAGER)。

3.进行CRCD的C,即插入(insert)操作

仍然使用之前的Group和User,二者为一对多关系

Group

package com.baosight.model;

import java.util.*;

import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import javax.persistence.Table;

@Entity
@Table(name="t_group")
public class Group {
	private String id;
	private String name;
	private Set<User> users = new HashSet<User>();
	@Id
	@GeneratedValue//auto
	public String getId() {
		return id;
	}
	public void setId(String id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	@OneToMany(mappedBy="group",cascade=CascadeType.ALL)
	public Set<User> getUsers() {
		return users;
	}
	public void setUsers(Set<User> users) {
		this.users = users;
	}
}

User

package com.baosight.model;

import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.OneToOne;
import javax.persistence.Table;

@Entity
@Table(name="t_user")
public class User {
	private String id;
	private String name;
	private Group group;
	@Id
	@GeneratedValue//auto
	public String getId() {
		return id;
	}
	public void setId(String id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	@ManyToOne(cascade=CascadeType.ALL)
	public Group getGroup() {
		return group;
	}
	public void setGroup(Group group) {
		this.group = group;
	}
}

使用JUnit进行测试

package com.baosight.model;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.AnnotationConfiguration;
import org.hibernate.cfg.Configuration;
import org.hibernate.tool.hbm2ddl.SchemaExport;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;

public class OrMappingTest {
	private static SessionFactory sf = null;
	@BeforeClass
	public static void beforeClass(){
		new SchemaExport(new AnnotationConfiguration().configure()).create(false, true);
		// 读取配置文件
		Configuration cfg = new AnnotationConfiguration();
		// 得到session工厂
		sf = cfg.configure().buildSessionFactory();
	}

	@Test
	public void testSaveUser() {
		Group g = new Group();
		User u = new User();
		u.setName("u1");
		g.setName("g1");
		u.setGroup(g);
		Session s = sf.getCurrentSession();
		s.beginTransaction();
//		s.save(g);
		s.save(u);
		s.getTransaction().commit();
	}
	@Test
	public void testSaveGroup() {
		User u1 = new User();
		u1.setName("u1");
		User u2 = new User();
		u2.setName("u2");
		Group g = new Group();
		g.setName("g1");
		g.getUsers().add(u1);
		g.getUsers().add(u2);
		u1.setGroup(g);
		u2.setGroup(g);
		Session s = sf.getCurrentSession();
		s.beginTransaction();
		s.save(g);
		s.getTransaction().commit();
	}
	@Test
	public void testGetUser() {
		testSaveGroup();
		Session s = sf.getCurrentSession();
		s.beginTransaction();
		User u = (User) s.get(User.class, "2");
		s.getTransaction().commit();
		System.out.println(u.getGroup().getName());
	}
	@Test
	public void testUpdateUser() {
		testSaveGroup();

		Session s = sf.getCurrentSession();
		s.beginTransaction();
		User u = (User) s.get(User.class, "2");
		s.getTransaction().commit();

		u.setName("user");
		u.getGroup().setName("group");

		Session s2 = sf.getCurrentSession();
		s2.beginTransaction();
		s2.update(u);
		s2.getTransaction().commit();

	}
	@Test
	public void testLoadUser() {
		testSaveGroup();
		Session s = sf.getCurrentSession();
		s.beginTransaction();
		User u = (User) s.load(User.class, "2");
		System.out.println(u.getGroup().getName());
		s.getTransaction().commit();
	}
	@Test
	public void testDeleteUser() {
		testSaveGroup();
		Session s = sf.getCurrentSession();
		s.beginTransaction();
//		User u = (User) s.load(User.class, "2");
//		u.setGroup(null);
//		s.delete(u);
		s.createQuery("delete from User u where u.id=2").executeUpdate();
		s.getTransaction().commit();
	}
	@Test
	public void testGetGroup() {
		testSaveGroup();
		Session s = sf.getCurrentSession();
		s.beginTransaction();
		Group g = (Group) s.get(Group.class, "1");
		s.getTransaction().commit();
		for(User u:g.getUsers()){
			System.out.println(u.getName());
		}
	}
	@Test
	public void testLoadGroup() {
		testSaveGroup();
		Session s = sf.getCurrentSession();
		s.beginTransaction();
		Group g = (Group) s.load(Group.class, "1");
		for(User u:g.getUsers()){
			System.out.println(u.getName());
		}
		s.getTransaction().commit();
	}
	@Test
	public void testDeleteGroup() {
		testSaveGroup();
		Session s = sf.getCurrentSession();
		s.beginTransaction();
		Group g = (Group) s.load(Group.class, "1");
		for(User u:g.getUsers()){
			u.setGroup(null);
		}
		g.setUsers(null);
		s.delete(g);
		s.getTransaction().commit();
	}
	/*@Test
	public void testSchemaExport() {
	}*/
	@AfterClass
	public static void afterClass(){
		// 关闭session工厂
		sf.close();
	}
}

其中测试C使用的方法为testSaveUser和testSaveGroup

3.1先看testSaveUser,当不设置Group和User二者之间的关联时,方法为:

	@Test
	public void testSaveUser() {
		Group g = new Group();
		User u = new User();
		u.setName("u1");
		g.setName("g1");
//		u.setGroup(g);
		Session s = sf.getCurrentSession();
		s.beginTransaction();
		s.save(g);
		s.save(u);
		s.getTransaction().commit();
	}

运行结果为

可以看到2张表插入的数据没有关联,group_id是null

3.2当testSaveUser设置Group和User二者之间的关联时,方法为:

@Test
	public void testSaveUser() {
		Group g = new Group();
		User u = new User();
		u.setName("u1");
		g.setName("g1");
		u.setGroup(g);
		Session s = sf.getCurrentSession();
		s.beginTransaction();
//		s.save(g);
		s.save(u);
		s.getTransaction().commit();
	}

需要在User中的getGroup上使用@ManyToOne(cascade=CascadeType.ALL),表示级联保存

@ManyToOne(cascade=CascadeType.ALL)
	public Group getGroup() {
		return group;
	}

运行结果

可以看到,这时group_id就有值了。

3.3再看看testSaveGroup,当仅在Group设置二者之间的关联时,方法为:

@Test
	public void testSaveGroup() {
		User u1 = new User();
		u1.setName("u1");
		User u2 = new User();
		u2.setName("u2");
		Group g = new Group();
		g.setName("g1");
		g.getUsers().add(u1);
		g.getUsers().add(u2);
//		u1.setGroup(g);
//		u2.setGroup(g);
		Session s = sf.getCurrentSession();
		s.beginTransaction();
		s.save(g);
		s.getTransaction().commit();
	}

需要在Group中的getUsers上使用@OneToMany(mappedBy="group",cascade=CascadeType.ALL),表示级联保存

@OneToMany(mappedBy="group",cascade=CascadeType.ALL)
	public Set<User> getUsers() {
		return users;
	}

测试结果为

可以看到,是有问题的,此时group_id的值为null

3.4还需要在上面的User设置关联,testSaveGroup为

@Test
	public void testSaveGroup() {
		User u1 = new User();
		u1.setName("u1");
		User u2 = new User();
		u2.setName("u2");
		Group g = new Group();
		g.setName("g1");
		g.getUsers().add(u1);
		g.getUsers().add(u2);
		u1.setGroup(g);
		u2.setGroup(g);
		Session s = sf.getCurrentSession();
		s.beginTransaction();
		s.save(g);
		s.getTransaction().commit();
	}

这时,group_id就有值了

4.关于CRUD的R,即读取操作,主要使用的是get和load方法,使用到的是fetch

值得一提的是,对于本例中的Many2One/One2Many双向关联,在不设置fetch的时候,hibernate对于fetch是有默认值的。

具体来说,@ManyToOne的默认值为fetch=FetchType.EAGER。例如本例中User不设置fetch相当于设置了fetch=FetchType.EAGER,当R的时候会自动级联查询1的一方

@OneToMany的默认值为fetch=FetchType.LAZY。例如本例中Group不设置fetch相当于设置了fetch=FetchType.LAZY,当R的时候不会自动级联查询多的一方

首先看下get方法

4.1看下testGetUser方法

@Test
	public void testGetUser() {
		testSaveGroup();
		Session s = sf.getCurrentSession();
		s.beginTransaction();
		User u = (User) s.get(User.class, "2");
		s.getTransaction().commit();
		System.out.println(u.getGroup().getName());
	}

结果为

从结果可以看到,会自动进行级联查询

4.2看下testGetGroup方法

@Test
	public void testGetGroup() {
		testSaveGroup();
		Session s = sf.getCurrentSession();
		s.beginTransaction();
		Group g = (Group) s.get(Group.class, "1");
		s.getTransaction().commit();
		for(User u:g.getUsers()){
			System.out.println(u.getName());
		}
	}

运行结果为

上面讲过@OneToMany的默认值为fetch=FetchType.LAZY,所以未执行对User的查询

4.3修改Group的getUsers方法

@OneToMany(mappedBy="group",cascade=CascadeType.ALL,fetch=FetchType.EAGER)
	public Set<User> getUsers() {
		return users;
	}

测试结果为

再来看看load方法

4.4看下testLoadUser

@Test
	public void testLoadUser() {
		testSaveGroup();
		Session s = sf.getCurrentSession();
		s.beginTransaction();
		User u = (User) s.load(User.class, "2");
		System.out.println(u.getGroup().getName());
		s.getTransaction().commit();
	}

执行结果为

4.5看下testLoadGroup

@Test
	public void testLoadGroup() {
		testSaveGroup();
		Session s = sf.getCurrentSession();
		s.beginTransaction();
		Group g = (Group) s.load(Group.class, "1");
		for(User u:g.getUsers()){
			System.out.println(u.getName());
		}
		s.getTransaction().commit();
	}

执行结果为

注意,此时,并为设置Group和Use的fetch属性

5.CRUD的U,即修改操作,主要使用的是update方法

前面提到了,可以设置cascade指明级联方式,再执行与之相对应的操作

看下testUpdateUser

@Test
	public void testUpdateUser() {
		testSaveGroup();

		Session s = sf.getCurrentSession();
		s.beginTransaction();
		User u = (User) s.get(User.class, "2");
		s.getTransaction().commit();

		u.setName("user");
		u.getGroup().setName("group");

		Session s2 = sf.getCurrentSession();
		s2.beginTransaction();
		s2.update(u);
		s2.getTransaction().commit();

	}

执行结果为

6.CRUD的D,即删除操作,主要使用delete方法

6.1先看下testDeleteUser

@Test
	public void testDeleteUser() {
		testSaveGroup();
		Session s = sf.getCurrentSession();
		s.beginTransaction();
		User u = (User) s.load(User.class, "2");
//		u.setGroup(null);
		s.delete(u);
//		s.createQuery("delete from User u where u.id=2").executeUpdate();
		s.getTransaction().commit();
	}

测试结果

由于Group和User中都设置了cascade,所以删除User数据会级联删除Group的数据

6.2要想只删除User的数据,需要在删除之前先切断映射关系

@Test
	public void testDeleteUser() {
		testSaveGroup();
		Session s = sf.getCurrentSession();
		s.beginTransaction();
		User u = (User) s.load(User.class, "2");
		u.setGroup(null);
		s.delete(u);
//		s.createQuery("delete from User u where u.id=2").executeUpdate();
		s.getTransaction().commit();
	}

执行结果

6.3当然,在明确知道要删除的多的一方的id的话,还可以直接执行HQL进行删除操作

@Test
	public void testDeleteUser() {
		testSaveGroup();
		Session s = sf.getCurrentSession();
		s.beginTransaction();
//		User u = (User) s.load(User.class, "2");
//		u.setGroup(null);
//		s.delete(u);
		s.createQuery("delete from User u where u.id=2").executeUpdate();
		s.getTransaction().commit();
	}

执行结果

6.4看下testDeleteGroup

@Test
	public void testDeleteGroup() {
		testSaveGroup();
		Session s = sf.getCurrentSession();
		s.beginTransaction();
		Group g = (Group) s.load(Group.class, "1");
//		for(User u:g.getUsers()){
//			u.setGroup(null);
//		}
//		g.setUsers(null);
		s.delete(g);
		s.getTransaction().commit();
	}

运行结果

由于Group和User都设置了cascade,所以在删除Group的同时会级联删除相关的User数据

为了解决这一问题,需要在删除之前,先将二者之间的级联设置为null

注意,只删除一方无效果,需要将双方的关联都去除

6.5只删除1,不删除多

@Test
	public void testDeleteGroup() {
		testSaveGroup();
		Session s = sf.getCurrentSession();
		s.beginTransaction();
		Group g = (Group) s.load(Group.class, "1");
		for(User u:g.getUsers()){
			u.setGroup(null);
		}
		g.setUsers(null);
		s.delete(g);
		s.getTransaction().commit();
	}

运行结果为

可以看到在删除1之前首先解除了多对其的引用

以上即为hibernate的CRUD常见的操作,需要注意cascade和fetch的配置,需要在具体的使用中仔细体会。

时间: 2024-10-18 03:04:09

hibernate的CRUD操作的相关文章

Spring MVC + Hibernate + Maven: Crud操作示例

Alexey是一个在使用Java,TestNG 和Selenium的自动化WEB应用程序中有丰富经验的测试开发者.他如此的喜欢QA以至于在下班后他为初级QA工程师提供培训课程. 在这篇文章中我想介绍一个Spring MVC + Hibernate + Maven例子.这组技术主要涉及一些基础知识,我想在每一个必要的地方详细解释它.本篇话题范围以外的更多资源,我会提供链接方便你阅读.在文章的最后,我将发布一个GitHub的链接. 目标 示例web应用程序是基于Spring MVC, Hiberna

hibernate之CRUD操作

CRUD是指在做计算处理时的增加(Create).读取(Retrieve)(重新得到数据).更新(Update)和删除(Delete)几个单词的首字母简写. 下面列举实例来讲解这几个操作: 实体类: package com.oumyye.model; public class Student { private long id; private String name; private Class c; public long getId() { return id; } public void

java框架篇---hibernate之CRUD操作

CRUD是指在做计算处理时的增加(Create).读取(Retrieve)(重新得到数据).更新(Update)和删除(Delete)几个单词的首字母简写. 下面列举实例来讲解这几个操作: 实体类: package com.oumyye.model; public class Student { private long id; private String name; private Class c; public long getId() { return id; } public void

用dbutils和hibernate分别实现CRUD操作

=====================用dbutils实现CRUD操作======================== 1.bean: Teacher.java package beans; public class Teacher { String id; String tname; String tage; //setter.getter @Override public String toString() { return "Teacher [id=" + id + &quo

Hibernate的CRUD重用性

1.在研究了hibernate框架之后,准备完成一套Hibernate的CRUD操作,并且让其具有高度的重用性.在复杂查询方面,hibernate可谓是各种不方便,因此查询方面,利用java反射做出一套根据对象属性来动态查询数据的小框架. 2.先做出可行的设计图 3.具体的实现过程 1 package com.framework.common.dao; 2 3 import test.framework.common.PageEntity; 4 5 import java.util.List;

Hibernate对象的CRUD操作

1.  Hibernate对象的CRUD操作 1.1.  对象的三种状态 瞬时(Transient) - 由new操作符创建,且尚未与HibernateSession 关联的对象被认定为瞬时(Transient)的.瞬时(Transient)对象不会被持久化到数据库中,也不会被赋予持久化标识(identifier).如果瞬时(Transient)对象在程序中没有被引用,它会被垃圾回收器(garbage collector)销毁.使用Hibernate Session可以将其变为持久(Persis

Hibernate系列(五):利用Hibernate完成简单的CRUD操作

这里利用Hibernate操作数据库完成简单的CRUD操作. 首先,我们需要先写一个javabean: package cn.itcast.domain; import java.util.Date; public class User { private int id; private String name; private Date birthday; public int getId() { return id; } public void setId(int id) { this.id

【SSH三大框架】Hibernate基础第五篇:利用Hibernate完成简单的CRUD操作

这里利用Hibernate操作数据库完成简单的CRUD操作. 首先,我们需要先写一个javabean: package cn.itcast.domain; import java.util.Date; public class User { private int id; private String name; private Date birthday; public int getId() { return id; } public void setId(int id) { this.id

【SSH三大框架】Hibernate基础第五篇:利用Hibernate完毕简单的CRUD操作

这里利用Hibernate操作数据库完毕简单的CRUD操作. 首先.我们须要先写一个javabean: package cn.itcast.domain; import java.util.Date; public class User { private int id; private String name; private Date birthday; public int getId() { return id; } public void setId(int id) { this.id