Hibernate学习总结
Hibernate学习总结
指尖残雪 发表于1年前
Hibernate学习总结
  • 发表于 1年前
  • 阅读 2
  • 收藏 0
  • 点赞 2
  • 评论 0

腾讯云实验室 1小时搭建人工智能应用,让技术更容易入门 免费体验 >>>   


hibernate配置文件:

hibernate.cfg.xml

示例代码:(连接的是MySQL数据库)

 

<!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 name="foo">

<!-- 配置数据库信息 --> 

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

<property name="connection.url">jdbc:mysql:///hibernate_20120328</property>

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

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

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

 

<!-- 其他配置 -->

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

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

<!-- 

create:先删除,再创建

update:如果表不存在就创建,不一样就更新,一样就什么都不做。

create-drop:初始化时创建表,SessionFactory执行close()时删除表。

validate:验证表结构是否一致,如果不一致,就抛异常。

 -->

<property name="hbm2ddl.auto">update</property>

<!-- 导入映射文件 

<mapping resource="cn/dyb/a_helloworld/User.hbm.xml"/>

-->

</session-factory>

</hibernate-configuration>

User.hbm.xml:(实体数据库映射文件)

<?xml version="1.0"?>

<!DOCTYPE hibernate-mapping PUBLIC

        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"

        "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

 

<hibernate-mapping package="cn.dyb.a_helloworld">

<class name="User" table="t_user">

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

            <generator class="native"/>

</id>

<property name="name" type="string" column="name" length="20"/>

</class>

</hibernate-mapping>

对应的类:

User.java

package cn.dyb.a_helloworld;

 

 

/**

 * ΚµΜε

 * 

 * @author tyg

 * 

 */

public class User {

private int id;

private String name;

 

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;

}

 

@Override

public String toString() {

return "[User: id=" + id + ", name=" + name + "]";

}

 

}

 

Hibernate连接数据库测试:

示例代码:

private static SessionFactory sessionFactory;

 

static {

Configuration cfg = new Configuration();

cfg.configure("hibernate.cfg.xml"); // 读取指定的主配置文件

sessionFactory = cfg.buildSessionFactory(); // 根据生成Session工厂

}

 

@Test

public void testSave() throws Exception {

User user = new User();

user.setName("张三");

 

// 保存

Session session = sessionFactory.openSession(); // 打开一个新的Session

Transaction tx = session.beginTransaction(); // 开始事务

 

session.save(user);

 

tx.commit(); // 提交事务

session.close(); // 关闭Session,释放资源

}

 

@Test

public void testGet() throws Exception {

Session session = sessionFactory.openSession();

Transaction tx = session.beginTransaction();

 

User user = (User) session.get(User.class, 1); // 获取

System.out.println(user);

 

tx.commit();

session.close();

}

 

Hibernate分页:

firstResult--开始取数据索引;maxResult--每页查询数据条数

封装到QueryResult类中:

QueryResult

package cn.dyb.b_dao;

 

import java.util.List;

 

public class QueryResult {

private int count; // 总记录数

private List list; // 一页的数据

 

public QueryResult(int count, List list) {

this.count = count;

this.list = list;

}

 

public int getCount() {

return count;

}

 

public void setCount(int count) {

this.count = count;

}

 

public List getList() {

return list;

}

 

public void setList(List list) {

this.list = list;

}

 

}

分页简单代码参考:

点击链接

 

小型案例:

HibernateUtils工具类:

package cn.dyb.b_dao;

 

import org.hibernate.Session;

import org.hibernate.SessionFactory;

import org.hibernate.cfg.Configuration;

 

import cn.dyb.a_helloworld.User;

 

public class HibernateUtils {

 

// SessionFactory全局只需要有一个就可以了

private static SessionFactory sessionFactory;

 

static {

Configuration cfg = new Configuration();

// cfg.configure(); // 读取默认的配置文件(hibernate.cfg.xml

// // cfg.configure("hibernate.cfg.xml"); // 读取指定位置的配置文件

// sessionFactory = cfg.buildSessionFactory();

 

// cfg.addResource("cn/dyb/a_helloworld/User.hbm.xml");

// cfg.addClass(User.class); // User类所在的包中查找名称为User,后缀为.hbm.xml的文件

 

// 初始化SessionFactory

sessionFactory = new Configuration()//

.configure()//

.buildSessionFactory();

}

 

/**

 * 获取全局唯一的SessionFactory

 * 

 * @return

 */

public static SessionFactory getSessionFactory() {

return sessionFactory;

}

 

/**

 * 从全局唯一的SessionFactory中打开一个Session

 * 

 * @return

 */

public static Session openSession() {

return sessionFactory.openSession();

}

}

 

Dao层类:

UserDao.java

package cn.dyb.b_dao;

 

import java.util.List;

 

import org.hibernate.Criteria;

import org.hibernate.Session;

import org.hibernate.Transaction;

import org.hibernate.criterion.Order;

import org.hibernate.criterion.Restrictions;

 

import cn.dyb.a_helloworld.User;

 

public class UserDao {

 

/**

 * 保存

 * 

 * @param user

 */

public void save(User user) {

Session session = HibernateUtils.openSession();

try {

Transaction tx = session.beginTransaction(); // 开始事务

session.save(user);

tx.commit(); // 提交事务

} catch (RuntimeException e) {

session.getTransaction().rollback(); // 回滚事务

throw e;

} finally {

session.close(); // 关闭Session

}

}

 

/**

 * 更新

 * 

 * @param user

 */

public void update(User user) {

Session session = HibernateUtils.openSession();

Transaction tx = null;

try {

tx = session.beginTransaction();

 

session.update(user); // 操作

 

tx.commit();

} catch (RuntimeException e) {

tx.rollback();

throw e;

} finally {

session.close();

}

}

 

/**

 * 删除

 * 

 * @param id

 */

public void delete(int id) {

Session session = HibernateUtils.openSession();

Transaction tx = null;

try {

tx = session.beginTransaction();

 

Object user = session.get(User.class, id); // 要先获取到这个对象

session.delete(user); // 删除的是实体对象

 

tx.commit();

} catch (RuntimeException e) {

tx.rollback();

throw e;

} finally {

session.close();

}

}

 

/**

 * 根据id查询一个User数据

 * 

 * @param id

 * @return

 */

public User getById(int id) {

Session session = HibernateUtils.openSession();

Transaction tx = null;

try {

tx = session.beginTransaction();

User user = (User) session.get(User.class, id); // 操作

tx.commit();

return user;

} catch (RuntimeException e) {

tx.rollback();

throw e;

} finally {

session.close();

}

}

 

/**

 * 查询所有

 * 

 * @return

 */

public List<User> findAll() {

Session session = HibernateUtils.openSession();

Transaction tx = null;

try {

tx = session.beginTransaction();

 

// 方式一:使用HQL查询

// List<User> list = session.createQuery("FROM User").list(); 

// 方式二:使用Criteria查询

Criteria criteria = session.createCriteria(User.class);

List<User> list = criteria.list();

tx.commit();

return list;

} catch (RuntimeException e) {

tx.rollback();

throw e;

} finally {

session.close();

}

}

 

/**

 * * 分页的查询数据列表

 * 

 * @param firstResult

 *            从结果列表中的哪个索引开始取数据

 * @param maxResults

 *            最多取多少条数据

 * @return 一页的数据列表 总记录数

 */

@SuppressWarnings("unchecked")

public QueryResult findAll(int firstResult, int maxResults) {

Session session = HibernateUtils.openSession();

Transaction tx = null;

try {

tx = session.beginTransaction();

 

// 查询一页的数据列表

// 方式一:

// Query query = session.createQuery("FROM User");

// query.setFirstResult(firstResult);

// query.setMaxResults(maxResults);

// List<User> list = query.list();

// 方式二:方法链

List<User> list = session.createQuery(//

"FROM User")//

.setFirstResult(firstResult)//

.setMaxResults(maxResults)//

.list();

 

// 查询总记录数

Long count = (Long) session.createQuery(//

"SELECT COUNT(*) FROM User")//

.uniqueResult();

tx.commit();

//  返回结果

return new QueryResult(count.intValue(), list);

} catch (RuntimeException e) {

tx.rollback();

throw e;

} finally {

session.close();

}

}

}

 

测试代码:

UserDaoTest.java

 

package cn.dyb.b_dao;

 

import java.util.List;

 

import org.junit.Test;

 

import cn.dyb.a_helloworld.User;

 

public class UserDaoTest {

 

private UserDao userDao = new UserDao();

 

@Test

public void testSave_1() {

User user = new User();

user.setName("张三");

 

// 保存

userDao.save(user);

}

 

@Test

public void testGetById() {

User user = userDao.getById(1);

System.out.println(user);

}

 

@Test

public void testUpdate() {

// 从数据库获取一条存在的数据

User user = userDao.getById(1);

user.setName("李四");

 

// 更新

userDao.update(user);

}

 

@Test

public void testDelete() {

userDao.delete(1);

}

 

// ------------

 

@Test

public void testSave_25() {

for (int i = 1; i <= 25; i++) {

User user = new User();

user.setName("test_" + i);

userDao.save(user); // 保存

}

}

 

@Test

public void testFindAll() {

List<User> list = userDao.findAll();

for (User user : list) {

System.out.println(user);

}

}

 

@Test

public void testFindAllIntInt() {

// 查询

// QueryResult qr = userDao.findAll(0, 10); // 1页,每页10

// QueryResult qr = userDao.findAll(10, 10); // 2页,每页10

QueryResult qr = userDao.findAll(20, 10); // 3页,每页10

 

// 显示结果

System.out.println("总记录数:" + qr.getCount());

for (User user : (List<User>) qr.getList()) {

System.out.println(user);

}

}

 

}

 

根据配置生成表结构

根据配置文件生成相应的数据库代码。

 

示例代码:

package cn.dyb.a_helloworld;

 

import org.hibernate.cfg.Configuration;

import org.hibernate.tool.hbm2ddl.SchemaExport;

import org.junit.Test;

 

public class CreateSchema {

 

// 根据配置生成表结构

@Test

public void test() throws Exception {

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

SchemaExport schemaExport = new SchemaExport(cfg);

// 第一个参数script的作用: print the DDL to the console

// 第二个参数export的作用: export the script to the database

schemaExport.create(true, true);

}

}

 

配置文件扩展

通过addClass添加实体类

private static SessionFactory sessionFactory = new Configuration()//

.configure()//

.addClass(User.class)// 添加Hibernate实体类(加载对应的映射文件)

.buildSessionFactory();

 

 

数据库中保存头像(小图片)

实体类中定义

private byte[] photo; // 头像图片

映射文件中的定义

<!-- 头像,二进制类型,最好指定长度 -->

<property name="photo" type="binary" length="102400"></property>

测试类中的图片存储与读取

// 读取图片文件

InputStream in = new FileInputStream( "c:/test.png");

byte[] photo = new byte[in.available()];

in.read(photo);

in.close();

//输出图片

OutputStream out = new FileOutputStream("c:/copy.png");

out.write(user.getPhoto());

out.close();

大文本数据保存

实体类中定义

private String desc; // 一大段说明

映射关系中定义(text

<property name="desc" type="text" length="5000" column="t_desc" ></property>

 

Hibernate主键生成策略

<generator class="?"/>

identity

<generator class="identity"/>

使用数据库的自动增长策略,不是所有数据库都支持,比如oracle就不支持 

sequence

<generator class="sequence"/>

在 DB2PostgreSQLOracleSAP DBMcKoi 中使用序列(sequence),在使用Oracle数据库时可以使用这一个

hilo

<generator class="hilo">

<param name="table">hi_value</param>

    <param name="column">next_value</param>

    <param name="max_lo">100</param>

</generator>

使用高低位算法生成主键值。只需要一张额外表,所有的数据都支持。

native

<generator class="native"></generator>

根据底层数据库的能力选择 identitysequence 或者 hilo中的一个。

increment

<generator class="increment"></generator>

Hibernate维护的自动增长。先查询当前最大的id值,再加1使用,不推荐使用,因为在多线程下会问题。

assigned

<generator class="assigned"></generator>

手工指定主键值  

uuid

<generator class="uuid"></generator>

可以添加:user.setId(UUID.randomUUID().toString()),否则自动生成。

Hibernate自动生成UUID并指定为主键值。

映射集合属性

set

在实体类中的定义:

private Set<String> addressSet = new HashSet<String>(); // Set集合

在映射文件中的定义:

addressSet属性,Set集合 

table属性:集合表的名称

key子元素:集合外键的列名

element子元素:存放集合元素的列的信息

sort属性:"unsorted|natural|comparatorClass" 默认为:unsorted

order-by属性:写的是order by 子句,是SQL语句,是操作的集合表。这是在查询数据时指定orderby子句。

<set name="addressSet" table="user_addressSet" order-by="address ASC">

<key column="userId"></key>

<element type="string" column="address"></element>

</set>

list

在实体类中的定义:

private List<String> addressList = new ArrayList<String>(); // List集合

在映射文件中的定义:

addressList属性,List集合 

list-index:用于存放索引的列

<list name="addressList" table="user_addressList">

<key column="userId"></key>

<list-index column="idx"></list-index>

<element type="string" column="address"></element>

</list>

Array数组

在实体类中的定义:

private String[] addressArray; // 数组

在映射文件中的定义:

addressArray属性,数组。与List的映射基本一致

<array name="addressArray" table="user_addressArray">

<key column="userId"></key>

<list-index column="idx"></list-index>

<element type="string" column="address"></element>

</array>

map

在实体类中的定义:

private Map<String, String> addressMap = new HashMap<String, String>();

在映射文件中的定义:

addressMap属性,Map集合 

<map name="addressMap" table="user_addressMap">

<key column="userId"></key>

<map-key type="string" column="key_"></map-key>

<element type="string" column="address"></element>

</map>

bag

在实体类中的定义:

private List<String> addressBag = new ArrayList<String>();

在映射文件中的定义:

addressBag属性,Bag集合:无序,可重复。与Set集合的映射基本一致

<bag name="addressBag" table="user_addressBag">

<key column="userId"></key>

<element type="string" column="address"></element>

</bag>

一对多多对一映射

例子:部门和员工的对应关系(部门员工一对多)

部门

private Set<Employee> employees = new HashSet<Employee>(); // 关联的很多员工

 

employees属性,Set集合,表达的是本类与Employee的一对多 

class属性:关联的实体类型

key子元素:对方表中的外键列(多方的那个表)

inverse属性:

默认为false,表示本方维护关联关系。

如果为true,表示本方不维护关联关系。

只是影响是否能设置外键列的值(设成有效值或是null值),对获取信息没有影响。

cascade属性:

默认为none,代表不级联。

级联是指操作主对象时,对关联的对象也做相同的操作。

可设为:delete, save-update, all, none ...

<set name="employees" cascade="all">

<key column="departmentId"></key>

<one-to-many class="Employee"/>

</set>

员工

private Department department; // 关联的部门对象

 

department属性,表达的是本类与Department的多对一 

class属性:关联的实体类型

column属性:外键列(引用关联对象的表的主键)

<many-to-one name="department" class="Department" column="departmentId"></many-to-one>

关联关系inverse

从部门方解除(与inverse有关系,为false时可以解除)

Department department = (Department) session.get(Department.class, 1);

department.getEmployees().clear();

 

删除部门方(一方)

A.如果没有关联的员工:能删除。

B.如果有关联的员工且inverse=true,由于不能维护关联关系,所以会直接执行删除,就会有异常

C.如果有关联的员工且inverse=false,由于可以维护关联关系,他就会先把关联的员工的外键列设为null值,再删除自己。

多对多

学生和教师例子(多对多关系)

学生

private Set<Teacher> teachers = new HashSet<Teacher>(); // 关联的老师们

 

teachers属性,Set集合。

表达的是本类与Teacher的多对多。

table属性:中间表(集合表)

key子元素:集合外键(引用当前表主键的那个外键)

<set name="teachers" table="teacher_student" inverse="false">

<key column="studentId"></key>

<many-to-many class="Teacher" column="teacherId"></many-to-many>

</set>

教师

private Set<Student> students = new HashSet<Student>(); // 关联的学生们

 

students属性,Set集合。

表达的是本类与Student的多对多。

<set name="students" table="teacher_student" inverse="true">

<key column="teacherId"></key>

<many-to-many class="Student" column="studentId"></many-to-many>

</set>

 

inverse

 a, 如果没有关联的对方:能删除。

 b, 如果有关联的对方且inverse=false,由于可以维护关联关系,他就会先删除关联关系,再删除自己。

 c, 如果有关联的对方且inverse=true,由于不能维护关联关系,所以会直接执行删除自己,就会有异常。

对象状态

Evict

session.evict(user); // 清除Session中一个指定的对象

将持久化状态转成游离状态

 

save()

把临时状态变为持久化状态(交给Sessioin管理)

会生成:insert into ...

 

update()

把游离状态变为持久化状态

会生成:update ...

在更新时,对象不存在就报错

 

saveOrUpdate()

把临时或游离状态转为持久化状态

会生成:insert into 或 update ...

在更新时,对象不存在就报错

本方法是根据id判断对象是什么状态的:如果id为原始值(对象的是null,原始类型数字是0)就是临时状态,如果不是原始值就是游离状态。

 

delete()

把持久化或游离转为删除状态

会生成:delete ...

如果删除的对象不存在,就会抛异常

 

get()

获取数据,是持久化状态

会生成:select ... where id=?

会马上执行sql语句

如果数据不存在,就返回null

 

load()

获取数据,是持久化状态

会生成:select ... where id=?

load()后返回的是一个代理对象,要求类不能是final的,否则不能生成子类代理,就不能使用懒加载功能了。

让懒加载失效的方式:一、把实体写成final的;二、在hbm.xml中写<class ... lazy="false">

不会马上执行sql语句,而是在第1次使用非idclass属性时执行sql

如果数据不存在,就抛异常:ObjectNotFoundException

 

加载方式

返回值

如果值不存在

get

立即加载

真是对象或null

返回null

load

延迟加载

代理对象

抛异常

Session保存内存溢出

当保存多条数据或者数据过大时,会造成数据溢出,要先刷出(存入数据库)然后清空再继续执行。

for (int i = 0; i < 30; i++) {

User user = new User();

user.setName("测试");

session.save(user);

if (i % 10 == 0) {

session.flush(); // 先刷出

session.clear(); // 再清空

}

}

一对一映射

基于外键的方式

人和身份证(身份证里面有一个关联人的外键,不能重复)

Person.java

private IdCard idCard; // 关联的身份证

映射文件:

    idCard属性,IdCard类型。

表达的是本类与IdCard的一对一。

采用基于外键的一对一映射方式,本方无外键方。

property-ref属性:

写的是对方映射中外键列对应的属性名。

<one-to-one name="idCard" class="IdCard" property-ref="person"/>

 

IdCare.java

private Person person; // 关联的公民

 

映射文件:

    person属性,Person类型。

表达的是本类与Person的一对一。

采用基于外键的一对一映射方式,本方有外键方。 

(多对一的特殊方式)

<many-to-one name="person" class="Person" column="personId" unique="true"></many-to-one>

 

关联关系

解除关联关系:一对一中,只能有外键方可以维护关联关系。

从有外键方解除关系,可以。

IdCard idCard = (IdCard) session.get(IdCard.class, 1);

idCard.setPerson(null);

从无外键方解除关系,不可以。

Person person = (Person) session.get(Person.class, 1);

person.setIdCard(null);

 

a, 如果没有关联的对方:能删除。

b, 如果有关联的对方且可以维护关联关系(有外键方),他就会先删除关联关系,再删除自己。

c, 如果有关联的对方且不能维护关联关系(无外键方),所以会直接执行删除自己,就会有异常。

基于主键的方式

Person实体类中定义:

private IdCard idCard; // 关联的身份证

映射文件定义:

<!-- idCard属性,IdCard类型。

表达的是本类与IdCard的一对一。

采用基于主键的一对一映射方式,本方无外键方。

 -->

<one-to-one name="idCard" class="IdCard"></one-to-one>

 

IdCard实体类中定义:

private Person person; // 关联的公民

映射文件定义:

<class name="IdCard" table="idCard2">

<id name="id">

<!-- 当使用基于主键的一对一映射时,

有外键方的主键生成策略一定要是foreign

参数property

生成主键值时所根据的对象。

 -->

     <generator class="foreign">

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

     </generator>

</id>

<property name="number"/>

<!-- person属性,Person类型。

表达的是本类与Person的一对一。

采用基于主键的一对一映射方式,本方有外键方。 -->

<one-to-one name="person" class="Person" constrained="true"></one-to-one>

</class>

关联关系:

解除关联关系:使用基于主键的一对一映射方式:双方都不可以解除关联关系。

如果没有关联的对方:能删除。

如果有关联的对方:因为会直接执行删除自己,所以无外键方会有异常,有外键方没有异常。

继承映射

用一张表的方式

 

使用论坛主题和回复为例:

Article.java

private Integer id;

private String title;

private String content;

private Date postTime;

Reply.java

  private int floor; // 楼层

Topic.java

  private int type; // 精华、置顶...

Article.hbm.xml使用父类的映射:

<!-- 

discriminator-value属性:

用于鉴别是哪个类的一个值,表示这个值就是这个类。

如果不写,默认为类的全限定名。

 -->

<class name="Article" table="article" discriminator-value="Aticle">

<id name="id">

     <generator class="native"/>

</id>

<!-- 用于鉴别是什么类型的一个列 -->

<discriminator type="string" column="class_"></discriminator>

<property name="title"/>

<property name="content" type="text" length="10000"/>

<property name="postTime" type="timestamp"/>

<!-- 子类:Topic -->

<subclass name="Topic" discriminator-value="Topic">

<property name="type"></property>

</subclass>

<!-- 子类:Reply -->

<subclass name="Reply" discriminator-value="Reply">

<property name="floor"></property>

</subclass>

</class>

每个类对应一张表

<!-- 采用每个类一张表的方式,抽象类也对应表。 -->

<class name="Article" table="article2">

<id name="id">

     <generator class="native"/>

</id>

<property name="title"/>

<property name="content" type="text" length="10000"/>

<property name="postTime" type="timestamp"/>

<!-- 子类:Topic -->

<joined-subclass name="Topic" table="topic2">

<key column="id"></key>

<property name="type"></property>

</joined-subclass>

<!-- 子类:Reply -->

<joined-subclass name="Reply" table="reply2">

<key column="id"></key>

<property name="floor"></property>

</joined-subclass>

</class>

具体类一张表,抽象类不对应表

<!-- 采用每个具体类一张表的方式,抽象类不对应表。 -->

<class name="Article" abstract="false" table="article3">

<id name="id">

<!-- 

当使用每个具体类一张表的方式时,主键生成策略不能是identity

因为在整个继承结构中,主键值是不能重复的。

 -->

    <generator class="hilo">

    <param name="table">hi_value</param>

            <param name="column">next_value</param>

            <param name="max_lo">100</param>

    </generator>

</id>

<property name="title"/>

<property name="content" type="text" length="10000"/>

<property name="postTime" type="timestamp"/>

<!-- 子类:Topic -->

<union-subclass name="Topic" table="topic3">

<property name="type"></property>

</union-subclass>

<!-- 子类:Reply -->

<union-subclass name="Reply" table="reply3">

<property name="floor"></property>

</union-subclass>

</class>

事务隔离级别

例如:

hibernate.cfg.xml中配置

<!-- 

设置默认的事务隔离级别:

隔离级别 对应的整数表示

READ UNCOMMITED 1

READ COMMITED 2

REPEATABLE READ 4

SERIALIZEABLE 8

 -->

<property name="connection.isolation">2</property>

HQL

简单示例

使用HQL查询

HQL: Hibernate Query Language.

特点:

>> 1,与SQL相似,SQL中的语法基本上都可以直接使用。

>> 2SQL查询的是表和表中的列;HQL查询的是对象与对象中的属性。

>> 3HQL的关键字不区分大小写,类名与属性名是区分大小写的。

>> 4SELECT可以省略.

1,简单的查询

hql = "FROM Employee";

hql = "FROM Employee AS e"; // 使用别名

hql = "FROM Employee e"; // 使用别名,as关键字可省略

 

2,带上过滤条件的(可以使用别名):Where

hql = "FROM Employee WHERE id<10";

hql = "FROM Employee e WHERE e.id<10";

hql = "FROM Employee e WHERE e.id<10 AND e.id>5";

 

3,带上排序条件的:Order By

hql = "FROM Employee e WHERE e.id<10 ORDER BY e.name";

hql = "FROM Employee e WHERE e.id<10 ORDER BY e.name DESC";

hql = "FROM Employee e WHERE e.id<10 ORDER BY e.name DESC, id ASC";

4,指定select子句(不可以使用select *

hql = "SELECT e FROM Employee e"; // 相当于"FROM Employee e"

hql = "SELECT e.name FROM Employee e"; // 只查询一个列,返回的集合的元素类型就是这个属性的类型

hql = "SELECT e.id,e.name FROM Employee e"; // 查询多个列,返回的集合的元素类型是Object数组

hql = "SELECT new Employee(e.id,e.name) FROM Employee e"; // 可以使用new语法,指定把查询出的部分属性封装到对象中

5,执行查询,获得结果(listuniqueResult、分页 )

Query query = session.createQuery("FROM Employee e WHERE id<3");

query.setFirstResult(0);

query.setMaxResults(10);

// List list = query.list(); // 查询的结果是一个List集合

Employee employee = (Employee) query.uniqueResult();// 查询的结果是唯一的一个结果,当结果有多个,就会抛异常

System.out.println(employee);

QBC

简单示例

// 创建Criteria对象

Criteria criteria = session.createCriteria(Employee.class);

// 增加过滤条件

criteria.add(Restrictions.ge("id", 1));

criteria.add(Restrictions.le("id", 5));

// 增加排序条件

criteria.addOrder(Order.desc("name"));

criteria.addOrder(Order.desc("id"));

// 执行查询

// criteria.setFirstResult(0);

// criteria.setMaxResults(100);

// criteria.uniqueResult();

// criteria.list()

List list = criteria.list();

懒加载

懒加载

也叫延迟加载,不是在执行获取操作时马上生成SQL,而是在第一次使用时生成SQL

分成两种:

类级别的:

<class ... lazy="true/false">

属性级别的:

<set/list/map/bag ... lazy="...">

<many-to-one ... lazy="...">

<one-to-one ... lazy="...">

在使用懒加载特性时,可能会有LazyInitializationException异常:

原因:

真正的去获取数据时,Session已经没有了。

解决办法:

方式一:让Session在真正加载后再关闭。

方式二:或是在Sessoin关闭前执行Hibernate.initialize(department.getEmployees());

 

extra策略

与 lazy=true” 类似主要区别是增强延迟检索策略能进一步延迟 Customer 对象的 orders 集合代理实例的初始化时机:

• 当程序第一次访问 orders 属性的 iterator() 方法时会导致 orders 集合代理类实例的初始化

• 当程序第一次访问 order 属性的 size(), contains() 和 isEmpty() 方法时, Hibernate 不会初始化 orders 集合类的实例仅通过特定的 select 语句查询必要的信息不会检索所有的 Order 对象

 

C3P0连接池设定

hibernate.cfg.xml中的配置

需要导包:(例如c3p0-0.9.1.jar

<!-- 使用c3p0连接池  配置连接池提供的供应商-->

<property name="connection.provider_class">

<!--在连接池中可用的数据库连接的最少数目 -->

<property name="c3p0.min_size">5</property>

<!--在连接池中所有数据库连接的最大数目  -->

<property name="c3p0.max_size">20</property>

<!--设定数据库连接的过期时间,以秒为单位,

如果连接池中的某个数据库连接处于空闲状态的时间超过了timeout时间,就会从连接池中清除 -->

<property name="c3p0.timeout">120</property>

 <!--3000秒检查所有连接池中的空闲连接 以秒为单位-->

<property name="c3p0.idle_test_period">3000</property>

 

二级缓存

配置示例

<!-- 使用二级缓存,默认是未打开的。 -->

<!-- 指定要使用的缓存的提供商,这也就打开了二级缓存 ,不同的提供商需要不同jar包支持需要手动添加

<property name="cache.provider_class">org.hibernate.cache.HashtableCacheProvider</property>

-->

<property name="cache.provider_class">org.hibernate.cache.EhCacheProvider</property>

<!-- 开启使用查询缓存 -->

<property name="cache.use_query_cache">true</property>

<!-- 指定要使用二级缓存的实体类 -->

<class-cache usage="read-write" class="cn.dyb.l_second_cache.Employee"/>

<collection-cache usage="read-write" collection="cn.dyb.l_second_cache.Department.employees" />

对应提供二级缓存的EhCacheProvider参考文档

它有自己的默认配置文件(ehcache.xml),可以直接复制到src目录

例如:ehcache.xml

<ehcache>

    <diskStore path="d:/cache/"/>

    <defaultCache

        maxElementsInMemory="10"

        eternal="false"

        timeToIdleSeconds="120"

        timeToLiveSeconds="120"

        overflowToDisk="true"

        />

</ehcache>

 

 

不管是一级缓存,还是二级缓存,都地在使用OID的获取对象时才有效。

get()

load()

对于Query.list()默认不会使用缓存,哪怕写成where id=1也不会使用缓存。

 

 

 

Update \____ 不会通知Session缓存。

Delete /  通知二级缓存

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

共有 人打赏支持
粉丝 8
博文 73
码字总数 0
×
指尖残雪
如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
* 金额(元)
¥1 ¥5 ¥10 ¥20 其他金额
打赏人
留言
* 支付类型
微信扫码支付
打赏金额:
已支付成功
打赏金额: