1.什么是hibernate框架
Hibernate是一个开放源代码的对象关系映射框架,它对JDBC进行了非常轻量级的对象封装,它将POJO与数据库表建立映射关系,是一个全自动的ORM框架。Hibernate可自动生成SQL语句,自动执行,使得Java程序员可以随心所欲的使用对象编程思维来操纵数据库。
2.hibernate的优缺点?
1.Hibernate优点:
(1)对象/关系数据库映射(Basic O/R Mapping)
它使用时只需要操纵对象,使开发更对象化,抛弃了数据库中心的思想,完全的面向对象思想。
(2)透明持久化(Persistent)
带有持久化状态的、具有业务功能的单线程对象,此对象生存期很短。这些对象可能是普通的JavaBeans/POJO,这个对象没有实现第三方框架或者接口,唯一特殊的是他们正与(仅仅一个)Session相关联。一旦这个Session被关闭,这些对象就会脱离持久化状态,这样就可被应用程序的任何层自由使用。(例如,用作跟表示层打交道的数据传输对象。)
(3)事务Transaction (org.Hibernate.Transaction)
应用程序用来指定原子操作单元范围的对象,它是单线程的,生命周期很短。它通过抽象将应用从底层具体的JDBC、JTA以及CORBA事务隔离开。某些情况下,一个Session之内可能包含多个Transaction对象。尽管是否使用该对象是可选的,但无论是使用底层的API还是使用Transaction对象,事务边界的开启与关闭是必不可少的。
(4)它没有侵入性,即所谓的轻量级框架。
(5)移植性会很好。
(6)缓存机制。提供一级缓存和二级缓存。
(7)简洁的HQL编程。
2.Hibernate缺点:
(1)Hibernate在批量数据处理的时候是有弱势。
(2)针对某一对象(单个对象)简单的查\改\删\增,不是批量修改、删除,适合用Hibernate;而对于批量修改、删除,不适合用Hibernate,这也是OR框架的弱点;要使用数据库的特定优化机制的时候,不适合用Hibernate。
3.jdbc与Hibernate的区别
JDBC与Hibernate在性能上相比,JDBC灵活性有优势。而Hibernate在易学性,易用性上有些优势。当用到很多复杂的多表联查和复杂的数据库操作时,JDBC有优势。
相同点:
◆两者都是JAVA的数据库操作中间件。
◆两者对于数据库进行直接操作的对象都不是线程安全的,都需要及时关闭。
◆两者都可以对数据库的更新操作进行显式的事务处理。
不同点:
◆使用的SQL语言不同:JDBC使用的是基于关系型数据库的标准SQL语言,Hibernate使用的是HQL(Hibernate query language)语言
◆操作的对象不同:JDBC操作的是数据,将数据通过SQL语句直接传送到数据库中执行,Hibernate操作的是持久化对象,由底层持久化对象的数据更新到数据库中。
◆数据状态不同:JDBC操作的数据是“瞬时”的,变量的值无法与数据库中的值保持一致,而Hibernate操作的数据是可持久的,即持久化对象的数据属性的值是可以跟数据库中的值保持一致的。
4. Hiberante工作原理
# 术语解释+ 持久化:把数据(如内存中的对象)保存到可永久保存的存储设备中(如磁盘)
+ ORM:Object Relation Mapping就是对象到关系的映射,把对表的操作变成对持久化对象的操作
5.Hibernate创建过程
##1 pom.xml 导入hibernate依赖包
```xml<!-- Hibernate -->
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>5.1.0.Final</version>
</dependency>
```
##2 核心配置文件hibernate.cfg.xml
```xml<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="hibernate.connection.url">jdbc:mysql://127.0.0.1:3306/scm?useUnicode=true&characterEncoding=utf-8</property>
<property name="hibernate.connection.username">root</property>
<property name="hibernate.connection.password">root123</property>
<property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
<property name="hibernate.show_sql">false</property>
<property name="hibernate.format_sql">true</property>
<mapping resource="com/mipo/domain/Employee.hbm.xml" />
</session-factory>
</hibernate-configuration>
```
##3 映射文件*.hbm.xml
```xml<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="com.mipo.domain.Employee" table="T_EMPLOYEE">
<id name="empId" column="EMP_ID">
<!--
<generator class="native" />
-->
<generator class="identity" />
</id>
<property name="empName" column="EMP_NAME" />
<property name="empSex" column="EMP_SEX" />
<property name="empMemo" column="EMP_MEMO" />
</class>
</hibernate-mapping>
```
##4 编写测试用例
+ 1) 获取SessionFactory```java
public SessionFactory getSessionFactory() {
final StandardServiceRegistry serviceRegistry = new StandardServiceRegistryBuilder().configure().build();
try {
return new MetadataSources(serviceRegistry).buildMetadata().buildSessionFactory();
} catch (Exception e) {
e.printStackTrace();
StandardServiceRegistryBuilder.destroy(serviceRegistry);
}
}
```
##5 编写测试dao
Session session = sessionFactory.openSession();
session.beginTransaction();
Employee employee = (Employee) session.get(Employee.class, 1);
Employee evictEmployee = new Employee();
evictEmployee.setUid(1);
session.evict(employee);// 手工清除一级缓存
// evictEmployee.setEmpId(Integer.valueOf(4));
evictEmployee.setEmpName("刘备");
evictEmployee.setEmpSex("M");
evictEmployee.setEmpMemo("刘大耳朵。。。");
session.update(evictEmployee);
session.getTransaction().commit();
session.close();
}
##6 一对一的关系
<class name="com.mipo.domain.Employee" table="T_EMPLOYEE">
<id name="uid" column="uid">
<generator class="identity" />
</id>
<property name="empName" column="EMP_NAME" />
<property name="empSex" column="EMP_SEX" />
<property name="empMemo" column="EMP_MEMO" />
<!--
属性名 描述
##########################################
name com.mipo.domain.Employee#idCard
lazy 指定加载策略,立即加载还是延迟加载
class 指定name对应数据类型
cascade 级联操作all、save-update、delete、none
-->
<one-to-one name="idCard" lazy="false" class="com.mipo.domain.IDCard" cascade="all" />
</class>
</hibernate-mapping>
private static final long serialVersionUID = -5864118345201555279L;
private Integer uid;
private String empName;
private String empSex;
private String empMemo;
private IDCard idCard;
<hibernate-mapping>
<class name="com.mipo.domain.IDCard" table="T_IDENTITY_CARD">
<id name="uid" column="UID">
<!-- 通过取对应表的主键 -->
<generator class="foreign">
<param name="property">employee</param>
</generator>
</id>
<property name="num" column="NUM"/>
<one-to-one name="employee" class="com.mipo.domain.Employee" cascade="none" />
</class>
</hibernate-mapping>
bean
public class IDCard implements Serializable {
private static final long serialVersionUID = -3343609137822895893L;
private Integer uid;
private String num;
private Employee employee;
不同的关系,级联的属性也不相同
对关联的对象如何级联操作,取值:
"none" :做任何操作都不影响关联对象
"save-update" :级联保存或修改
"delete" :级联删除
"delete-orphan" :级联删除并从缓存中清除关联对象
"all" :级联保存、修改、删除。
##7一对多和多对一的关系
<session-factory>
<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="hibernate.connection.url">jdbc:mysql://127.0.0.1:3306/scm?useUnicode=true&characterEncoding=utf-8</property>
<property name="hibernate.connection.username">root</property>
<property name="hibernate.connection.password">root123</property>
<property name="hibernate.dialect">org.hibernate.dialect.MySQL57InnoDBDialect</property>
<property name="hibernate.show_sql">false</property>
<property name="hibernate.format_sql">true</property>
<mapping resource="com/mipo/domain/Employee.hbm.xml" />
<mapping resource="com/mipo/domain/Department.hbm.xml" />
</session-factory>
</hibernate-configuration>
Hiberante中对象的状态
临时状态:刚创建出来的对象,跟session是没有关系
持久状态:已经存在与数据库中。跟session有关系;
托管状态:曾经跟session有关系,后来跟session脱离关系
Lazy和fetch区别:
Lazy:false【立即检索】:获取一个对象之后,会立即再组装此对象所关联的对象
Lazy:true【延迟加载】:不立即组装和它关联的对象,一对多默认是这种加载策略
预抓取:和立即检索相比,预先抓取可以减少SQL语句的条数,提高查询速度。
创建session工厂
public final class HibernateUtil {
private static final SessionFactory sessionFactory = buildSessionFactory();
private HibernateUtil() {
// do nothing
}
private static SessionFactory buildSessionFactory() {
final StandardServiceRegistry serviceRegistry = new StandardServiceRegistryBuilder().configure().build();
try {
return new MetadataSources(serviceRegistry).buildMetadata().buildSessionFactory();
} catch (Exception e) {
StandardServiceRegistryBuilder.destroy(serviceRegistry);
throw new ExceptionInInitializerError(e);
}
}
public static SessionFactory getSessionFactory() {
return sessionFactory;
}
}
<class name="com.mipo.domain.Department" table="T_DEPARTMENT">
<id name="uid" column="uid" type="integer">
<generator class="identity" />
</id>
<property name="depName" column="DEP_NAME" type="string" />
<property name="depAddress" column="DEP_ADDRESS" type="string" />
<!--
set节点: 指定一对多存放集合
name属性: 指定com.mipo.domain.Department类中employees属性;
cascade属性: 级联操作,操作主表时,是否同时操作从表;
inverse属性: 反转,外键控制权交由对方维护;
lazy属性: 延迟加载,通常用于加载多条数据;
-->
<set name="employees" lazy="true" cascade="save-update" inverse="true">
<!--
column属性:T_EMPLOYEE表关联的外键
-->
<key column="DEPT_ID" />
<!--
one-to-many节点:指定一对多
class属性:指定Department类employees属性的数据类型;
-->
<one-to-many class="com.mipo.domain.Employee" />
</set>
<!--
<list name="listData">
<key column="DEP_ID" />
<list-index column="EMP_ID" base="1" />
<one-to-many class="com.mipo.domain.Employee" />
</list>
<map name="mapData">
<key column="DEP_ID" />
<index column="EMP_ID" type="integer" />
<one-to-many class="com.mipo.domain.Employee" />
</map>
-->
</class>
</hibernate-mapping>
private static final long serialVersionUID = -2222647138773687754L;
private Integer uid;
private String depName;
private String depAddress;
private Set<Employee> employees = new HashSet<Employee>();
<class name="com.mipo.domain.Employee" table="T_EMPLOYEE">
<id name="uid" column="uid" type="integer">
<generator class="identity" />
</id>
<!-- <property name="depId" column="DEP_ID" insert="false" update="false" type="integer" /> -->
<property name="empName" column="EMP_NAME" type="string" />
<property name="empSex" column="EMP_SEX" type="string" />
<property name="empMemo" column="EMP_MEMO" type="string" />
<!--
属性 描述
##############################################
name 指定Employee类中department属性
class 指定Employee类中department属性的数据类型
column 指定T_EMPLOYEE表关联的外键
-->
<many-to-one name="department" class="com.mipo.domain.Department" column="DEPT_ID" cascade="save-update" lazy="proxy"/>
</class>
</hibernate-mapping>
private static final long serialVersionUID = -8483463007573917074L;
private Integer uid;
private String empName;
private String empSex;
private String empMemo;
private Department department;
##8 多对多的关系
Role
<hibernate-mapping><class name="com.mipo.domain.Role" table="T_ROLE">
<id name="uid" column="UID" type="integer">
<generator class="identity" />
</id>
<property name="name" column="NAME" type="string" />
<property name="memo" column="MEMO" type="string" />
<set name="users" table="T_USER_ROLE_REL" cascade="save-update" lazy="true">
<key column="ROLE_ID" />
<many-to-many column="USER_ID" class="com.mipo.domain.User" />
</set>
</class>
</hibernate-mapping>
private static final long serialVersionUID = 267803398483097335L;
private Integer uid;
private String name;
private String memo;
private Set<User> users = new HashSet<User>(0);
<class name="com.mipo.domain.User" table="T_USER">
<id name="uid" column="UID" type="integer">
<generator class="identity" />
</id>
<property name="name" column="NAME" type="string" />
<property name="pwd" column="PWD" type="string" />
<set name="roles" table="T_USER_ROLE_REL" cascade="save-update" lazy="true">
<key column="USER_ID" />
<many-to-many column="ROLE_ID" class="com.mipo.domain.Role" />
</set>
</class>
</hibernate-mapping>
private static final long serialVersionUID = -1287292866725348553L;
private Integer uid;
private String name;
private String pwd;
private Set<Role> roles = new HashSet<Role>(0);
<session-factory>
<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="hibernate.connection.url">jdbc:mysql://127.0.0.1:3306/scm?useUnicode=true&characterEncoding=utf-8</property>
<property name="hibernate.connection.username">root</property>
<property name="hibernate.connection.password">root123</property>
<property name="hibernate.dialect">org.hibernate.dialect.MySQL57InnoDBDialect</property>
<property name="hibernate.show_sql">false</property>
<property name="hibernate.format_sql">true</property>
<mapping resource="com/mipo/domain/User.hbm.xml" />
<mapping resource="com/mipo/domain/Role.hbm.xml" />
</session-factory>
</hibernate-configuration>
@GeneratedValue(strategy = GenerationType.IDENTITY) i d的增长方式
@Column(name = "UID") 对应字段的名字
@Entity
@Table(name = "T_DEPARTMENT")
public class Department implements Serializable {
private static final long serialVersionUID = -2222647138773687754L;
private Integer uid;
private String depName;
private String depAddress;
private Set<Employee> employees = new HashSet<Employee>();
public Department() {
// Auto-generated constructor stub
}
public Department(String depName, String depAddress) {
this.depName = depName;
this.depAddress = depAddress;
}
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "UID")
public Integer getUid() {
return uid;
}
public void setUid(Integer uid) {
this.uid = uid;
}
@Column(name = "DEP_NAME")
public String getDepName() {
return depName;
}
public void setDepName(String depName) {
this.depName = depName;
}
@Column(name = "DEP_ADDRESS")
public String getDepAddress() {
return depAddress;
}
public void setDepAddress(String depAddress) {
this.depAddress = depAddress;
}
/**
* mappedBy: 用于指定在双向关系中两个实体中哪个实体是被关联处理的,在OneToMany中定义。
*
* @return
*/
@OneToMany(fetch = FetchType.LAZY, mappedBy = "department")
@org.hibernate.annotations.Cascade(org.hibernate.annotations.CascadeType.ALL)
public Set<Employee> getEmployees() {
return employees;
}
public void setEmployees(Set<Employee> employees) {
this.employees = employees;
}
@Override
public int hashCode() {
final int prime = 37;
int result = 17;
result = prime * result + ((depAddress == null) ? 0 : depAddress.hashCode());
result = prime * result + ((uid == null) ? 0 : uid.hashCode());
result = prime * result + ((depName == null) ? 0 : depName.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Department other = (Department) obj;
if (depAddress == null && other.depAddress != null)
return false;
else if (!depAddress.equals(other.depAddress))
return false;
if (uid == null && other.uid != null)
return false;
else if (!uid.equals(other.uid))
return false;
if (depName == null && other.depName != null)
return false;
else if (!depName.equals(other.depName))
return false;
return true;
}
@Override
public String toString() {
return "department {\"uid\": " + uid + ", \"depName\": \"" + depName + "\", \"depAddress\": \"" + depAddress + "\"}";
}
}
Hql
Session session = sessionFactory.openSession();
session.beginTransaction();
String hql = "select new Employee(e.empName, e.empSex) from Employee e where e.uid = 1";
Query query = session.createQuery(hql);
@SuppressWarnings("unchecked")
List<Employee> data = query.list();
for (Employee employee : data) {
System.out.println(employee);
}
session.getTransaction().commit();
session.close();
}
sql
public void queryMulEntity() {
Session session = sessionFactory.openSession();
session.beginTransaction();
SQLQuery query = session.createSQLQuery("SELECT T.* FROM T_EMPLOYEE T");
query.addEntity(Employee.class);
// query.addEntity("com.mipo.domain.Employee");
@SuppressWarnings("unchecked")
List<Employee> list = query.list();
for (Employee employee : list) {
System.out.println(employee);
}
session.getTransaction().commit();
session.close();
}
什么是数据缓存
2、不重要、容许出现偶尔并发的数据不会被并发访问的数据参数数据
不适合放入Hibernate二级缓存的数据
2、绝不容许出现并发的数据与其他应用共享的数据
1、首先,hql是面向对象查询的;sql是面向数据库做查询。
2、hql的语法结构:from + 类名+类对象 +where+类对象属性的条件;
sql的语法结构:from +数据库表名+ where +表字段条件
3、新增:hql不需要再用insert语句,只需构造新增对象后调用save()方法
4、修改:hql不需要再用update语句,只需得到修改对象后调用update()方法
5、删除:hql不需要再用delete语句,只需得到要删除的对象后调用delete()方法
6. hql严格区分大小写,sql不区分大小写
3.Hibernate中save、persist和saveOrUpdate这三个方法的不同之处?
4.Hibernate中的SessionFactory有什么作用? SessionFactory是线程安全的吗?
5.Hibernate中的SessionFactory有什么作用? SessionFactory是线程安全的吗?
6.Hibernate中Session的lock()方法有什么作用?
7.Hibernate中二级缓存指的是什么?
8.bernate中的查询缓存指的是什么?
9.为什么在Hibernate的实体类中要提供一个无参数的构造器这一点非常重要?
每个Hibernate实体类必须包含一个 无参数的构造器, 这是因为Hibernate框架要使用
Reflection API,通过调用Class.newInstance()来创建这些实体类的实例。如果在实体
类中找不到无参数的构造器,这个方法就会抛出一个InstantiationException异常。
10.可不可以将Hibernate的实体类定义为final类?
是的,你可以将Hibernate的实体类定义为final类,但这种做法并不好。因为
Hibernate会使用代理模式在延迟关联的情况下提高性能,如果你把实体类定义成final
类之后,因为 Java不允许对final类进行扩展,所以Hibernate就无法再使用代理了,如
此一来就限制了使用可以提升性能的手段。不过,如果你的持久化类实现了一个接口而
且在该接口中声明了所有定义于实体类中的所有public的方法轮到话,你就能够避免出
现前面所说的不利后果。
11.hibernate对象状态?
托管状态:无论对实体类做任何操作度都不会影响数据库的数据(对象不在hibernate 的缓存中)
自由对象和游离对象的区别:
自由对象在数据库中没有数据与之对应
游离对象在数据库中有一条数据与之对应
托管的对象一定是有持久状态转移过来的
调用save(),saveorupdate()可以把临时状态改变为持久状态
event(),clear(),close()可以持久态变为托管状态
update(),saveorupdate()可以把托管状态变为持久态
delete()可以把持久状态变为临时状态
2. load方法加载实体对象的时候,根据映射文件上类级别的lazy属性的配置(默认为
(1)若为true,则首先在Session缓存中查找,看看该id对应的对象 是否 存在,不存在则
这里get和load有两个重要区别: