Hibernate入门四(主键生产器和对象状态)

主键的产生器

在一个关系数据库中,所有的数据都是存储在表里的,每一个表都有一个主键(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发生再几种情况下:

  1. 调用某些查询的时候
  2. transaction commit的时候
  3. 手动调用flush的时候

七,lock和update区别
update是把一个已经更改过的脱管状态的对象变成持久状态
lock是把一个没有更改过的脱管状态的对象变成持久状态
对应更改一个记录的内容,两个的操作不同:
1. update的操作步骤是:更改脱管的对象->调用update
2. lock的操作步骤是:调用lock把对象从脱管状态变成持久状态–>更改持久状态的对象的内容–>等待flush或者手动flush

副本的概念/缓存的机制

这里写图片描述

提高效率

企业不用nosql的原因:

简单理解:智能分析的时候用nosql,你得有集群,得养人。
nosql免费开源,但是对事务的支持不强。
如果系统的严谨性不是很强,一般情况用关系型数据库就够用了。

为什么初创公司不适合用NoSQL?

  1. NoSQL还不太成熟,一个Bug可能导致重大的损失,在初创公司,更可能是毁灭性的问题。
  2. NoSQL人才不好找
  3. NoSQL技术不成熟,还处于发展阶段,今天用的核心功能可能明天就没了
  4. NoSQL的用法太怪异了,和传统的关系型数据库设计思路冲突
  5. NoSQL周边工具太少,比如客户端库不足,监控运维工具需要自己写

为什么初创公司适合用NoSQL?

  1. NoSQL很酷
  2. NoSQL扩展性好,可以轻松伴随一个新公司的快速业务增长
  3. 很多NoSQL是schema free的,可以应对初创公司的频繁变化
  4. NoSQL提供了一些传统数据库没有的功能,比如Redis灵活的数据结构
  5. NoSQL便宜,绝大多数NoSQL都是开源免费的,你不需要花钱购买

回到咱们的问题:学时成绩不能一个一个改,那怎么办呢,于是我们就涉及到一级缓存的概念。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Go语言(也称为Golang)是由Google开发的一种静态强类型、编译型的编程语言。它旨在成为一门简单、高效、安全和并发的编程语言,特别适用于构建高性能的服务和分布式系统。以下是Go语言的一些主要特点和优势: 简洁性:Go语言的语法简单直观,易于学习和使用。它避免了复杂的语法特性,如继承、重载等,转而采用组合和接口来实现代码的复用和扩展。 高性能:Go语言具有出色的性能,可以媲美C和C++。它使用静态类型系统和编译型语言的优势,能够生成高效的机码。 并发性:Go语言内置了对并发的支持,通过轻量级的goroutine和channel机制,可以轻松实现并发编程。这使得Go语言在构建高性能的服务和分布式系统时具有天然的优势。 安全性:Go语言具有强大的类型系统和内存管理机制,能够减少运行时错误和内存泄漏等问题。它还支持编译时检查,可以在编译阶段就发现潜在的问题。 标准库:Go语言的标准库非常丰富,包含了大量的实用功能和工具,如网络编程、文件操作、加密解密等。这使得开发者可以更加专注于业务逻辑的实现,而无需花费太多时间在底层功能的实现上。 跨平台:Go语言支持多种操作系统和平台,包括Windows、Linux、macOS等。它使用统一的构建系统(如Go Modules),可以轻松地跨平台编译和运行代码。 开源和社区支持:Go语言是开源的,具有庞大的社区支持和丰富的资源。开发者可以通过社区获取帮助、分享经验和学习资料。 总之,Go语言是一种简单、高效、安全、并发的编程语言,特别适用于构建高性能的服务和分布式系统。如果你正在寻找一种易于学习和使用的编程语言,并且需要处理大量的并发请求和数据,那么Go语言可能是一个不错的选择。
Go语言(也称为Golang)是由Google开发的一种静态强类型、编译型的编程语言。它旨在成为一门简单、高效、安全和并发的编程语言,特别适用于构建高性能的服务和分布式系统。以下是Go语言的一些主要特点和优势: 简洁性:Go语言的语法简单直观,易于学习和使用。它避免了复杂的语法特性,如继承、重载等,转而采用组合和接口来实现代码的复用和扩展。 高性能:Go语言具有出色的性能,可以媲美C和C++。它使用静态类型系统和编译型语言的优势,能够生成高效的机码。 并发性:Go语言内置了对并发的支持,通过轻量级的goroutine和channel机制,可以轻松实现并发编程。这使得Go语言在构建高性能的服务和分布式系统时具有天然的优势。 安全性:Go语言具有强大的类型系统和内存管理机制,能够减少运行时错误和内存泄漏等问题。它还支持编译时检查,可以在编译阶段就发现潜在的问题。 标准库:Go语言的标准库非常丰富,包含了大量的实用功能和工具,如网络编程、文件操作、加密解密等。这使得开发者可以更加专注于业务逻辑的实现,而无需花费太多时间在底层功能的实现上。 跨平台:Go语言支持多种操作系统和平台,包括Windows、Linux、macOS等。它使用统一的构建系统(如Go Modules),可以轻松地跨平台编译和运行代码。 开源和社区支持:Go语言是开源的,具有庞大的社区支持和丰富的资源。开发者可以通过社区获取帮助、分享经验和学习资料。 总之,Go语言是一种简单、高效、安全、并发的编程语言,特别适用于构建高性能的服务和分布式系统。如果你正在寻找一种易于学习和使用的编程语言,并且需要处理大量的并发请求和数据,那么Go语言可能是一个不错的选择。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值