Hibernate是一个开源的对象关系映射(ORM)框架。对JDBC进行了非常轻量级的对象封装。
将对象和数据库表建立映射关系,Hibernate框架使用在数据持久化层(dao)。
ORM:对象关系映射(英语:Object Relational Mapping)
采用映射元数据(配置文件)来描述对象-关系的映射细节。ORM框架通过配置文件将实体对象和数据库表对应起来。
前提准备:导入jar包
需要的jar包 hibernate路径下下lib/required的所有jar包和jpa目录下的jar包
mysql驱动jar包
第一步:创建实体类
Hibernate要求实体类必须提供一个不带参数的默认构造方法。因为程序运行时,Hibernate会运用java的反射机制,创建实体类的实例。
public class User {
private int id;
private String name;
private String password;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
第二步:创建对应的数据库表
CREATE DATABASE hibernate;
USE hibernate;
CREATE TABLE USER(
id INT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(50),
password VARCHAR(50)
);
第三步:创建Hibernate的配置文件,放在src目录下,文件名为hibernate.cfg.xml
<hibernate-configuration>
<session-factory>
<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driverproperty>//指定数据库的驱动程序
<property name="hibernate.connection.username">rootproperty>//数据库的用户名
<property name="hibernate.connection.password">123456property>//数据库的密码
<property name="hibernate.connection.url">jdbc:mysql://localhost:3306/hibernateproperty>//连接数据库的url
<property name="show_sql">trueproperty>//为true时会在控制台输出sql语句,有利于跟踪hibernate的状态
<property name="format_sql">trueproperty>//会格式化输出sql语句
<property name="hbm2ddl.auto">updateproperty>
<property name="hibernate.connection.autocommit">trueproperty>//自动提交事务
<mapping resource="com/cad/domain/User.hbm.xml"/>//引入映射文件
session-factory>
hibernate-configuration>
第四步:创建对象-关系映射文件
该文件应该和实体类在同一目录下。命名规则为 实体类名.hbm.xml 例如User.hbm.xml
<hibernate-mapping> //根元素
<class name="com.cad.domain.User" table="user"> //指定实体类和对应的数据表
<id name="id" column="id"> //<id>元素设定类中的id和表的主键id的映射
<generator class="native">generator> //<gender>元素指定对象标识符生成器,负责生成唯一id。以后会详细讲
id>
<property name="name" column="name">property> //name是实体类属性的名字,column是数据表中列的名字
<property name="password" column="password">property>
class>
hibernate-mapping>
第五步:调用HibernateAPI操作数据库
public class Demo {
@Test
public void test() {
//读取配置文件
Configuration conf=new Configuration().configure();
//根据配置创建factory
SessionFactory sessionfactory=conf.buildSessionFactory();
//获得操作数据库的session对象
Session session=sessionfactory.openSession();
//创建对象
User u=new User();
u.setName("张三");
u.setPassword("123456");
//将对象保存到数据库
session.save(u);
//关闭资源
session.close();
sessionfactory.close();
}
}
通过上面的小例子,我们大致了解了使用Hibernate的流程,接下来让我们详解Hibernate。
Hibernate从其配置文件中读取和数据库连接有关的信息。Hibernate配置文件有两种形式,XML格式或者java属性文件(properties)格式。
(一)java属性文件的格式创建hibernate的配置文件,默认文件名为hibernate.properties,为键值对的形式,放在src目录下:例如
hibernate.dialect=org.hibernate.dialect.MySQLDialect
hibernate.connection.driver_class=com.mysql.jdbc.Driver
hibernate.connection.url=jdbv:mysql://localhost:3306/hibernate
hibernate.connection.username=root
hibernate.connection.password=123456
hibernate.show_sql=true
hibernate.dialect:指定数据库使用的sql方言。可以根据数据库的不同生成不同的方言,底层是通过调用一个一个类实现的。
hibernate.connection.driver_class:指定数据库的驱动程序
hibernate.connection.url:指定连接数据库的url
hibernate.connection.username:指定连接数据库的用户名
hibernate.connection.password:指定连接数据库的密码
hibernate.show_sql:如果为true,可以在控制台打印sql语句
hbm2ddl.auto:生成表结构的策略配置,配置这个可以通过映射文件和实体类自动生成表结构
有四个值:
update(最常用的取值):如果当前数据库不存在对应的数据表,那么自动创建数据表
如果存在对应的数据表,并且表结构和实体类属性一致,那么不做任何修改
如果存在对应的数据表,但是表结构和实体类属性不一致,那么会新创建与实体类属性对应的列,其他列不变
create(很少使用):无论是否存在对应的数据表,每次启动Hibernate都会重新创建对应的数据表,以前的数据会丢失
create-drop(极少使用):无论是否存在对应的数据表,每次启动Hibernate都会重新创建对应的数据表,每次运行结束删除数据表
validate(很少使用):只校验表结构是否和我们的实体类属性相同,不同就抛异常
(二)使用xml格式的配置文件,默认文件名为hibernate.cfg.xml
<hibernate-configuration>
<session-factory>
<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driverproperty>
<property name="hibernate.connection.username">rootproperty>
<property name="hibernate.connection.password">123456property>
<property name="hibernate.connection.url">jdbc:mysql://localhost:3306/hibernateproperty>
<property name="show_sql">trueproperty>
<property name="format_sql">trueproperty>
<property name="hbm2ddl.auto">updateproperty>
<property name="hibernate.connection.autocommit">trueproperty>
//引入映射文件
<mapping resource="com/cad/domain/User.hbm.xml"/>
session-factory>
hibernate-configuration>
两种方式的区别
如果Hibernate的配置文件为java属性文件,那么必须通过代码来声明需要加载的映射文件
通过Configuration的addClass(实体类名.class)来加载。
配置文件为xml文件时,可以通过元素来指定需要加载的映射文件。
当通过Configuration的默认构造方法创建实例时,会默认查找hibernate.properties文件,如果找到就将配置信息加载到内存中。
默认情况下,hibernate不会加载hibernate.cfg.xml文件,必须通过Configuration的configure()方法来显式加载hibernate.cfg.xml文件
-必须提供无参数的默认构造方法。因为程序运行时,Hibernate会运用java的反射机制,创建实体类的实例。
-所有属性必须提供public访问控制符的set get方法
-属性应尽量使用基本数据类型的包装类型(如Integer)
基本数据类型无法表达null值,所有基本数据类型的默认值都不是null,这样就有很大的缺陷。
例如有一个score属性,表示学生分数,如果为0,那么是表示该学生未参加考试还是说该学生成绩为0呢?
这时候如果用包装类型,就可以使用null来表示空值,学生未参加考试等等。
-不要用final修饰实体(将无法生成代理对象进行优化)
在关系数据库中,通过主键来识别记录并保证记录的唯一性。
主键的要求:不允许为null,不能重复,不能改变
自然主键:在业务中,某个属性符合主键的三个要求,那么该属性可以作为主键。比如人的身份证就可以当作主键
代理主键:增加一个不具备任何意义的字段,通常为ID,来作为主键
在java中,按照内存地址不同区分不同的对象。
在Hibernate中通过对象标识符(OID)来维持java对象和数据库表中对应的记录。
与表的代理主键对应,OID也是整数类型,为了保证OID的唯一性和不可变性,通常由Hibernate或者底层数据库库给OID赋值。
Hiernate采用XML格式的文件来指定对象和关系数据之间的映射。Hibernate通过这个文件来生成各种sql语句。
命名规则为 实体类名.hbm.xml 应该和实体类放在同一目录下。
<hibernate-mapping>
<class name="com.cad.domain.User" table="user">
<id name="id" column="id">
<generator class="native">generator>
id>
<property name="name" column="name">property>
<property name="password" column="password">property>
class>
hibernate-mapping>
Configuration类
Configuration类:用来加载默认文件路径下的配置文件(hibernate.properties)。
调用configure()方法会加载默认文件路径下的xml格式的配置文件(hibernate.cfg.xml)推荐使用。
如果配置文件在不默认文件路径下或者配置文件名不符合默认规则
可以使用
new Configuration().configure(file) 加载指定文件
new Configuration().configure(path) 加载指定路径下的文件
如果使用properties格式的配置文件,可以使用addClass(实体类名.class)方法可以加载映射文件。
SessionFactory对象
SessionFactory对象:
SessionFactory代表数据库存储源。根据Hibernate配置文件创建对应的数据库存储源。
SessionFactory对象创建后,和Configuration对象再无关联。修改Configuration包含的配置文件信息,不会对SessionFactory有任何影响。
获取SessionFactory对象:new Configuration().configure().buildSessionFactory();
对象的缓存很大,就称为重量级对象。SessionFactory存放了Hibernate配置信息,映射元数据信息等。是重量级对象。
Session对象
Session对象:
代表程序和数据库的会话。Session提供了操作数据库的各种方法。是轻量级对象。
获取Session对象
factory.openSession(): 获取新的Session实例。
factory.getCurrentSession():采用该方法创建的Session会取出当前线程中的Session,底层使用ThreadLocal进行存取
save()方法:把Java对象保存到数据库中。
Transaction ts=session.beginTransaction();
User u=new User();
u.setName("赵六");
u.setPassword("123456");
//将对象保存到数据库
session.save(u);
ts.commit();
update()方法:更新数据库的方法
Transaction ts=session.beginTransaction();
//先查出要修改的对象,根据主键值
User user=session.get(User.class, 1);
user.setName("jery");
//将对象更新到数据库,根据OID
session.update(user);
ts.commit();
delete()方法:删除方法
底层根据OID进行删除。有两种方式
(1)
Transaction ts=session.beginTransaction();
User user=session.get(User.class, 1);
//删除指定对象
session.delete(user);
ts.commit();
(2)
Transaction ts=session.beginTransaction();
User user=new User();
user.setId(2);
session.delete(user);
ts.commit();
load()或get()方法:从数据库查找指定对象
session.get(实体类名.class,OID);或session.load(实体类名.class,OID);
load()和get()的区别
我们使用get查询时发现控制台会立马打出查询语句。
使用load查询时控制台不会打印查询语句。
get方法被调用时立刻发送sql语句到数据库进行查询。
load方法被调用时并没有查询数据库,当我们需要使用查询的对象时,才去查询,所以当我们打印对象时,才会在控制台打印sql语句。
get()的原理
程序调用get方法,Hibernate发送sql语句到数据库
数据库返回结果,Hibernate将结果封装成对象,返回对象到程序。
load()的原理
程序调用load方法,Hibernate使用代理技术,创建一个代理对象,属性只有ID值。
然后返回代理对象给程序,我们使用对象时,代理对象调用Hibernate查询数据库,初始化其他属性。
load方法,返回一个代理对象,获取其属性时,会查询数据库,每次访问属性都会查询数据库么?
答:不是。代理对象中有一个标识是否被初始化的boolean类型变量,记录是否被初始化。
查询所有对象的方法
使用HQL语言(后面会详细介绍),HQL语言是面向对象的
Query query=session.createQuery("from User");
第二种方式
Criteria c=session.createCriteria(User.class);
List l=c.list();
第三种方式,使用原生sql语句进行查询
SQLQuery query=session.createSQLQuery("select * from user");
List l=query.list();
Transaction对象
封装了事务的操作。我们做增删改查等操作时,必须开启事务.
因为session是线程不安全的,这样主要是为了线程安全。保证数据的正确性。
开启事务: Transaction ts=session.beginTransaction();
提交事务:ts.commit();
回滚事务:ts.rollback();
当通过getCurrentSession获取当前线程绑定的Session时,事务关闭时,会自动把Session关闭并删除。
Query对象
封装HQL语句的对象。
返回一个对象的方法 query.uniqueResult();
分页相关
query.setFirstResult(index):从第几个取
query.setMaxResults(count):指定取几行记录