自学hibernate第二步(回首掏,详解细节操作,解锁更多基础操作)

pojoName.hbm.xml这里面写的啥?

约束

<!DOCTYPE hibernate-configuration PUBLIC
	"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
	"http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">

约束对于我们程序员来说还是很重要,但是对于最终呈现的效果而言并不重要,但是作为一名优秀的Java开发工程师,最好还是把约束带上,这样可以更早的发现错误并改正

不知道你发现没有(假装是我自己挖的坑)
在这里插入图片描述
没错,它红了,理论上是系统提醒我们,这里的写法是错误的
但是,它并不影响我们的程序运行!
是谁的锅呢?没错,就是约束出了问题
你可能不信,我把约束删除了,又运行了一遍程序,然后,它跑通了!图片为证!(当然这是我做的一个实验为了印证我的猜想,约束仅仅是告诉系统我的标签格式应该是怎样的,并不影响运行效果,实践是检验真理的唯一标准!)
没有约束一样正确执行
这个文件的正确的约束应该在hibernate-core的jar包底下的(最底下)
hibernate-mapping的dtd文件里找到
约束的位置

<!DOCTYPE hibernate-mapping PUBLIC 
    "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
    "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">

一顿操作猛如虎,CV大法之后我们的PojoName.hbm.xml的文件里面的警告和红线全部消灭干净
约束修改之后
然后我们可以安心的进行下一步操作,不用被红线报错和警告所扰了(如果我们还报错,那就是我们真的真的写错了!)

hibernate-mapping标签

这个标签的意思就是hibernate的映射,mapping的中文意思就是“映射”,这个标签里面的内容都是来描述映射的
啥叫映射呢??就是放学回家,各找各妈
hibernate中的映射关系我们可以简单的从一张图看出,还是我们上一步做的项目
映射关系
图中红色箭头的意思是:我就是我,程序中的ID就是数据库中的ID,
图中黑色箭头的意思是:我到家了,程序中的id找到了数据库中的ID
这样,我们用程序操作数据库的时候,hibernate才知道应该生成什么样的SQL语言

hibernate-mapping的标签属性

<hibernate-mapping>标签中有一个标签属性package,(中文意思是“包”)package的值是包的路径,意为这个hibernate-mapping里面的映射关系的pojo类都在这个包里
在我们一般的项目中,数据库里面不会只是一张表,那么多张表,就要建立多个<class>标签,在我们写程序的时候一般都是把pojo写在一个包里,所以为了避免我们写多个<class>中的name属性麻烦,于是我们可以用package这个hibernate-mapping标签属性来简化我们之后的代码
大概呢就是这个样子
package属性
如果有多个表的话,我们是不是就不用在class标签的name属性里写那个又臭又长的路径名了

class标签

在class标签中对应的就是程序中的实体类与数据库一张表的映射关系

class标签属性

name:完整类名,如果hibernate-mapping中没有写package,则必须要写完整的路径(正如第一步所作的那样)
table:数据库表名

id标签

配置主键映射的属性,要注意的是:id标签内的主键字段不要再property中再写一遍(这个坑本人已经踩平,希望我的读者们别再掉进去)

id标签属性

name:实体类中(与数据库表中的主键对应)的属性名
column:表中的主键字段名

generator标签

generator(生产者&发动机&创始者&发生器)这里我个人习惯称之为发生器,根据它的作用,我们专业一些的叫法是主键生成策略,下面是我关于主键生成策略所作的笔记,尽管拿去,一起学习,共同进步!!
generator笔记

property标签

填写除id之外的普通属性映射

property标签属性

name:填写实体类中的属性名

column:填写表中的字段名,如果不写,默认就是与类属性名一致(一般实体类中的属性名和数据库表中的字段名是不同的,因为命名规范不同)大多数时候都是要写上去。

type:(可选)故名思意就是字段属性的意思,
可以写Java属性(java.lang.String)或hibernate属性(java)
或数据库属性(varchar),一般不写这个属性,不写的话hibernate会自动检测你的数据库和程序属性

not-null:配置字段是否不能为空,默认为false(可以为空)

length:配置字段的长度,默认为数据库类型的最大长度(判断长度这种事情最好在前端那里就解决了,严谨一些的公司要求是涉及到数据长度问题,各个环节都要作判断和限制)

hibernate.cfg.xml这里面写的啥?

这是hibernate的主配置文件,里面包含连接数据库、读取映射文件必须填写的配置,以及一些可选的选项来操纵hibernate的工作逻辑

约束

这里的约束跟之前那个映射文件的约束作用一样,就是长的不一样。

hibernate-configuration标签

起一个边界的作用,表明里面写的东西是hibernate的配置

session-factory标签

session factory直译过来意思是“会话工厂”,人家就是要告诉你,这个标签里面是生产会话的地方,什么是会话呢?就是要建立数据库和程序的数据通道,让程序和数据库的数据流通。
那问题来了,会话工厂怎么来生产会话呢?这就需要里面的property标签指出数据库的四要素(driver,url,username,password)、数据库方言(dialect)、操作逻辑(hbm2ddl.auto)、映射文件路径(mapping)以及其他可选操作

property标签

session-factory标签内的property标签主要用于提供生产会话的必要数据和条件也可以将生成的SQL语言输出到控制台

数据库驱动

<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>

数据库url(通过这个url来找到你所要操作的数据库,其中csdn_study是数据库的名字)

<property name="hibernate.connection.url">jdbc:mysql:///csdn_study?useSSL=false</property>

数据库用户名

<property name="hibernate.connection.username">root</property>

数据库密码

<property name="hibernate.connection.password">mypassword</property>

数据库方言(不同数据库的SQL语言有些不同)

<property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>

程序与数据库的映射文件(千万不要把斜杠写成点)

<mapping resource="com/study/pojo/PersonBase.hbm.xml"/>

hibernate生成的SQL语言打印到控制台

<property name="hibernate.show_sql">true</property>

hibernate生成的SQL语言采用标准的格式

<property name="hibernate.format_sql">true</property>

hibernate的操作数据库的逻辑

<property name="hibernate.hbm2bbl.auto">update</property>

关于hibernate操作数据库逻辑的笔记
hibernate.hbm2bbl.auto操作逻辑笔记

PersonControl里面猫腻

主要是hibernate的内置对象以及方法(API)

configuration

加载核心配置文件,调用空参构造来创建hibernate对象,并调用读取配置文件方法configure()

Configuration cfg = new Configuration().configure();

在这里插入图片描述
我们可以看到configure读取配置文件方法里是可以带参数的,我们这里采用的是无参的方法,那么无参的configure方法怎么就能找到我们的配置文件(hibernate.cfg.xml)呢? 阅读hibernate源码你会发现,他这个无参方法中返回的是一个含常量参数的configure方法,而这个常量的值就是
hibernate.cfg.xml,所以这个方法也是官方推荐的,只要配置文件在根目录(src)下而且命名为hibernate.cfg.xml他就能读取到

SessionFactory

根据配置信息,创建sessionFactory对象

//创建一个sessionFactory
		SessionFactory sessionFactory = cfg.buildSessionFactory();

这个是负责保存和使用所有配置信息,消耗资源非常大,sessionFactory属于线程安全的对象设计,所以:要保证在web项目中,session Factory只创建一个(节省资源且安全)

Session

打开session对象

//创建session对象
		Session session = sessionFactory.openSession();

session是hibernate操作数据库的核心对象,表达hibernate框架与数据库连接(会话),session类似于JDBC年代的connection对象,可以完成对数据库进行增删改查。

Transaction

事务类,用于事务处理,简单来说就是,开启事务之后,事务记录session对数据库的操作,Transaction把这些操作打包成事务,如果要数据库保存执行事务结果就调用commit()方法,如果误操作之类的可以调用rollback()让数据库返回事务开启前的样子

//开启事务的方式一(推荐)
Transaction tx = session.beginTransaction();
//开启事务的方式二(忘了它吧)
Transaction transaction = session.getTransaction();
transaction.begin();

我们对数据库的操作就写在开启事务(begin)和提交事务(commit)之间

对数据库的常规操作(详解+拓展)

增(save):

//创建一个实体对象
PersonBase pb = new PersonBase();
//对新创建的对象的属性赋值
pb.setName("墨风拂尘");
pb.setAge(18);
//用session中的save方法保存对象到数据库中(要事务提交后实现)
session.save(pb);

查(get):

PersonBase pb = session.get(PersonBase.class, 4);
System.out.println(pb.toString());

这里get方法的第一个参数是传入实体类的类型(运用了Java反射)第二个参数默认是数据库中的id字段(至于其他字段的查询那是以后要走的路)
我们可以是实体类中重写tostring()方法以观察更明显的效果
执行出来如下
在这里插入图片描述

删(delete)

删除一条信息的逻辑是这样的:首先hibernate从数据库中找到这条数据,然后hibernate调用session(会话)中的delete()方法生成删除这条数据的SQL语句,再交给事务提交,数据库完成删除操作
删除前
在这里插入图片描述
删除后
在这里插入图片描述
我们可以观察到,hibernate生成删除语句时也是默认生成的由id字段(主键)作为限制条件

改(update)

与删除一样的原理,不同的是,拿到数据后去设置目标对象的属性值

PersonBase pb = session.get(PersonBase.class, 3);
pb.setAge(23);
session.update(pb);

执行前
在这里插入图片描述
执行后
在这里插入图片描述
我们并没有更改NAME字段,SQL语句里面还是生成了,这印证了hibernate不在乎对象本身的属性,而在乎对象本身(我不在乎你的好和坏,我只在乎你),是一个单纯的面向对象的框架

最后的收尾工作

在一顿操作的最后,我们需要把我们的操作提交给数据库啊,还有我们从sessionFactory(会话工厂)生产出来的会话还没关上呢,sessionFactory倒是不用关,因为这个东西会伴随hibernate的一生(从启动服务器到关闭服务器)

//提交事务
tx.commit();
//释放资源
session.close();

hibernate工具类的封装

经过之前对hibernate的了解,我们应该可以发现,在使用hibernate框架时有几行固定的代码经常重复使用,俗称‘套路’,所以,我们还是把它封装起来,啥时候用,就啥时候调用它就可以了

封装hibernate工具的步骤和思路

封装前的准备:在pojo(装实体类的包)同级的地方,新建一个包,命名为utils(职业术语叫‘工具包’,中文翻译‘跑龙套’,里面跑的都是套路)
在utils包内新建一个类,命名为HibernateUtils
工程结构如图
项目结构图
墨风拂尘封装的中心思想:注重用户体验(启动时间无所谓,重要的是运行流畅)
首先,生产session的sessionFactory和hibernate框架同生共死,会话工厂是hibernate的唯一,所以用静态变量封装
然后,从读取配置到建设会话工厂,这些代码都是固定的套路,我们用静态代码块封存这些步骤,只要启动服务器,这些代码就会执行(不会重复执行)
然后,解决工具类创建和给出session的问题,个人想法是,这个方法会经常被用到,我们要避免重复的创建工具类对象,所以用public static 来定义方法比较合适,其他包里的程序来调用只需要:HibernateUtils.openSession()就可以拿到session了
HibernateUtils里的代码如下

package com.study.utils;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;

public class HibernateUtils {
	private static SessionFactory sessionFactory;
	
	static{
		Configuration config = new Configuration().configure();
		sessionFactory = config.buildSessionFactory();
	}

	public static Session openSession(){
		 return  sessionFactory.openSession();
	}
	
	//获得线程绑定的session(彩蛋!下一步揭晓)
	public static Session getCurrentSession(){
		return sessionFactory.getCurrentSession();
	}

}

测试
在这里插入图片描述
至此,我们稳健的自学hibernate第二步就走完了!加油!

发布了4 篇原创文章 · 获赞 4 · 访问量 268

猜你喜欢

转载自blog.csdn.net/qq_40604335/article/details/89924605