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 排序条件
相关文章推荐
- windows下FTP服务器的搭建之工具Home Ftp Server
- AndroidManifest中android:persistent属性研究
- Python下MySQL数据库操作
- Serializable的好处
- 细节错误
- 《多线程之NSOPeration/NSOperationQueue》
- 一个App的界面设计流程是怎么产生的
- OpenCV 实践程序17——实现图片标注
- 请务必注意 Redis 安全配置,否则将导致轻松被入侵
- Android应用开发:页面跳转和数据传递
- 性能调优之mysql通过status性能优化 4
- Storm DRPC实现机制分析剖析
- esxi+vcenter6.0+sql2008安装手册+排错
- [BZOJ1010][HNOI2008]玩具装箱toy 斜率优化第一题
- hbase跨版本导数
- Qt头文件包含问题
- LeetCode --- House Robber & House Robber II
- 数据分页处理系列之二:HBase表数据分页处理
- iOS二维码的生成与识别
- 转战Android Studio 二