您的位置:首页 > 其它

Hibernate学习小结

2017-07-29 20:45 447 查看

hibernate学习小结

<----------------------------------------------------->

hibernate的持久化

1.狭义的:数据从不能断电的设备保存到能断电的设备上

2.广义上的:指的是和数据库相关的操作,增删改查,加载;加载:指的是根据OID查询数据库中的一条

具体的记录

OID:Object ID,特指java对象中与数据库表的主键相对应的一个属性;即表的id与javabean中表的id

属性一致

<--------------------------------------------------------->

hibernate的搭建环境

1.导入jar包(可以利用maven的依赖,网上下载),数据库驱动(jar包maven依赖)

2.创建hibernate自身的配置文件:hibernate.cfg.xml(文件名字固定,普通项目放在src下。maven项

目放在src/main/resources)

//头部文件

<!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://localhost:3306/20170610</property>

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

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

  <!-- 在控制台中打印出sql语句 -->

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

         <!-- 映射关系。资源的值是java下的映射表的对应路径-->

  <mapping  resource="com/qf/User.hbm.xml" />

 </session-factory>

</hibernate-configuration>

3.创建持久化的类对应的关系映射文件:(pojo类,domain,entity,beans,数据模型类)

放在src下或者maven项目的src/main/java下

要求:[1]有无参构造函数。[2]有OID属性;[3]有getter,setter方法;[4]非final类

4.创建持久化类对应的关系映射文件:Xxxx.hbm.xml(固定格式,与实体类放在一起,同一包下)

//头部文件:同hibernate.cfg.xml头部一样

<hibernate-mapping>

 <class name="实体类的全类名"  table="数据库的表名">

  <id name="id" type="int">

   <generator class="native"></generator>//class中有多个可选择值

  </id>

  <!--接下来是实体类的除了id之外的所有属性-->

  <property name="name" type="java.lang.String">

   <column name="NAME" />

  </property>

 </class>

</hibernate-mapping>

5.Hibernate中重要的API(hibernate4以后版本)

  5.1.Configuration:负责管理hibernate的配置信息。

  hibernate.cfg.xml文件中的信息:数据库URL地址、用户名、密码、jdbc驱动、数据库连接池的桉

树等。

  Xxxx.hbm.xml文件中的信息:持久化类与数据库表之间的对应关系。

  5.2.Transaction代表一次数据库事务。

  hibernate主张把所有持久化操作都纳入到事务中,哪怕仅仅只是只读操作

  5.3.Session代表hibernate应用程序和数据库之间的一次会话。

  作用相当于JDBC中的Connection,其中封装了一系列的操作方法,并包含缓存功能

  5.4.SessionFactory用于创建Session对象的工厂

  SessionFactory对象一旦构造完毕,即被赋予特定的配置信息,构造SessionFactory很消耗资源,

一般情况下一个应用只初始化一个SessionFactory对象;在hibernate4新增了一个ServiceRegister接

口,所有基于hibernate的配置或者服务都必须统一向这个SessionFactory注册后才能生效。

  创建SessionFactory的步骤:创建Configuration对象;在ServiceRegister对象中注册配置信息;

通过Configuration对象构建SessionFactory对象

hibernate的hellowolrd:

public class hb_helloworld{

 public static void main(String[] args){

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

  ServiceRegistyBuilder srb = new ServiceRegistyBuilder().applySettings

(config.getProprties   ());

  ServiceRegisty sr = srb.buildServiceRegisty();

  SessionFactory factory = config.buildSessionFacory(sr);

  Session session = factory.openSession();

  //创建一个实体类对象

  Users users = new Users();

  users.setName("张四");

  users.setSex("男");

  users.setAge(22);

  //开启事务

  Transaction tr = session.beginTransaction();

  //保存对象(insert操作)

  session.save(user);

  //修改操作(update操作)

  users.setId(1);

  users.setName("qqww");

  users.setSex("女");

  users.setAge(19);

  session.update(users2);

  session.saveOrUpdate(users);//当OID为null时。可以执行insert操作

  //查询操作(select操作)

  Users users2 = (Users) session.get(Users.class,3);

  Users users3 = (Users) session.load(Users.class,2);//延迟检索操作。即只

是查询操作,不执行sql语句,当对属性操作时。才执行查询操作

  System.out.print(users2+"--"+users3)

 
c397
 //删除操作(delete操作)

  users.setId(1);

  session.delete(users);

  

  //提交事务

  tr.commit();

  session.close();

  factory.close();

  

 }

}

6.Session的一级缓存

Session接口是hibernate向应用程序提供的操纵数据库的最主要接口,他提供了最基本的增删改查方法

每一个session对象都在内存中维护了一个缓存。被称作一级缓存,即两次调用get方法查询同一条记录

,hibernate只会发送1条sql语句,因为session中有缓存。第二次调用时,直接从session缓存中取得

,从而也减少了多数据库的访问次数

7.持久化对象的四种状态

  7.1.临时状态:OID:无;session缓存:无;数据库对应记录:无。刚new出来的对象

  7.2.持久化状态:OID:有;session缓存:有;数据库对应记录:有。get查询操作后

  7.3.游离状态:OID:有;session缓存:无;数据库对应记录:有。new一个对象,并set与数据一条

记录相同的数据

  7.4.删除状态;OID:有(但无效);session缓存:无;数据库对应记录:无

8.Session的核心方法

save():可以将一个临时对象转化成持久化对象,可以不要临时对象中的OID,持久化的对象OID不允

许修改

persist():用处和save()一样,但是不允许保存带有OID的对象,会抛异常

get():根据OID的值。从数据库中立即加载一个对象到内存中,当session缓存中有时,则不会发送sql

语句,直接从缓存中取值

load():采用延迟检索策略。在调用load()后返回一个代理对象,不发生sql语句,在用到非OID值

时,才发送sql语句,当通过OID没有找到时,会报异常

update();对数据库进行更新操作,使用update()更新一个OID不存在的对象会抛出异常

saveOrUpdate():有更新和保存两种功能,当OID不存在时,会执行更新操作。OID存在时,会执行更新

操作

delete():根据OID,进行删除操作;

9.在hibernate环境下执行原生的jdbc代码;

session.doWork(new Work() { 

@Override

  

 public void execute(Connection connection) throws SQLException {

   //使用传入的Connection对象实现原生的JDBC操作...

 }

});

10.表与表之间的映射关系

  hibernate中使用 实体类名.hbm.xml.文件来定义持久化类和数据库表之间的映射关系

  持久化类对应的数据库中的表,持久化属性对应的是数据库表中的字段

  当然除了xml配置文件之外,hibernate也支持注解的形式进行配置

11.xml中<property>中元素属性说明

  name:持久化对象的属性名;

  type:通常用来指定hibernate映射的数据类型(可以使用java类型,也可以使用hibernate数据类型

);hibernate类型:integer,string,character,date,timestamp,float,object,blob等。

  column:对应的数据库的字段名;

  not-null:属性中不能为空;

  length:属性的长度;

  unique:是否唯一;

12.hibernate中的主键生成方式:<generator class="">

  此处介绍常用的有:native:由hibernate判断数据库,并且由数据库本身生成主键;

  identity:数据库为MySQL的数据库,由数据库本身生成主键id;

  increment:由hibernate查询数据库,并在原先数据的id加1生成,和底层数据库的类型没有关系;

  foreign:生成的是外键。

13.java中大对象类型的hibernate映射

  长字符串:长度超过255的字符串时,用text

  二进制数据:图片、音频、视频等文件以二进制保存到数据库;

  TinyBlob:255字节;Blob:65kb;MediumBlob:16mb;LongBlob:4GB.

14.在hibernate中对于大的文件,可以以blob的方式存入(如图片直接保存在数据库)

  保存

  FileInputStream in = new FileInputStream(1.png);

  Blob picture = Hibernate.getLobCreator(session).createBlob(in,in.available());

  读取

  InputStream in = blob.getBinaryStream();

15表关系

  [1].表关系之多对一

  例如:有一个学生表(student,多)和一张成绩表(score,一);一个学生有多门成绩

  单向多对一:首先,分别创建持久化类;齐次,创建对应的实体类.hbm.xml;最后,添加映射关系配

置信息。

  双向多对一:设置玩单向多对一后,在one的一段同意步骤设置信息。即形成双向关系。

  hibernate.cfg.xml中表的mapping能手动生成

  many一端设置:

  实体类(Student)中添加上:private Set<Score> scores;然后的对应的getter、setter方法

  Student.hbm.xml文件中:

  <set name="scores" table="score">

   <key>

     <column name="对应的外键名或者在score表中的对应学生表的id" />

 </key>

 <one-to-many class="com.zdl.bean.Student" />

  </set>

  one的一端设置:

  实体类(Score)中添上:private Student studrnt;

  Score.hbm.xml文件中:

  <many-to-one name="student" class="com.zdl.bean.Student" column="对应的外键名或者在

score表中的对应学生表的id" />

  [2].表关系之一对一

  例如有部门经理(manager)和部门(department)两张表;一般一个部门只有一个经理(一个经理

也只管一个部门)

  分别在把其他类的对象当做属性写在自己的类中

  Manager实体类中:private Department department;

  Department实体类中:private Manage manager;

  hbm.xml文件中:

  Manager.hbm.xml中:

  <one-to-one name="department" class="com.zdl.bean.Department"/>

  Department.hbm.xml中:

  设置外键(也可以给manager设置 constrained="true" 为外键约束)

  <generator class="foreign">

 <param name="property">manager</param>

  </genertor>

  <one-to-one name="manager" class="com.zdl.bean.Manager" constrained="true"/>

  [3].表关系之多对多

  例如:一个学生可以学习多门课程,一门课程可以有多个学生

  两个实体类设置:需要添加对方的set<类名> 属性;

  xml文件中:添加两个<set>和<many-to-many /> 标签

 

16.当为两张表中同时插入一个学生和他的成绩时,往往会报错(一起save)或者分为两步完成

  为了解决一次save报错的问题。需要在many一端的set中添加元素:cascade="save-update"

  或者cascade="all";all中包含了多种操作方法;cascade为是否级联其他表,默认为none。

17.inverse属性:inverse="true"表示的是只需要指定另外一方来维护关联的记录

<---hibernate的检索方式------------------------>

18.hibernate中的检索方式

  [1].OID检索方式:按照对象的OID来检索对象get/load;

 

  [2].对象图导航检索方式:获取到的当前类的属性是其他类的对象,然后获取其他类对象的属性;

 如:user.getBook().getBookName();

  [3].HQL检索方式:使用面向对象的hql(hibernate query language)查询语言

  hql是使用最广的一种检索语言(hql语句关键字不区分大小写,但是java类名严格区分大小写)

 (1)FROM子句(查询员工表中全部员工)

 from Employee;//Employee是java类类名,而不是表名;下同。

 

 (2)WHERE子句(此时的后面条件依旧是java类中的属性,而不是表字段)

 from Employee e where e.salary>6000;

 

 (3)使用基于位置的占位符参数:?(和sql语句一样)

 from Employee e where e.salary>?;

 填充占位符:query.setDouble(0,8000.00);0表示参数位置(从0开始!)

 使用具名参数:格式为":参数名称(自定义)"

 from Employee e where e.salary>:salary;

 填充占位符:query.setDouble("salary",8000.00);

 以实体类对象作为参数(有表的级联关系)

 from Employee e where e.department=?;

 Department department = new Department();

 department.setDeptId(1);

 填充占位符:query.setEntity(0, department)

 

 (4)order by子句(desc:降序;asc(升序,默认))

 from Employee e where e.salary>6000 order by e.salary desc

 

 (5)分页查询;当前页的页码:pageNo;一页显示多少条数据:pageSize

 Query中定义了两个相关函数

 setFirstResult(int index);指定查询结果从index位置开始。可以从0取值

 setMaxResult(int maxResult);指定查询结果显示多少条数据

 index和pageNo的关系:index=(pageNo-1)*pageSize;

 

 (6)投影查询方式(即查询一张表的部分字段对应的是java类中的部分属性)

 方式一:返回值形式是一个泛型为object[]

 Query query = session.createQuery(hql);

  List<Object[]> objs = query.list();

  for(Object[] o :objs){

   System.out.println(o[0]+"-"+o[1]);

  }

 方式二:返回值的泛型任然是实体类的对象,但是需要在实体类中的提供对应的构造器

 select new Employee(e.name,e.salary) from Employee e

 

 (7)多表查询(返回泛型的是数组,也可以写个所有属性的实体类,写上构造器,使用对象)

 from Student s,Score sc where s.id=sc.stuid;

 from Student s inner join Score sc on s.id=sc.stuid;

 (8)报表查询使用group by和having配合起来使用进行分组,再结合统计函数进行报表查询)

 select min(e.salary),max(e.salary)from Employee e

 group by e.department having min(e.salary)>3000; 

 

 (9)子查询:查询部门名以A开头的部门的员工姓名和部门名称

 select e.name,e.department.deptname from Employee e

 where e.department in(from Department d where d.deptname like 'A%');

 

  [4].QBC检索方式:使用qbc(query by criteria)API来检索对象。

 

 //1.创建Criteria对象

 Criteria c = session,createCriteria(Employee.class);

 //2.取得查询结果

 List<Employee> list = c.list();

 uniqueResult()方法获取单一的记录的查询结果(例如登录)

 (1)条件查询:Restrictions(各种条件都封装这个类中了)

 多个条件可以add添加,如c.add(like).add(gt).list();

 例如:模糊查询:like;判等:eq;大于:gt;小于:lt;大于等于:ge;

  小于等于:le;在两者之间:between num1 and num2;

  包含:in;

 (2)and 和 or 的使用(也可以互相嵌套使用)

 Conjunction表示and;Disjunction()表示or。

 //创建and条件对象

 Conjunction c = Restrictions.conjunction();(默认的就是and的对象)

 //创建or条件对象

 Disjunction d = Restrictions.disjunction();

 add(d).list();

 

 (3)报表查询Projections(单个统计函数);ProjectionList(多个统计函数)

 AggregateProjection max = Projection.max("salary");

 AggregateProjection min = Projection.min("salary");

 ProjectionList pList = Projections.projectionList();

 projectionList.add(max).add(min);

 List<Object[]> list session.createCriteria(Employee.class)

 .setProjection(pList).list();

 (4).group by分组

 Criteria c = session,createCriteria(Employee.class);

 PropertyProjection pp = Property.groupProperty("department");

 c.setProjection(pp).list();

 (5)order by排序 

 Order desc = Order.desc("name");

 List<Empolyee> list = session.createCriteria(Employee.class)

 .add(desc).list();

 

 (6)分页

 int pageNo=3;int pageSize=6;

 List<Employee> list = session.createCriteria(Employee.class)

 .setFirstResult((pageNo-1)*pageSize).setMaxResult(pageSize).list();

  [5].使用本地数据库的sql查询语句。SQLQuery extend Query

 见19.[4]

19.执行sql语句

  [1].查询

 String hql ="";

 Session session = hibernate.getSession();

 Query query = session.createQuery(hql);

 List<Employee> es = query.list();

 for(Employee e : es){

  System.out.print(e);

 }

  [2].修改

 String hql=" update Employee e set e.name='Tom' where e.id='1'";

 session.createQuery(hql).executeUpdate();

  [3].删除

 String hql ="delete from Employee e where e.id='2'";

 session.createQuery(hql).executeUpdate();

  [4].执行原生的sql语句

 List users = session.createSQLQuery(selet * from user);

 for(User e : users){

  System.out.print(e);

 }

20.hibernate的三种检索策略

  [1].立即检索策略:get方法

  优点:频繁使用的关联对象能够被加载到缓存中

  缺点:1.占用内存。2.select语句过多

  [2].延迟检索策略:load方法

  在类级别操作时,延迟检索策略,自加载类的OID,不加载类的其他属性,只有当第一次去访问其他属

性时,才会访问数据库的去加载内容。

  在关联级别操作时,延迟检索策略,只加载类本身,不加载关联类,直达第一次调用关联对象,才去

加载关联对象(默认的)

  优点:由程序决定加载哪些类和内容,避免了大量无用的sql语句和内存消耗

  缺点:在session关闭后,就不能访问关联对象了,需要确保session.close调用关联对象。

21.关联级别操作

  关联级别操作默认的是延迟加载策略,比如先获取一个对象,但不使用其关联对象,则就默认不会查

询,在xml配置文件中<class>中的lazy属性值默认是true,即默认延迟。

  lazy属性可以在class标签中

 也可以在set标签中,默认也是true;有三个可选值true.false.extra;

 还可以存在many-to-one标签中:默认值是proxy表示延迟加载,false不延迟加载

 (开发中常用延迟加载)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: