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();
}
}
运行结果:Cascade级联保存
如果保存book的时候没有保存user,就会报错,那么使用级联保存可以解决这一问题。
Cascade级联操作:NONE,SAVE_UPDATE,DELETE,ALL
级联保存:我在保存这个对象的时候要不要一起保存一下相关的对象。
配置级联的时候我们只需要考虑该不该删,该删就用ALL,不该删就用SAVE_UPDATE。
测试一下SAVE_UPDATE,在Book类中添加代码:
@Cascade(CascadeType.SAVE_UPDATE)
测试一下ALL,在User类添加代码:
@Cascade(CascadeType.ALL)//删除User的时候级联删除相关的Book
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();
}
}
创建一个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();
}
}
运行结果:
注意:这里删除的仅仅是选书的记录,而不是书本身,因为这本书许多人所共享,不能直接把书删掉,在这里移除的仅仅是里面的一个中间关系,对于这个人来讲,没有这本书了,对于其他人来讲,这本书还在。
---------------------------------------------------------------------------------------------------------------------------------------
总结一下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-----------
一个人可以有很多本书,一本书有很多主人
多对多关系需要使用中间表