主键的产生器
在一个关系数据库中,所有的数据都是存储在表里的,每一个表都有一个主键(Primary Key)。对大多数的用户输入数据来讲,主键需要由系统以序列号的方式产生,而不是由操作人员给出,在hibernate中:
incretment
先找到主键的最大值,在最大值的基础之加1,要求主键必须是数字assigned
主键必须在程序中手动设置(一般测试用)identity
主键的生成策略支持主键的值的自动增长,但是该表本身没有这样的机制
主键必须是数字 效率要比icrement高,不用找到最大值了,但是id值不连续。
现在介绍一个靠谱的!!是比较常用的方法!
uuid
string 类型的 pid
数据库也是varchar pid
uuid的字符串是由hibernate内部产生的
要求:必须是字符串类型
native 自动生成策略(了解 不用)
对象状态
hibernate对于对象的保存有很多方法,而对象就存在着很多种状态,假设数据库中有张表,记录成绩字段,我想改一下每个人的成绩,要是用hibernate做,你得先查到班级 ,再把每个人查出来,改变每个人的属性,现在就有问题了,100个人,每个人改了成绩都得给数据库进行交互,是不是很慢啊!!为了解决上述问题,我们要先学习对象的状态!!
1.Person person=new Person();
2.person.setName();
3.session.save();
4.transcation.commit();
5.session.close();
对象的状态转化图:
脱离/游离:就是脱离了hibernate的管理
- save方法:该方法可以把游离状态转化为持久化状态
- get方法:该方法是个持久化方法 直接从数据库中读取数据
- update方法:该方法可以讲一个对象变成持久化状态,如果已经是一个持久化状态(例如get到了一个person),是不需要写update语句的,所以不写也可以。
- evict方法:可以将某个持久化对象变成游离态对象,不行啊,你得管我,然后你只需执行update方法就OK了。
- clear方法:该方法将hibernate中所有的持久化对象变成游离态对象。
- flush方法:在hibernate内部,会检查所有的持久化对象,或者说持久化对象是由临时状态转化过来的情况,则发出insert语句
如果持久化对象是由get等方法得到的,再查看一下副本,如果副本对照一样,则什么都不做,如果跟副本不一样,则发出update语句。
解释一下:
执行到这一句的时候:
Person person2=(Person)session.get(Person.class,1L);
控制台输出:
Hibernate:select max(pid) from Person
因为主键的生成机制是increment所以,我要讲主键的最大值找出来。
当执行到:
transation.commit()
控制台输出:
那么到底是什么时候发出的语句呢?实际并不是在事务提交的时候,实际上在提交之前执行了一个session.flush()操作。
我们去看源代码:
提示:如果transaction.commit()之前的代码由session.flush(),则提交事务的时候不再flush,没有必须得执行session.flush()
我们就想,它到底做了什么事情?他会在hibernate
package com.itheima12.hibernate.state;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.junit.Test;
import com.itheima12.hibernate.domain.Person;
import com.itheima12.hibernate.utils.HibernateUtils;
/**
* 对象的状态
*
*/
public class StateTest {
/**
* 把一个对象的状态从临时状态转化成持久化状态
*/
@Test
public void testSave(){
SessionFactory sessionFactory = HibernateUtils.sessionFactory;
Session session = sessionFactory.openSession();
Transaction transaction = session.beginTransaction();
Person person = new Person();
person.setName("aaa");
session.save(person);
transaction.commit();
session.close();
}
@Test
public void testGet(){
SessionFactory sessionFactory = HibernateUtils.sessionFactory;
Session session = sessionFactory.openSession();
Person person = (Person)session.get(Person.class, 1L);//持久化状态
session.close();
}
@Test
public void testUpdate(){
SessionFactory sessionFactory = HibernateUtils.sessionFactory;
Session session = sessionFactory.openSession();
Transaction transaction = session.beginTransaction();
Person person = (Person)session.get(Person.class, 1L);//持久化状态
person.setDescription("111");
//session.update(person);//update方法就是把一个对象的状态变成持久化状态,person对象已经是持久化状态了,所以这行代码不需要写
transaction.commit();
session.close();
}
/**
* evict方法使得某一个对象变成脱管状态了
*/
@Test
public void testEvict(){
SessionFactory sessionFactory = HibernateUtils.sessionFactory;
Session session = sessionFactory.openSession();
Transaction transaction = session.beginTransaction();
Person person = (Person)session.get(Person.class, 1L);//持久化状态
person.setDescription("111");
session.evict(person);//该方法可以把一个持久化状态变成脱管状态
session.update(person);//由脱管状态的对象变成持久化状态
transaction.commit();
session.close();
}
@Test
public void testClear(){
SessionFactory sessionFactory = HibernateUtils.sessionFactory;
Session session = sessionFactory.openSession();
Transaction transaction = session.beginTransaction();
Person person = (Person)session.get(Person.class, 1L);//持久化状态
person.setDescription("111");
Person person2 = new Person();
person2.setName("88");
session.save(person2);//person2是一个持久化状态的对象
session.clear();//把hibernate里面的所有的对象都变成脱管状态的对象
transaction.commit();
session.close();
}
}
一、预备知识:
hibernate的对象有三种状态
- transient:瞬态或者自由态
- persistent:持久化状态
- detached:脱管状态或者游离态
游离状态的实例可以通过调用save()、persist()或者saveOrUpdate()方法进行持久化。
持久化实例可以通过调用 delete()变成脱管状态。通过get()或load()方法得到的实例都是持久化状态的。
脱管状态的实例可以通过调用 update()、0saveOrUpdate()、lock()或者replicate()进行持久化。
save()和persist()将会引发SQL的INSERT,delete()会引发SQLDELETE,
而update()或merge()会引发SQLUPDATE。对持久化(persistent)实例的修改在刷新提交的时候会被检测到,
它也会引起SQLUPDATE。saveOrUpdate()或者replicate()会引发SQLINSERT或者UPDATE
二、save 和update区别
- save的作用是把一个新的对象保存
- update是把一个脱管状态的对象保存
三,update 和saveOrUpdate区别
saveOrUpdate基本上就是save和update的合体版本
通常下面的场景会使用update()或saveOrUpdate():
- 程序在第一个session中加载对象
- 该对象被传递到表现层
- 对象发生了一些改动
- 该对象被返回到业务逻辑层
- 程序序调用第二个session的update()方法持久这些改动
saveOrUpdate()做下面的事:
如果对象已经在本session中持久化了,不做任何事
如果另一个与本session关联的对象拥有相同的持久化标识(identifier),抛出一个异常
如果对象没有持久化标识(identifier)属性,对其调用save()
如果对象的持久标识(identifier)表明其是一个新实例化的对象,对其调用save()
如果对象是附带版本信息的(通过或) 并且版本属性的值表明其是一个新实例化的对象,save()它。
否则update() 这个对象。
四,persist和save区别
简单翻译一下上边的句子的主要内容:
1,persist把一个瞬态的实例持久化,但是并”不保证”标识符被立刻填入到持久化实例中,标识符的填入可能被推迟
到flush的时间。
2,persist”保证”,当它在一个transaction外部被调用的时候并不触发一个Sql Insert,这个功能是很有用的,
当我们通过继承Session/persistence context来封装一个长会话流程的时候,一个persist这样的函数是需要的。
3,save”不保证”第2条,它要返回标识符,所以它会立即执行Sql insert,不管是不是在transaction内部还是外部
课堂记录:
- persist:不会立刻往数据库中存 同一个对象会有两个持久化对象 最好不要设置id
- save:立刻将游离态对象 持久化 写了id没有用
五,saveOrUpdateCopy,merge和update区别
首先说明merge是用来代替saveOrUpdateCopy的,然后比较update和merge
update的作用上边说了,这里说一下merge的
如果session中存在相同持久化标识(identifier)的实例,用用户给出的对象的状态覆盖旧有的持久实例
如果session没有相应的持久实例,则尝试从数据库中加载,或创建新的持久化实例,最后返回该持久实例
用户给出的这个对象没有被关联到session上,它依旧是脱管的
重点是最后一句:
当我们使用update的时候,执行完成后,我们提供的对象A的状态变成持久化状态
但当我们使用merge的时候,执行完成,我们提供的对象A还是脱管状态,hibernate或者new了一个B,或者检索到
一个持久对象B,并把我们提供的对象A的所有的值拷贝到这个B,执行完成后B是持久状态,而我们提供的A还是托管状态
六,flush和update区别
这两个的区别好理解
update操作的是在脱管状态的对象
而flush是操作的在持久状态的对象。
默认情况下,一个持久状态的对象是不需要update的,只要你更改了对象的值,等待hibernate flush就自动
保存到数据库了。hibernate flush发生再几种情况下:
- 调用某些查询的时候
- transaction commit的时候
- 手动调用flush的时候
七,lock和update区别
update是把一个已经更改过的脱管状态的对象变成持久状态
lock是把一个没有更改过的脱管状态的对象变成持久状态
对应更改一个记录的内容,两个的操作不同:
1. update的操作步骤是:更改脱管的对象->调用update
2. lock的操作步骤是:调用lock把对象从脱管状态变成持久状态–>更改持久状态的对象的内容–>等待flush或者手动flush
副本的概念/缓存的机制
提高效率
企业不用nosql的原因:
简单理解:智能分析的时候用nosql,你得有集群,得养人。
nosql免费开源,但是对事务的支持不强。
如果系统的严谨性不是很强,一般情况用关系型数据库就够用了。
为什么初创公司不适合用NoSQL?
- NoSQL还不太成熟,一个Bug可能导致重大的损失,在初创公司,更可能是毁灭性的问题。
- NoSQL人才不好找
- NoSQL技术不成熟,还处于发展阶段,今天用的核心功能可能明天就没了
- NoSQL的用法太怪异了,和传统的关系型数据库设计思路冲突
- NoSQL周边工具太少,比如客户端库不足,监控运维工具需要自己写
为什么初创公司适合用NoSQL?
- NoSQL很酷
- NoSQL扩展性好,可以轻松伴随一个新公司的快速业务增长
- 很多NoSQL是schema free的,可以应对初创公司的频繁变化
- NoSQL提供了一些传统数据库没有的功能,比如Redis灵活的数据结构
- NoSQL便宜,绝大多数NoSQL都是开源免费的,你不需要花钱购买
回到咱们的问题:学时成绩不能一个一个改,那怎么办呢,于是我们就涉及到一级缓存的概念。