5. 对象的状态及生命周期及CRUD操作
5.1 对象的状态及生命周期
Transient:瞬时态,session中有,数据库中没有
Persistent:持久态,session中有,数据库中有。
Detached:游离态,session中没有,数据库中有。
5.2 new->save->close->update
@Test
public void testSave() {
Session session = null;
Transaction tx = null;
User user = null;
try {
session = HibernateUtil.getSession();
tx = session.beginTransaction();
// 构造对象--瞬时状态
user = new User();
user.setName("李四");
user.setPwd("222");
// 持久状态,user被session管理
session.save(user);
/*
* 在持久状态下,脏数据检查:当提交事务时或者清理缓存时,发现session中的数据和数据库中的数据不一致时,
* 将session中的数据更新到数据库中
*/
user.setName("刘德华");
// 在保存以后再修改对象将会产生多条sql语句,效率较低,建议在save前修改
session.flush();
tx.commit();
} catch (Exception e) {
e.printStackTrace();
tx.rollback();
} finally {
HibernateUtil.closeSession();
}
// 游离状态
user.setName("梁朝伟");
try {
session = HibernateUtil.getSession();
tx = session.beginTransaction();
// 持久状态
session.update(user);
tx.commit();
} catch (Exception e) {
e.printStackTrace();
tx.rollback();
} finally {
HibernateUtil.closeSession();
}
}
5.3 get/load->clear/evict
get/load的区别:get会立即查询对象,load在使用才去查询,get找不到对象返回null,load找不到对象抛异常。
@Test
public void testGet() {
Session session = null;
Transaction tx = null;
User user = null;
try {
session = HibernateUtil.getSession();
tx = session.beginTransaction();
// get后会变为持久状态
// get方法会立即查询对象:范围从Session,SessionFactory,数据库
// get查询不到对象返回null
user = (User) session.get(User.class, 11);
// System.out.println(user);
// 游离状态下不被session管理 数据库中不会被更改
// session.evict(user);
// session.clear();
// user.setName("郭富城");
tx.commit();
} catch (Exception e) {
e.printStackTrace();
tx.rollback();
} finally {
HibernateUtil.closeSession();
}
}
@Test
public void testLoad() {
Session session = null;
Transaction tx = null;
User user = null;
try {
session = HibernateUtil.getSession();
tx = session.beginTransaction();
// load后会变为持久状态
// load方法不会立即查询对象,到使用的时候才会查询
// loadl当对象不存在会抛异常
user = (User) session.load(User.class, 11);
System.out.println(user);
// 游离状态下不被session管理 数据库中不会被更改
// session.evict(user);
// session.clear();
// user.setName("郭富城");
tx.commit();
} catch (Exception e) {
e.printStackTrace();
tx.rollback();
} finally {
HibernateUtil.closeSession();
}
}
5.4 update:先获取再修改->可以避免异常
@Test
public void testUpdate() {
Session session = null;
Transaction tx = null;
User user = null;
try {
session = HibernateUtil.getSession();
tx = session.beginTransaction();
// 手动构造的瞬时状态的对象也可以修改,但是需要指定所有属性,不建议使用。
// user = new User();
// user.setId(5);
// user.setName("王五");
// 通过从数据库中加载该对象然后再修改 可以进行判断从而避免异常,提高程序的健壮性
user = (User) session.get(User.class, 5);
if(user != null) {
user.setName("老王");
session.update(user);
}
tx.commit();
} catch (Exception e) {
e.printStackTrace();
tx.rollback();
} finally {
HibernateUtil.closeSession();
}
}
5.5 delete:先获取再删除->可以避免异常
@Test
public void testDelete() {
Session session = null;
Transaction tx = null;
User user = null;
try {
session = HibernateUtil.getSession();
tx = session.beginTransaction();
// 手动构造的瞬时状态的对象也可以删除,不建议使用。
// user = new User();
// user.setId(5);
// 通过从数据库中加载该对象然后再修改 可以进行判断从而避免异常,提高程序的健壮性
user = (User) session.get(User.class, 1);
if(user != null) {
session.delete(user);
}
tx.commit();
} catch (Exception e) {
e.printStackTrace();
tx.rollback();
} finally {
HibernateUtil.closeSession();
}
}
6. SchemaExport&组合主键映射
6.1 SchemaExport的使用
@Test
public void testCreateDB() {
Configuration cfg = new Configuration().configure();
SchemaExport se = new SchemaExport(cfg);
// 第一个参数是否生成ddl脚本,第二个参数是否执行到数据库
se.create(true, true);
}
6.2 通过组件来实现组合主键的步骤
- 编写组合主键的类,该类必须实现Serializable接口
public class ScoreId implements Serializable {
private Integer stuId;
private Integer subjectId;
public Integer getStuId() {
return stuId;
}
public void setStuId(Integer stuId) {
this.stuId = stuId;
}
public Integer getSubjectId() {
return subjectId;
}
public void setSubjectId(Integer subjectId) {
this.subjectId = subjectId;
}
}
- 在主类中引用对应的组件
public class Score implements Serializable {
private ScoreId scoreId;
private Integer result;
public ScoreId getScoreId() {
return scoreId;
}
public void setScoreId(ScoreId scoreId) {
this.scoreId = scoreId;
}
public Integer getResult() {
return result;
}
public void setResult(Integer result) {
this.result = result;
}
}
- 编写配置文件
<hibernate-mapping package="com.yxxy.pojo">
<class name="Score">
<!-- 组合主键 -->
<composite-id name="scoreId" class="ScoreId">
<key-property name="stuId"></key-property>
<key-property name="subjectId"></key-property>
</composite-id>
<!-- 实体类的属性 -->
<property name="result"></property>
</class>
</hibernate-mapping>
- 测试
@Test
public void testSave() {
Session session = null;
Transaction tx = null;
try {
session = HibernateUtil.getSession();
tx = session.beginTransaction();
Score score = new Score();
ScoreId sId = new ScoreId();
sId.setStuId(1);
sId.setSubjectId(2);
score.setResult(90);
score.setScoreId(sId);
session.save(score);
tx.commit();
} catch (Exception e) {
e.printStackTrace();
tx.rollback();
} finally {
HibernateUtil.closeSession();
}
}
7. 大对象映射
- 在pojo类中,用Blob类型和Clob类型
public class Student {
private Integer id;
private String name;
private Integer age;
// 存放大数据 最大可存放4G
private Blob image;
private Clob introduce;
}
- 在*.hbm.xml文件中需要指定类型
<hibernate-mapping package="com.yxxy.pojo">
<class name="Student">
<id name="id">
<generator class="native"></generator>
</id>
<!-- 实体类的属性 -->
<property name="name"></property>
<property name="age"></property>
<property name="image" type="java.sql.Blob"></property>
<property name="introduce" type="java.sql.Clob"></property>
</class>
</hibernate-mapping>
- 测试
@Test
public void testSave() {
Session session = null;
Transaction tx = null;
try {
session = HibernateUtil.getSession();
tx = session.beginTransaction();
Student stu = new Student();
stu.setName("张三");
stu.setAge(20);
Blob blob = new SerialBlob("blob".getBytes());
Clob clob = new SerialClob("clob".toCharArray());
stu.setImage(blob);
stu.setIntroduce(clob);
session.save(stu);
tx.commit();
} catch (Exception e) {
e.printStackTrace();
tx.rollback();
} finally {
HibernateUtil.closeSession();
}
}
8. 组件映射
- 编写Teacher类
public class Teacher {
private Integer id;
private String name;
private String sex;
private Address address;
}
- 编写Teacher类的组件Address类
public class Address {
private String add1;
private String add2;
private String add3;
}
- Teacher.hbm.xml映射文件
<hibernate-mapping package="com.yxxy.pojo">
<class name="Teacher">
<id name="id">
<generator class="native"></generator>
</id>
<!-- 实体类的属性 -->
<property name="name"></property>
<property name="sex"></property>
<!-- 组件映射 -->
<component name="address" class="Address">
<property name="add1"></property>
<property name="add2"></property>
<property name="add3"></property>
</component>
</class>
</hibernate-mapping>
- 测试
@Test
public void testSave() {
Session session = null;
Transaction tx = null;
try {
session = HibernateUtil.getSession();
tx = session.beginTransaction();
Teacher teacher = new Teacher();
teacher.setName("高淇");
teacher.setSex("男");
Address address = new Address();
address.setAdd1("西三旗");
address.setAdd2("西直门");
address.setAdd3("北五环");
teacher.setAddress(address);
session.save(teacher);
tx.commit();
} catch (Exception e) {
e.printStackTrace();
tx.rollback();
} finally {
HibernateUtil.closeSession();
}
}
9. 单向多对一的关联映射
- 学生表和年级表
学生表
ID | Name | Age | Grade_ID |
---|---|---|---|
1 | 张三 | 20 | 1 |
2 | 李四 | 30 | 2 |
3 | 王五 | 40 | 1 |
年级表
ID | Name |
---|---|
1 | 初级 |
2 | 中级 |
- Student类和Grade类
public class Student {
private Integer id;
private String name;
private Integer age;
private Grade grade;
}
public class Grade {
private Integer id;
private String name;
}
- 映射文件
Grade.hbm.xml
<hibernate-mapping package="com.yxxy.pojo">
<class name="Grade">
<id name="id">
<generator class="native"></generator>
</id>
<!-- 实体类的属性 -->
<property name="name"></property>
</class>
</hibernate-mapping>
Student.hbm.xml
<hibernate-mapping package="com.yxxy.pojo">
<class name="Student">
<id name="id">
<generator class="native"></generator>
</id>
<!-- 实体类的属性 -->
<property name="name"></property>
<property name="age"></property>
<!--
多对一
name:表示属性名
class:指明属性对应的类
colume:指数据库表中的列名
-->
<many-to-one name="grade" class="Grade" column="grade_id" foreign-key="fk_grade" not-null="true"></many-to-one>
</class>
</hibernate-mapping>
- 测试
@Test
public void testSave() {
Session session = null;
Transaction tx = null;
try {
session = HibernateUtil.getSession();
tx = session.beginTransaction();
Grade grade = new Grade();
grade.setName("基础");
Student stu = new Student();
stu.setName("张三");
stu.setAge(20);
stu.setGrade(grade);
session.save(grade);
session.save(stu);
tx.commit();
} catch (Exception e) {
e.printStackTrace();
tx.rollback();
} finally {
HibernateUtil.closeSession();
}
}
10. 单向一对多的关联映射
- 类Student和Grade类
public class Grade {
private Integer id;
private String name;
private Set<Student> students = new HashSet<>();
}
public class Student {
private Integer id;
private String name;
private Integer age;
}
- 映射文件
Grade.hbm.xml
<hibernate-mapping package="com.yxxy.pojo">
<class name="Grade">
<id name="id">
<generator class="native"></generator>
</id>
<!-- 实体类的属性 -->
<property name="name"></property>
<!-- set是Grade中的集合属性 name属性名称 -->
<set name="students">
<!-- key表示外键 colume外键列名 -->
<key column="grade_id" not-null="true" foreign-key="fk_grade"></key>
<!-- 一对多 类Grade中 students所表示的类型 -->
<one-to-many class="Student"/>
</set>
</class>
</hibernate-mapping>
Student.hbm.xml
<hibernate-mapping package="com.yxxy.pojo">
<class name="Student">
<id name="id">
<generator class="native"></generator>
</id>
<!-- 实体类的属性 -->
<property name="name"></property>
<property name="age"></property>
</class>
</hibernate-mapping>
- 测试
@Test
public void testSave() {
Session session = null;
Transaction tx = null;
try {
session = HibernateUtil.getSession();
tx = session.beginTransaction();
Grade grade = new Grade();
grade.setName("基础");
Student stu = new Student();
stu.setName("张三");
stu.setAge(20);
stu.setGrade(grade);
session.save(grade);
session.save(stu);
tx.commit();
} catch (Exception e) {
e.printStackTrace();
tx.rollback();
} finally {
HibernateUtil.closeSession();
}
}
11. 双向一对多的关联映射
- 类Student和Grade类
public class Grade {
private Integer id;
private String name;
private Set<Student> students = new HashSet<>();
}
public class Student {
private Integer id;
private String name;
private Integer age;
private Grade grade;
}
-
映射文件
Grade.hbm.xml
<hibernate-mapping package="com.yxxy.pojo">
<class name="Grade">
<id name="id">
<generator class="native"></generator>
</id>
<!-- 实体类的属性 -->
<property name="name"></property>
<!-- set是Grade中的集合属性 name属性名称 -->
<set name="students">
<!-- key表示外键 colume外键列名 -->
<key column="grade_id" not-null="true" foreign-key="fk_grade"></key>
<!-- 一对多 类Grade中 students所表示的类型 -->
<one-to-many class="Student"/>
</set>
</class>
</hibernate-mapping>
Student.hbm.xml
<hibernate-mapping package="com.yxxy.pojo">
<class name="Student">
<id name="id">
<generator class="native"></generator>
</id>
<!-- 实体类的属性 -->
<property name="name"></property>
<property name="age"></property>
<!--
多对一
name:表示属性名
class:指明属性对应的类
colume:指数据库表中的列名
-->
<many-to-one name="grade" class="Grade" column="grade_id" foreign-key="fk_grade"></many-to-one>
</class>
</hibernate-mapping>
- 测试
@Test
public void testSaveByOneToMany() {
Session session = null;
Transaction tx = null;
try {
session = HibernateUtil.getSession();
tx = session.beginTransaction();
Student stu = new Student();
stu.setName("张三");
stu.setAge(20);
Grade grade = new Grade();
grade.getStudents().add(stu);
grade.setName("基础");
/**
* 保存数据的顺序是根据外键的配置来决定的
* 如果外键不能为null 先保存一的一端
* 如果外键可以为null 则随意保存,但是会多执行update语句
*/
session.save(grade);
session.save(stu);
tx.commit();
} catch (Exception e) {
e.printStackTrace();
tx.rollback();
} finally {
HibernateUtil.closeSession();
}
}
@Test
public void testSaveByManyToOne() {
Session session = null;
Transaction tx = null;
try {
session = HibernateUtil.getSession();
tx = session.beginTransaction();
Grade grade = new Grade();
grade.setName("基础");
Student stu = new Student();
stu.setName("张三");
stu.setAge(20);
stu.setGrade(grade);
session.save(grade);
session.save(stu);
tx.commit();
} catch (Exception e) {
e.printStackTrace();
tx.rollback();
} finally {
HibernateUtil.closeSession();
}
}
@Test
public void testGet() {
Session session = null;
Transaction tx = null;
try {
session = HibernateUtil.getSession();
tx = session.beginTransaction();
//取数据
Grade grade = (Grade) session.get(Grade.class, 1);
System.out.println("gradeName:" + grade.getName());
System.out.println("grade所对应的多的一端的数据");
Iterator<Student> iter = grade.getStudents().iterator();
for(; iter.hasNext();) {
Student stu = iter.next();
System.out.println("name=" + stu.getName() + " age=" + stu.getAge());
}
System.out.println("=================================");
Student stu = (Student) session.get(Student.class, 1);
System.out.println("name=" + stu.getName() + " age=" + stu.getAge());
System.out.println("student所对应的一端的数据");
System.out.println("gradeName:" + stu.getGrade().getName());
tx.commit();
} catch (Exception e) {
e.printStackTrace();
tx.rollback();
} finally {
HibernateUtil.closeSession();
}
}