您的位置:首页 > 其它

hibernate第三天——session的缓存与事务隔离级别,一对一关系,多种方式查询

2015-12-16 17:14 525 查看

1、session的缓存与事务隔离级别

(1)、查询数据(session的缓存):

先在session的缓存中找,如果找不到再找数据库。这样虽然提高性能,但是存在一定的风险,可能另一个线程改变了数据库内容,但是查询的还是缓存中的数据。
class Session{
private Map<Serializable, Object> cache; // 缓存

public Object get(.., id){
Object obj = cache.get(id);
if(obj == null){
obj = "select * from xxx whereid=?";
cache.put(id, obj);
}
return obj;
}
}


事务隔离级别

数字类型的常量值。

session.refresh()方法。

清除缓存,进行重新查询。

在Hibernate中指定事务隔离级别。

(2)、事务与事务隔离级别:



读未提交(read uncommitted):改了还没提交就获得了新的数据,几乎不使用。
读已提交(read commited):改了提交了才能重新获得。用的比较广泛
可重复读(repeatable read):事务开始时创建快照,不关注其他事务,其他事物不改变状态。。默认的事务隔离
串行化(不可并发):只能一个一个的来。对数据的要求最为严格,自然也是性能最差的一种隔离级别。

hibernate的配置文件:
<property name="connection.isolation">2</property>


2、一对一映射关系

电话,身份证号,都是String类型

集合可以初始化,但是对象不要初始化



基于外键的可以解除关系。

(1)、基于外键的方式:

IdCard.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.itcast.i_hbm_oneToOne">

<class name="IdCard" table="idCard">
<id name="id">
<generator class="native"></generator>
</id>
<property name="number"/>

<!-- person属性,Person类型。
表达的是本类与Person的一对一。
采用基于外键的一对一映射方式,本方有外键方。 -->
<many-to-one name="person" class="Person" column="personId" unique="true"></many-to-one>

</class>

</hibernate-mapping>


Person.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.itcast.i_hbm_oneToOne">

<class name="Person" table="person">
<id name="id">
<generator class="native"></generator>
</id>
<property name="name"/>

<!-- idCard属性,IdCard类型。
表达的是本类与IdCard的一对一。
采用基于外键的一对一映射方式,本方无外键方。
property-ref属性:
写的是对方映射中外键列对应的属性名。
-->
<one-to-one name="idCard" class="IdCard" property-ref="person"/>

</class>

</hibernate-mapping>


测试App:
package cn.itcast.i_hbm_oneToOne;

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

public class App {

private static SessionFactory sessionFactory = new Configuration()//
.configure()//
.addClass(Person.class)// 添加Hibernate实体类(加载对应的映射文件)
.addClass(IdCard.class)// 添加Hibernate实体类(加载对应的映射文件)
.buildSessionFactory();

// 保存,有关联关系
@Test
public void testSave() throws Exception {
Session session = sessionFactory.openSession();
session.beginTransaction();
// --------------------------------------------

// 新建对象
Person person = new Person();
person.setName("张三");

IdCard idCard = new IdCard();
idCard.setNumber("100000011X");

// 关联起来
// person.setIdCard(idCard);
idCard.setPerson(person);

// 保存
session.save(person);
session.save(idCard);

// --------------------------------------------
session.getTransaction().commit();
session.close();
}

// 获取,可以获取到关联的对方
@Test
public void testGet() throws Exception {
Session session = sessionFactory.openSession();
session.beginTransaction();
// --------------------------------------------

// 获取一方,并显示另一方信息
// Person person = (Person) session.get(Person.class, 1);
// System.out.println(person);
// System.out.println(person.getIdCard());

IdCard idCard = (IdCard) session.get(IdCard.class, 1);
System.out.println(idCard);
System.out.println(idCard.getPerson());

// --------------------------------------------
session.getTransaction().commit();
session.close();

}

// 解除关联关系:一对一中,只能有外键方可以维护关联关系。
@Test
public void testRemoveRelation() throws Exception {
Session session = sessionFactory.openSession();
session.beginTransaction();
// --------------------------------------------

// 从有外键方解除关系,可以。
// IdCard idCard = (IdCard) session.get(IdCard.class, 1);
// idCard.setPerson(null);

// 从无外键方解除关系,不可以。
Person person = (Person) session.get(Person.class, 1);
person.setIdCard(null);

// --------------------------------------------
session.getTransaction().commit();
session.close();
}

// 删除对象,对关联对象的影响
@Test
public void testDelete() throws Exception {
Session session = sessionFactory.openSession();
session.beginTransaction();
// --------------------------------------------

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

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

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

// --------------------------------------------
session.getTransaction().commit();
session.close();
}

}


小结:
有外键方的可以自动维护表关系。
inverse属性只用于一对多。
外键都是many-one。
一对一的有外键的方式只能从有外键的一方来维护表结构。

单向关联:

单向一对多。

单向多对一。

单向多对多。

单向一对一(只能做从有外键方到无外键方的单向关联)

(2)、基于主键的方式:

IdCard.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.itcast.i_hbm_oneToOne2">

<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>

</hibernate-mapping>


Person.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.itcast.i_hbm_oneToOne2">

<class name="Person" table="person2">
<id name="id">
<generator class="native"></generator>
</id>
<property name="name"/>

<!-- idCard属性,IdCard类型。
表达的是本类与IdCard的一对一。
采用基于主键的一对一映射方式,本方无外键方。
-->
<one-to-one name="idCard" class="IdCard"></one-to-one>

</class>

</hibernate-mapping>


测试App:

package cn.itcast.i_hbm_oneToOne2;

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

public class App {

private static SessionFactory sessionFactory = new Configuration()//
.configure()//
.addClass(Person.class)// 添加Hibernate实体类(加载对应的映射文件)
.addClass(IdCard.class)// 添加Hibernate实体类(加载对应的映射文件)
.buildSessionFactory();

// 保存,有关联关系
@Test
public void testSave() throws Exception {
Session session = sessionFactory.openSession();
session.beginTransaction();
// --------------------------------------------

// 新建对象
Person person = new Person();
person.setName("张三");

IdCard idCard = new IdCard();
idCard.setNumber("100000011X");

// 关联起来
person.setIdCard(idCard);
idCard.setPerson(person);

// 保存
session.save(person);
session.save(idCard);

// --------------------------------------------
session.getTransaction().commit();
session.close();
}

// 获取,可以获取到关联的对方
@Test
public void testGet() throws Exception {
Session session = sessionFactory.openSession();
session.begin
1290d
Transaction();
// --------------------------------------------

// 获取一方,并显示另一方信息
// Person person = (Person) session.get(Person.class, 1);
// System.out.println(person);
// System.out.println(person.getIdCard());

IdCard idCard = (IdCard) session.get(IdCard.class, 1);
System.out.println(idCard);
System.out.println(idCard.getPerson());

// --------------------------------------------
session.getTransaction().commit();
session.close();

}

// 解除关联关系:使用基于主键的一对一映射方式:双方都不可以解除关联关系。
@Test
public void testRemoveRelation() throws Exception {
Session session = sessionFactory.openSession();
session.beginTransaction();
// --------------------------------------------

// 基于主键的一对一映射:从有外键方解除关系,不可以,因为主键 不能为null。
IdCard idCard = (IdCard) session.get(IdCard.class, 1);
idCard.setPerson(null);

// // 基于主键的一对一映射:从无外键方解除关系,不可以。
// Person person = (Person) session.get(Person.class, 1);
// person.setIdCard(null);

// --------------------------------------------
session.getTransaction().commit();
session.close();
}

// 删除对象,对关联对象的影响
@Test
public void testDelete() throws Exception {
Session session = sessionFactory.openSession();
session.beginTransaction();
// --------------------------------------------

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

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

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

// --------------------------------------------
session.getTransaction().commit();
session.close();
}

}


3、继承结构



(1)、使用1张表

Article.cfg.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.itcast.j_hbm_extends">

<!--
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>

</hibernate-mapping>


(2)、每个类一张表,抽象类也对应表

<?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.itcast.j_hbm_extends2">

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

</hibernate-mapping>


(3)、每个类一张表,抽象类不对应表

<?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.itcast.j_hbm_extends3">

<!-- 采用每个具体类一张表的方式,抽象类不对应表。
abstract默认为false,设为true表示本类不对应表(类可以不是abstract的),这时就会忽略table属性。
-->
<class name="Article" abstract="true" 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-mapping>


<!-- table: table name (default <tt>hibernate_sequences</tt>)
primary_key_column: key column name (default <tt>sequence_name</tt>)
value_column: hi value column name(default <tt>sequence_next_hi_value</tt>)
primary_key_value: key value for the current entity (default to the entity's primary table name)
primary_key_length: length of the key column in DB represented as a varchar (default to 255)
max_lo: max low value before increasing hi (default to Short.MAX_VALUE)
-->
<generator class="org.hibernate.id.MultipleHiLoPerTableGenerator">
<param name="table">hi_value</param>
<param name="max_lo">100</param>
</generator>


4、多种查询方式——hql

1,简单的查询

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

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

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

可以使用new语法,指定把查询出的部分属性封装到对象中

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

6,方法链

1,聚集函数

2,分组

3,连接查询 / HQL是面向对象的查询

4,查询时使用参数

方式一:使用'?'占位

方式二:使用变量名

5,使用命名查询

6,update与delete,不会通知Session缓存

在update或delete后,需要refresh(obj)一下以获取最新的状态

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

<!--
auto-import表示在HQL中写类的简单名称时,是否自动导入当前这个包。
即为true时,在HQL中可以写简单名称,表示当前这个类。
当为false时,在HQL中就得写全限定名了。
默认为true。
-->
<hibernate-mapping package="cn.itcast.k_query_hql" auto-import="true">

<class name="Employee" table="employee">
<id name="id">
<generator class="native"></generator>
</id>
<property name="name" type="string" column="name"/>

<!-- department属性,表达的是本类与Department的多对一 -->
<many-to-one name="department" class="Department" column="departmentId"></many-to-one>

</class>

<!-- 定义命名的查询 -->
<query name="queryByIdRange">
<![CDATA[FROM Employee e WHERE e.id >= :idMin AND e.id <= :idMax]]>
</query>

</hibernate-mapping>


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,执行查询,获得结果(list、uniqueResult、分页 )

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);

1,聚集函数:count(), max(), min(), avg(), sum()

hql = "SELECT COUNT(*) FROM Employee"; // 返回的结果是Long型的

hql = "SELECT min(id) FROM Employee"; // 返回的结果是id属性的类型

Number result = (Number) session.createQuery(hql).uniqueResult();

System.out.println(result.getClass());

System.out.println(result);

2,分组: Group By ... Having

hql = "SELECT e.name,COUNT(e.id) FROM Employee e GROUP BY e.name";

hql = "SELECT e.name,COUNT(e.id) FROM Employee e GROUP BY e.name HAVING count(e.id)>1";

hql = "SELECT e.name,COUNT(e.id) FROM Employee e WHERE id<9 GROUP BY e.name HAVING count(e.id)>1";

---

hql = "SELECT e.name,COUNT(e.id) " + //

"FROM Employee e " + //

"WHERE id<9 " + //

// "GROUP BY e.name " + //

// "HAVING count(e.id)>1 " + //

"ORDER BY count(e.id) ASC";

---

hql = "SELECT e.name,COUNT(e.id) AS c " + //

"FROM Employee e " + //

"WHERE id<9 " + //

// "GROUP BY e.name " + //

// "HAVING count(e.id)>1 " + // 在having子句中不能使用列别名

"ORDER BY c ASC"; // 在orderby子句中可以使用列别名

3,连接查询 / HQL是面向对象的查询

>> 内连接(inner关键字可以省略)

hql = "SELECT e.id,e.name,d.name FROM Employee e JOIN e.department d";

hql = "SELECT e.id,e.name,d.name FROM Employee e INNER JOIN e.department d";

>> 左外连接(outer关键字可以省略)

hql = "SELECT e.id,e.name,d.name FROM Employee e LEFT OUTER JOIN e.department d";

>> 右外连接(outer关键字可以省略)

hql = "SELECT e.id,e.name,d.name FROM Employee e RIGHT JOIN e.department d";

可以使用更方便的方法

hql = "SELECT e.id,e.name,e.department.name FROM Employee e";

4,查询时使用参数

>> 方式一:使用'?'占位

hql = "FROM Employee e WHERE id BETWEEN ? AND ?";

List list = session.createQuery(hql)//

.setParameter(0, 5)// 设置参数,第1个参数的索引为0。

.setParameter(1, 15)//

.list();

>> 方式二:使用变量名

hql = "FROM Employee e WHERE id BETWEEN :idMin AND :idMax";

List list = session.createQuery(hql)//

.setParameter("idMax", 15)//

.setParameter("idMin", 5)//

.list();

当参数是集合时,一定要使用setParameterList()设置参数值

hql = "FROM Employee e WHERE id IN (:ids)";

List list = session.createQuery(hql)//

.setParameterList("ids", new Object[] { 1, 2, 3, 5, 8, 100 })//

.list();

5,使用命名查询

Query query = session.getNamedQuery("queryByIdRange");

query.setParameter("idMin", 3);

query.setParameter("idMax", 10);

List list = query.list();

6,update与delete,不会通知Session缓存

>> Update

int result = session.createQuery(//

"UPDATE Employee e SET e.name=? WHERE id>15")//

.setParameter(0, "无名氏")//

.executeUpdate(); // 返回int型的结果,表示影响了多少行。

System.out.println("result = " + result);

>> Delete

Employee.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">

<!--
auto-import表示在HQL中写类的简单名称时,是否自动导入当前这个包。
即为true时,在HQL中可以写简单名称,表示当前这个类。
当为false时,在HQL中就得写全限定名了。
默认为true。
-->
<hibernate-mapping package="cn.itcast.k_query_hql" auto-import="true">

<class name="Employee" table="employee">
<id name="id">
<generator class="native"></generator>
</id>
<property name="name" type="string" column="name"/>

<!-- department属性,表达的是本类与Department的多对一 -->
<many-to-one name="department" class="Department" column="departmentId"></many-to-one>

</class>

<!-- 定义命名的查询 -->
<query name="queryByIdRange">
<![CDATA[FROM Employee e WHERE e.id >= :idMin AND e.id <= :idMax]]>
</query>

</hibernate-mapping>


App:
package cn.itcast.k_query_hql;

import java.util.Arrays;
import java.util.List;

import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.junit.Test;

public class App {

private static SessionFactory sessionFactory = new Configuration()//
.configure()//
.addClass(Department.class)// 添加Hibernate实体类(加载对应的映射文件)
.addClass(Employee.class)// 添加Hibernate实体类(加载对应的映射文件)
.buildSessionFactory();

// 准备数据
@Test
public void testSave() throws Exception {
Session session = sessionFactory.openSession();
session.beginTransaction();
// --------------------------------------------

// 保存一些部门数据
for (int i = 1; i <= 10; i++) {
Department department = new Department();
department.setName("开发部_" + i);
session.save(department);
}

// 保存一些员工数据
for (int i = 1; i <= 20; i++) {
Employee employee = new Employee();
employee.setName("李XX_" + i);
session.save(employee);
}

// --------------------------------------------
session.getTransaction().commit();
session.close();
}

// 使用HQL查询
// HQL: Hibernate Query Language.
// 特点:
// >> 1,与SQL相似,SQL中的语法基本上都可以直接使用。
// >> 2,SQL查询的是表和表中的列;HQL查询的是对象与对象中的属性。
// >> 3,HQL的关键字不区分大小写,类名与属性名是区分大小写的。
// >> 4,SELECT可以省略.
@Test
public void testHql() throws Exception {
Session session = sessionFactory.openSession();
session.beginTransaction();
// --------------------------------------------
String hql = null;

// 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,执行查询,获得结果(list、uniqueResult、分页 )
// 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);

// 6,方法链
List list = session.createQuery(//
"FROM Employee")//
.setFirstResult(0)//
.setMaxResults(10)//
.list();

// // ----- 执行查询
// List list = session.createQuery(hql).list();
//
// ----- 显示结果
for (Object obj : list) {
if (obj.getClass().isArray()) {
System.out.println(Arrays.toString((Object[]) obj));
} else {
System.out.println(obj);
}
}

// --------------------------------------------
session.getTransaction().commit();
session.close();
}

@Test
public void testHql_2() throws Exception {
Session session = sessionFactory.openSession();
session.beginTransaction();
// --------------------------------------------
String hql = null;

// 1,聚集函数:count(), max(), min(), avg(), sum()
// hql = "SELECT COUNT(*) FROM Employee"; // 返回的结果是Long型的
// hql = "SELECT min(id) FROM Employee"; // 返回的结果是id属性的类型
// Number result = (Number) session.createQuery(hql).uniqueResult();
// System.out.println(result.getClass());
// System.out.println(result);

// 2,分组: Group By ... Having
// hql = "SELECT e.name,COUNT(e.id) FROM Employee e GROUP BY e.name";
// hql = "SELECT e.name,COUNT(e.id) FROM Employee e GROUP BY e.name HAVING count(e.id)>1";
// hql = "SELECT e.name,COUNT(e.id) FROM Employee e WHERE id<9 GROUP BY e.name HAVING count(e.id)>1";
// ---
// hql = "SELECT e.name,COUNT(e.id) " + //
// "FROM Employee e " + //
// "WHERE id<9 " + //
// "GROUP BY e.name " + //
// "HAVING count(e.id)>1 " + //
// "ORDER BY count(e.id) ASC";
// ---
// hql = "SELECT e.name,COUNT(e.id) AS c " + //
// "FROM Employee e " + //
// "WHERE id<9 " + //
// "GROUP BY e.name " + //
// "HAVING count(e.id)>1 " + // 在having子句中不能使用列别名
// "ORDER BY c ASC"; // 在orderby子句中可以使用列别名

// 3,连接查询 / HQL是面向对象的查询
// >> 内连接(inner关键字可以省略)
// hql = "SELECT e.id,e.name,d.name FROM Employee e JOIN e.department d";
// hql = "SELECT e.id,e.name,d.name FROM Employee e INNER JOIN e.department d";
// >> 左外连接(outer关键字可以省略)
// hql = "SELECT e.id,e.name,d.name FROM Employee e LEFT OUTER JOIN e.department d";
// >> 右外连接(outer关键字可以省略)
// hql = "SELECT e.id,e.name,d.name FROM Employee e RIGHT JOIN e.department d";
// 可以使用更方便的方法
// hql = "SELECT e.id,e.name,e.department.name FROM Employee e";

// 4,查询时使用参数
// >> 方式一:使用'?'占位
// hql = "FROM Employee e WHERE id BETWEEN ? AND ?";
// List list = session.createQuery(hql)//
// .setParameter(0, 5)// 设置参数,第1个参数的索引为0。
// .setParameter(1, 15)//
// .list();

// >> 方式二:使用变量名
// hql = "FROM Employee e WHERE id BETWEEN :idMin AND :idMax";
// List list = session.createQuery(hql)//
// .setParameter("idMax", 15)//
// .setParameter("idMin", 5)//
// .list();

// 当参数是集合时,一定要使用setParameterList()设置参数值
// hql = "FROM Employee e WHERE id IN (:ids)";
// List list = session.createQuery(hql)//
// .setParameterList("ids", new Object[] { 1, 2, 3, 5, 8, 100 })//
// .list();

// 5,使用命名查询
// Query query = session.getNamedQuery("queryByIdRange");
// query.setParameter("idMin", 3);
// query.setParameter("idMax", 10);
// List list = query.list();

// 6,update与delete,不会通知Session缓存
// >> Update
// int result = session.createQuery(//
// "UPDATE Employee e SET e.name=? WHERE id>15")//
// .setParameter(0, "无名氏")//
// .executeUpdate(); // 返回int型的结果,表示影响了多少行。
// System.out.println("result = " + result);
// >> Delete
int result = session.createQuery(//
"DELETE FROM Employee e WHERE id>15")//
.executeUpdate(); // 返回int型的结果,表示影响了多少行。
System.out.println("result = " + result);

// ----- 执行查询并显示结果
// // List list = session.createQuery(hql).list();
// for (Object obj : list) {
// if (obj.getClass().isArray()) {
// System.out.println(Arrays.toString((Object[]) obj));
// } else {
// System.out.println(obj);
// }
// }

// --------------------------------------------
session.getTransaction().commit();
session.close();
}

@Test
public void testHql_DML() throws Exception {
Session session = sessionFactory.openSession();
session.beginTransaction();
// --------------------------------------------

// 第一次显示名称
Employee employee = (Employee) session.get(Employee.class, 13);
System.out.println(employee.getName());

// update与delete,不会通知Session缓存
int result = session.createQuery(//
"UPDATE Employee e SET e.name=? WHERE id>10")//
.setParameter(0, "无名氏3")//
.executeUpdate(); // 返回int型的结果,表示影响了多少行。

// 第二次显示名称
// 在update或delete后,需要refresh(obj)一下以获取最新的状态
session.refresh(employee);
System.out.println(employee.getName());

// --------------------------------------------
session.getTransaction().commit();
session.close();
}

}


5、多种查询方式——qbc

package cn.itcast.k_query_qbc;

import java.util.Arrays;
import java.util.List;

import org.hibernate.Criteria;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Restrictions;
import org.junit.Test;

public class App {

private static SessionFactory sessionFactory = new Configuration()//
.configure()//
.addClass(Department.class)// 添加Hibernate实体类(加载对应的映射文件)
.addClass(Employee.class)// 添加Hibernate实体类(加载对应的映射文件)
.buildSessionFactory();

// 准备数据
@Test
public void testSave() throws Exception {
Session session = sessionFactory.openSession();
session.beginTransaction();
// --------------------------------------------

// 保存一些部门数据
for (int i = 1; i <= 10; i++) {
Department department = new Department();
department.setName("开发部_" + i);
session.save(department);
}

// 保存一些员工数据
for (int i = 1; i <= 20; i++) {
Employee employee = new Employee();
employee.setName("李XX_" + i);
session.save(employee);
}

// --------------------------------------------
session.getTransaction().commit();
session.close();
}

// 使用QBC方式查询:Query By Criteria
@Test
public void testQBC() throws Exception {
Session session = sessionFactory.openSession();
session.beginTransaction();
// --------------------------------------------

// 创建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();
// 显示结果
for (Object obj : list) {
if (obj.getClass().isArray()) {
System.out.println(Arrays.toString((Object[]) obj));
} else {
System.out.println(obj);
}
}

// --------------------------------------------
session.getTransaction().commit();
session.close();
}

}


一、一对一的关联关系映射(外键 + 唯一)

基于外键的

有外键方:<many-to-one name="obj" class=".." column=".." unique="true"/>

无外键方:<one-to-one name=".." class=".." property-ref="obj"/>

基于主键的

有外键方:<one-to-one ...>

无外键方:<one-to-one ...>

操作:

在采用基于外键的方式时:只有有外键方可以维护关联关系。

在采用基于主键的方式时:双方都不可以维护关系。

二、继承结构映射

1,整个继承结构使用一张表。列上不能有not-null="true"。

2,每个类对应一张表,抽象类也对应表。

3,每个具体类对应一张表,抽象类不对应表。

三、HQL语句

与SQL的语法类似。

HQL查询的对象、属性,所以写的时候写的是类名、属性名。

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

语法:

SELECT 别名/属性名/表达式

FROM 实体 AS 别名

WHERE 过滤条件

ORDER BY 排序条件

SELECT 别名/属性名/表达式

FROM 实体 AS 别名

WHERE 过滤条件

GROUP BY 分组条件

HAVING 分组后的结果的过滤条件

ORDER BY 排序条件
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: