Hibernate实体关系映射

Hibernate中的实体关系映射
多对一关系
创建一个项目:Hibernate注解-ManyToOne

创建一个User类,继承UUIDEntity。
添加代码:

package demo.entity;
import java.util.List;
import javax.persistence.Entity;
import javax.persistence.Table;

@Entity
@Table(name="hbn_ann_m2o_user")
public class User extends UUIDEntity{
	private String username;
	private String password;
	private int age;
	
	@OneToMany(mappedBy="user")//对方用什么属性维护关系
	private List books;
	
	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;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	public List getBooks() {
		return books;
	}
	public void setBooks(List books) {
		this.books = books;
	}
}

创建一个Book类,继承UUIDEntity。
添加代码:

package demo.entity;
import javax.persistence.Entity;
import javax.persistence.Table;

@Entity
@Table(name="hbn_ann_m2o_book")
public class Book extends UUIDEntity{
	private String name;	//书的名字
	private String author;	//书的作者
	private int pages;		//书的页数
	
	@ManyToOne 				//当前类对应这个属性:多对一
    @JoinColumn(name="user_id")
	private User user;		//书的主人
	
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public String getAuthor() {
		return author;
	}
	public void setAuthor(String author) {
		this.author = author;
	}
	public int getPages() {
		return pages;
	}
	public void setPages(int pages) {
		this.pages = pages;
	}
	public User getUser() {
		return user;
	}
	public void setUser(User user) {
		this.user = user;
	}
}

创建一个Test类,测试一下上述代码。
添加代码:

package demo.entity;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;

public class Test {
	public static void main(String[] args) {
		Configuration cfg = new Configuration().configure();
		SessionFactory fac = cfg.buildSessionFactory();	
		Session session = fac.getCurrentSession();
		session.getTransaction().begin();
		
		Book book1 = new Book();
		book1.setAuthor("无始大帝");
		book1.setName("无始经");
		book1.setPages(999);
		
		Book book2 = new Book();
		book2.setAuthor("西王母");
		book2.setName("西皇经");
		book2.setPages(888);
		
		User a = new User();
		a.setUsername("yefan1");
		a.setPassword("123");
		a.setAge(18);
		
		book1.setUser(a);
		book2.setUser(a);
		
		session.save(a);
		session.save(book1);
		session.save(book2);
		
		session.getTransaction().commit();	
		fac.close();
	}
}

运行结果:
在这里插入图片描述
在这里插入图片描述在这里插入图片描述

创建一个Test2类,再测试一下上述代码。
添加代码:

package demo.entity;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;

public class Test2 {
	public static void main(String[] args) {
		Configuration cfg = new Configuration().configure();
		SessionFactory fac = cfg.buildSessionFactory();
		Session session = fac.getCurrentSession();
		session.getTransaction().begin();
		
		//关联查询
		User user = session.get(User.class,"402881e86a72aeda016a72aedcb50000");
		System.out.println(user.getUsername());
		System.out.println(user.getBooks().size());
		
		Book book = session.get(Book.class,"402881e86a72aeda016a72aedcc30001");
		System.out.println(book.getName());
		System.out.println(book.getUser().getUsername());
		
		session.getTransaction().commit();
		fac.close();
	}
}

运行结果:Hibernate实体关系映射_第1张图片Cascade级联保存
如果保存book的时候没有保存user,就会报错,那么使用级联保存可以解决这一问题。
Cascade级联操作:NONE,SAVE_UPDATE,DELETE,ALL
级联保存:我在保存这个对象的时候要不要一起保存一下相关的对象。
配置级联的时候我们只需要考虑该不该删,该删就用ALL,不该删就用SAVE_UPDATE。

测试一下SAVE_UPDATE,在Book类中添加代码:

@Cascade(CascadeType.SAVE_UPDATE)

Hibernate实体关系映射_第2张图片此时,不保存user也可以。

测试一下ALL,在User类添加代码:

@Cascade(CascadeType.ALL)//删除User的时候级联删除相关的Book

在这里插入图片描述创建一下Test3类,测试一下上述代码:

package demo.entity;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;

public class Test3 {
	public static void main(String[] args) {
		Configuration cfg = new Configuration().configure();
		SessionFactory fac = cfg.buildSessionFactory();
		Session session = fac.getCurrentSession();
		session.getTransaction().begin();
		
		//如果删除的数据有关联关系,删除之前要查询
		User user = session.get(User.class,"402881e86a72aeda016a72aedcb50000");
		session.delete(user);
		
		session.getTransaction().commit();	
		fac.close();
	}
}

运行结果:
在这里插入图片描述
在这里插入图片描述
删除user的时候与user有关的book也会被删除。
注意:如果删除的数据有关联关系,删除之前要查询,否则会产生失去连接的数据(冗余数据)

创建一个Test4类,再测试一下级联保存:
添加代码:

package demo.entity;
import java.util.ArrayList;
import java.util.List;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;

public class Test4 {
	public static void main(String[] args) {
		Configuration cfg = new Configuration().configure();
		SessionFactory fac = cfg.buildSessionFactory();
		Session session = fac.getCurrentSession();
		session.getTransaction().begin();
		
		Book book1 = new Book();
		book1.setAuthor("无始大帝");
		book1.setName("无始经");
		book1.setPages(999);
		
		Book book2 = new Book();
		book2.setAuthor("西王母");
		book2.setName("西皇经");
		book2.setPages(888);
		
		User a = new User();
		a.setUsername("yefan1");
		a.setPassword("123");
		a.setAge(18);
		
		List list = new ArrayList();
		list.add(book1);
		list.add(book2);
		
		a.setBooks(list);
		
		book1.setUser(a);
		book2.setUser(a);
		
		session.save(a);//级联保存-生效
		
		session.getTransaction().commit();
		fac.close();
	}
}

这段代码非常冗长,所以级联保存应该以关系的维护方(多的一方)为主。

---------------------------------------------------------------------------------------------------------------------------------------

一对一关系
OneToOne
主键关联:不同表中的数据,如果ID相同,我们就认为他们是一起的。
唯一外键:可以在A和B任意一方添加外键列。

创建一个项目:Hibernate注解-OneToOne
创建一个User类,添加代码:

package demo.entity;
import java.util.List;
import javax.persistence.Entity;
import javax.persistence.OneToMany;
import javax.persistence.OneToOne;
import javax.persistence.Table;

import org.hibernate.annotations.Cascade;
import org.hibernate.annotations.CascadeType;

@Entity
@Table(name="hbn_ann_o2o_user")
public class User extends UUIDEntity{
	private String username;
	private String password;
	
	@OneToOne(mappedBy="user")	//对方用什么属性维护关系
	@Cascade(CascadeType.SAVE_UPDATE)
	private Weapon wapon;
	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;
	}
	public Weapon getWapon() {
		return wapon;
	}
	public void setWapon(Weapon wapon) {
		this.wapon = wapon;
	}
}

创建一个Weapon类,添加代码:

package demo.entity;
import javax.persistence.Entity;
/**
 * 一个人只能拥有一个武器,一个武器只能被一个人拥有
 */
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.OneToOne;
import javax.persistence.Table;
import org.hibernate.annotations.Cascade;
import org.hibernate.annotations.CascadeType;

@Entity
@Table(name="hbn_ann_o2o_weapon")
public class Weapon extends UUIDEntity{
	private String name;	//武器的名字

	@OneToOne
	@JoinColumn(name="user_id",unique=true)
	@Cascade(CascadeType.SAVE_UPDATE)
	private User user;		//武器的主人

	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public User getUser() {
		return user;
	}
	public void setUser(User user) {
		this.user = user;
	}
}

创建一个Test类,测试一下上述代码。
添加代码:

package demo.entity;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;

public class Test {
	public static void main(String[] args) {
		
		Configuration cfg = new Configuration().configure();
		SessionFactory fac = cfg.buildSessionFactory();
		Session session = fac.getCurrentSession();
		session.getTransaction().begin();
		
		User user = new User();
		user.setUsername("叶凡");
		
		Weapon weapon = new Weapon();
		weapon.setName("天帝鼎");
		
		weapon.setUser(user);
		
		session.save(weapon);
		
		session.getTransaction().commit();
		session.close();
		fac.close();
	}
}

运行结果:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

---------------------------------------------------------------------------------------------------------------------------------------

多对多关系
ManyToMany
一个人可以有很多本书,一本书有很多主人
多对多关系需要使用中间表

创建一个项目:Hibernate注解-ManyToMany
创建一个User类,添加代码:

package demo.entity;
import java.util.ArrayList;
import java.util.List;
import javax.persistence.Entity;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import org.hibernate.annotations.Cascade;
import org.hibernate.annotations.CascadeType;

@Entity
@Table(name="hbn_ann_m2m_user")
public class User extends UUIDEntity{
	private String name;
	
	@ManyToMany
	@Cascade(CascadeType.ALL)
	@JoinTable(name="hbn_ann_m2m_user_book",
		joinColumns= {@JoinColumn(name="user_id")},//连接当前类
		inverseJoinColumns= {@JoinColumn(name="book_id")})//连接当前属性
	private List books = new ArrayList();
	
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public List getBooks() {
		return books;
	}
	public void setBooks(List books) {
		this.books = books;
	}
}

创建一个Book类,添加代码:

package demo.entity;
import java.util.ArrayList;
import java.util.List;
import javax.persistence.Entity;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
import org.hibernate.annotations.Cascade;
import org.hibernate.annotations.CascadeType;

@Entity
@Table(name="hbn_ann_m2m_book")
public class Book extends UUIDEntity{
	private String name;

	@ManyToMany
	@Cascade(CascadeType.ALL)
	@JoinTable(name="hbn_ann_m2m_user_book",
		joinColumns= {@JoinColumn(name="book_id")},
		inverseJoinColumns= {@JoinColumn(name="user_id")})
	private List users = new ArrayList();

	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public List getUsers() {
		return users;
	}
	public void setUsers(List users) {
		this.users = users;
	}
}

创建一个Test类,测试一下上述代码。
添加代码:

package demo.entity;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;

public class Test {
	public static void main(String[] args) {
		
		Configuration cfg = new Configuration().configure();
		SessionFactory fac = cfg.buildSessionFactory();
		Session session = fac.getCurrentSession();
		session.getTransaction().begin();
		
		User u1 = new User();
		u1.setName("叶凡");
		
		User u2 = new User();
		u2.setName("姬紫月");
		
		Book b1 = new Book();
		b1.setName("九秘");
		
		Book b2 = new Book();
		b2.setName("大虚空术");
		
		u1.getBooks().add(b1);
		
		u2.getBooks().add(b1);
		u2.getBooks().add(b2);		
		
		session.save(u1);
		session.save(u2);
		
		session.getTransaction().commit();
		session.close();
		fac.close();
	}
}

运行结果:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
Hibernate实体关系映射_第3张图片

创建一个Test2类,再测试一下上述代码。
添加代码:

package demo.entity;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;

public class Test2 {
	public static void main(String[] args) {
		
		Configuration cfg = new Configuration().configure();
		SessionFactory fac = cfg.buildSessionFactory();
		
		Session session = fac.getCurrentSession();
		session.getTransaction().begin();
		
		User user = session.get(User.class,"402881e86a772512016a772514be0002");
		System.out.println(user.getName());
		for(Book b : user.getBooks())
		{
			System.out.println(b.getName());
		}
		
		user.getBooks().remove(0);
		session.update(user);
		
		session.getTransaction().commit();
		session.close();
		fac.close();
	}
}

运行结果:
Hibernate实体关系映射_第4张图片在这里插入图片描述
注意:这里删除的仅仅是选书的记录,而不是书本身,因为这本书许多人所共享,不能直接把书删掉,在这里移除的仅仅是里面的一个中间关系,对于这个人来讲,没有这本书了,对于其他人来讲,这本书还在。

---------------------------------------------------------------------------------------------------------------------------------------

总结一下hibernate5:
Hibernate5是一个全自动持久化框架,
框架:可复用的程序集,
集合框架:List、Set、Map、迭代器。
ORM框架 - 对象关系映射
哪个类对应哪个表,哪些属性对应哪些字段
使用Hibernate可以非常快速的进行增删改查
连接数据库依然还是依靠JDBC,所有JDBC代码都已经在Hibernate底层写好,我们是不需要接触JDBC的。
学习框架目的:提高开发效率,该关注的就是如何使用,目的很简单,就是做出功能。
Hibernate方言:根据不同的方言生成不同的SQL语句,以适应各种数据库
org.hibernate.dialect.MySQL5Dialect

session.getTransaction().begin();//启动事务
session.getTransaction().commit();//提交事务
session.getTransaction().rollback();//回滚事务(滚回到begin的位置)

稳妥的修改:先查询再修改(查询,改值,更新)
User user = session.get(User.class, 60);

OpenSession 打开新的Session
GetCurrentSession 获取最近的Session,我们需要在配置文件中描述何为最近
GetCurrentSession()会获取最近的CurrentSession,如果没有就建一个。
OpenSession在查询的时候可以不用事务,用过之后必须关闭
CurrentSession必须使用事务,使用之后不用关闭
无论什么Session,无论增删改查,都加事务就肯定没错。

Cascade 级联操作:NONE,SAVE_UPDATE,DELETE,ALL
级联保存:我在保存这个对象的时候要不要一起保存一下相关的对象
配置级联的时候我们只需要考虑该不该删,该删就用ALL,不该删就用SAVE_UPDATE
失去连接的数据,也叫冗余数据

-----------OneToOne-----------
主键关联:不同表中的数据,如果ID相同,我们就认为他们是一起的
唯一外键:可以在A和B任意一方添加外键列

-----------ManyToMany-----------
一个人可以有很多本书,一本书有很多主人
多对多关系需要使用中间表

你可能感兴趣的:(Java,Web)