Hibernate学习笔记-操作部分
教程来自:https://how2j.cn/
- 使用JDBC做数据库相关功能开发会做很多重复性的工作,比如创建连接,关闭连接,把字段逐一映射到属性中。
Hibernate把这一切都封装起来了,使得数据库访问变得轻松而简单,代码也更加容易维护。
文章目录
一、Hibernate操作
1. 插入
hibernate的基本步骤是:
- 获取SessionFactory
- 通过SessionFactory 获取一个Session
- 在Session基础上开启一个事务
- 通过调用Session的save方法把对象保存到数据库
- 提交事务
- 关闭Session
- 关闭SessionFactory
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import bean.Person;
public class testHibernate {
public static void main(String[] args) {
SessionFactory sf = new Configuration().configure().buildSessionFactory();
Session s = sf.openSession();
s.beginTransaction();
Person p = new Person();
p.setName("郭");
p.setAge(70);
s.save(p);
s.getTransaction().commit();
s.close();
sf.close();
}
}
2. 获取
Person pGet = (Person) s.get(Person.class, 355);
获取与插入都需要先使用Session开启事务,使用id获取需要知道id,并且需要类对象,获取后需要转型为对应的类。
3. 删除
Person pGet = (Person) s.get(Person.class, 355);
s.delete(pGet);
删除需要先获取id对应的对象。
4. 更新
Person pGet2 = (Person) s.get(Person.class, 532);
pGet2.setName("hahaha");
s.update(pGet);
5. hql查询
String name = "guo";
Query q = s.createQuery("from Person p where p.name like ?0");
q.setParameter(0, "%" + name + "%");
List<Person> ps = q.list();
查询使用HQL语句,这里进行模糊查询,可以看到查询语句中用的不是表名person而是类名称Person,?0表示插入地点,setParameter函数类似ps.setString。Query对象有list()函数可以返回模糊查询结果列表。
6. criteria查询
暂时没搞懂
7. sql查询
String sql = "select * from person p where p.name like '%" + name + "%'";
Query sqlq = s.createSQLQuery(sql);
List<Object[]> pl = sqlq.list();
for (Object[] os : pl) {
for (Object o : os) {
System.out.print(o + "\t");
}
System.out.println();
}
结果:
二、Hibernate关系
实体类对象在Hibernate中有3种状态
分别是瞬时,持久和脱管
瞬时 指的是没有和hibernate发生任何关系,在数据库中也没有对应的记录,一旦JVM结束,这个对象也就消失了
持久 指得是一个对象和hibernate发生联系,有对应的session,并且在数据库中有对应的一条记录
脱管 指的是一个对象虽然在数据库中有对应的一条记录,但是它所对应的session已经关闭了
p.setName("郭");
//此时为瞬时状态
s.save(p);
//此时为持久状态
s.getTransaction().commit();
s.close();
//此时为脱管状态
1. 多对一
准备Category类:
package bean;
public class Category {
private int id;
private String name;
public int getId() {
return this.id;
}
public void setId(int id) {
this.id = id;
}
public String getname() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
}
准备Category.hbm.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="bean">
<class name="Category" table="category_">
<id name="id" column="id">
<generator class="native">
</generator>
</id>
<property name="name" />
</class>
</hibernate-mapping>
这里会自动创建category_表,但必须在hibernate.cfg.xml中添加:
<property name="dialect">org.hibernate.dialect.MySQL5Dialect</property>
表示使用MySQL55Dialect方言,这样才能自动创建表,并且添加外键的表与外键所在表的字符编码形式应该一样,比如都为utf-8。
为Person类添加Category属性
private Category category;
public Category getCategory() {
return this.category;
}
public void setCategory(Category category) {
this.category = category;
}
在Product.hbm.xml中设置Category 多对一关系映射
<many-to-one name="category" class="Category" column="cid"/>
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="bean">
<class name="Person" table="person">
<id name="id" column="id">
<generator class="native">
</generator>
</id>
<property name="name" />
<property name="age" />
<property name="IQ" />
<property name="energy" />
<many-to-one name="category" class="Category" column="cid"/>
</class>
</hibernate-mapping>
这里在运行时会自动在person表内创建cid列
2. 一对多
一对多的意思就是一个category对应多个person
在Category类里添加Set<Person>集合属性persons
private Set<Person> persons;
public Set<Person> getPersons() {
return this.persons;
}
public void setPersons(Set<Person> persons) {
this.persons = persons;
}
在Category.hbm.xml中添加one-to-many映射
<set name="persons" lazy="false">
<key column="cid" not-null="false"/>
<one-to-many class="Person"/>
</set>
<set 用于设置一对多(多对多也是他)关系,也可以用list,设置稍复杂点,这里使用简单的set来入门。
name=“products” 对应 Category类中的persons属性
lazy=“false” 表示不使用延迟加载。关于延迟加载,请参考关系的延迟加载
<key column=“cid” not-null=“false” /> 表示外键是cid,可以为空
<one-to-many class=“Product” /> 表示一对多所对应的类是Product
测试一对多关系:
package test;
import java.util.Set;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import bean.Category;
import bean.Person;
public class testcategory {
public static void main(String[] args) {
SessionFactory sf = new Configuration().configure().buildSessionFactory();
Session s = sf.openSession();
s.beginTransaction();
// Category c = new Category();
// c.setName("c1");
// s.save(c);
//
// Person p = (Person) s.get(Person.class, 400);
// p.setCategory(c);
// s.update(p);
Category c = (Category) s.get(Category.class, 2);
Set<Person> ps = c.getPersons();
for (Person p : ps) {
System.out.println(p);
}
s.getTransaction().commit();
s.close();
sf.close();
}
}
测试结果:
3.多对多
测试多对多关系
多对多关系相当于一个人可以在各个学校中读小学、初中、高中,每所学校也是各个人的母校,即多对多的关系。many-to-many
要实现多对多关系,必须有一张中间表 person_school 用于维护 Person和School之间的关系
下面是School类,包含name、id、Person集合
package bean;
import java.util.Set;
public class School {
private int id;
private String name;
private Set<Person> persons;
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
public void setId(int id) {
this.id = id;
}
public int getId() {
return this.id;
}
public Set<Person> getPersons() {
return this.persons;
}
public void setPersons(Set<Person> persons) {
this.persons = persons;
}
}
下面是Person类,包含各个属性以及一个School集合
package bean;
import java.util.Set;
public class Person {
private String name;
private int age;
private int IQ;
private int energy;
private int id;
private Category category;
private Set<School> schools;
static String copyright;
// 使用static修饰代码块时,类对象被JVM被加载时就会执行,
//且只会加载一次。不加static则会在每次实例化时执行
static {
System.out.println("Person类对象初始化 copyright by Arlen");
copyright = "由Arlen所有权";
}
public Person() {
}
// 增加一个初始化name的构造方法
public Person(String name) {
this.name = name;
}
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public Person(String name, int age, int iq) {
this.name = name;
this.age = age;
this.IQ = iq;
}
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
public int getIQ() {
return this.IQ;
}
public void setIQ(int iq) {
this.IQ = iq;
}
public void setId(int id) {
this.id = id;
}
public int getId() {
return this.id;
}
public int getAge() {
return this.age;
}
public void setAge(int age) {
this.age = age;
}
public int getEnergy() {
return this.energy;
}
public void setEnergy(int energy) {
this.energy = energy;
}
public Category getCategory() {
return this.category;
}
public void setCategory(Category category) {
this.category = category;
}
public Set<School> getSchools() {
return this.schools;
}
public void setSchools(Set<School> schools) {
this.schools = schools;
}
添加School.hbm.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="bean">
<class name="School" table="school">
<id name="id" column="id">
<generator class="native">
</generator>
</id>
<property name="name" />
<set name="persons" table="person_school" lazy="false">
<key column="sid"/>
<many-to-many column="pid" class="Person"/>
</set>
</class>
</hibernate-mapping>
<set>段设置了映射关系,name属性表示School里的persons集合,table属性表示中间表,lazy表示懒加载。
<key column>设置为’sid’,表示school的主键’id’与中间表中’sid’外键关联。
<many-to-many>段column设置为’pid’,中间表中表示Person的主键’id’与中间表的’pid’外键关联。
在Person.hbm.xml中添加多对多映射
<set name="schools" table="person_school" lazy="false">
<key column="pid"/>
<many-to-many column="sid" class="School"/>
</set>
测试中间表
package test;
import java.util.HashSet;
import java.util.Set;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import bean.Person;
import bean.School;
public class testManyToMany_School {
public static void main(String[] args) {
SessionFactory sf = new Configuration().configure().buildSessionFactory();
Session s = sf.openSession();
s.beginTransaction();
// 增加3个人物
Set<Person> persons = new HashSet();
for (int i = 0; i < 3; i++) {
Person p = new Person();
p.setName("user" + i);
persons.add(p);
s.save(p);
}
// 学校1是人物1、2、3的母校
//School s1 = new School();
//s1.setName("HUST");
//s.save(s1);
School s2 = (School) s.get(School.class, 1);
s2.setPersons(persons);
s.save(s2);
s.getTransaction().commit();
s.close();
sf.close();
}
}
console结果
mysql结果