1. 持久化类:
Department.java
public class Department {
private Integer id;
private String name;
private Set<Employee> emps = new HashSet<Employee>();
省略getter和setter
}
Employee.java
public class Employee {
private Integer id;
private String name;
private float salary;
private String email;
private Department dept;
省略getter和setter
}
2. 对象关系映射hbm.xml
Department.hbm.xml
<hibernate-mapping package="com.baidu.entities">
<class name="Department" table="BB_DEPARTMENTS">
<id name="id" type="java.lang.Integer">
<column name="ID" />
<generator class="native" />
</id>
<property name="name" type="java.lang.String">
<column name="NAME" />
</property>
<set name="emps" table="BB_EMPLOYEES" inverse="true" lazy="true">
<key>
<column name="DEPT_ID" />
</key>
<one-to-many class="Employee" />
</set>
</class>
</hibernate-mapping>
Employee.hbm.xml
<hibernate-mapping package="com.baidu.entities">
<class name="Employee" table="BB_EMPLOYEES">
<id name="id" type="java.lang.Integer">
<column name="ID" />
<generator class="native" />
</id>
<property name="name" type="java.lang.String">
<column name="NAME" />
</property>
<property name="salary" type="float">
<column name="SALARY" />
</property>
<property name="email" type="java.lang.String">
<column name="EMAIL" />
</property>
<many-to-one name="dept" class="Department" >
<column name="DEPT_ID" />
</many-to-one>
</class>
<query name="salaryEmps"><![CDATA[FROM Employee e WHERE e.salary > :minSal AND e.salary < :maxSal ]]></query>
</hibernate-mapping>
3 测试 与详解
package com.baidu.test;
import java.util.Arrays;
import java.util.List;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.service.ServiceRegistryBuilder;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import com.baidu.entities.Department;
import com.baidu.entities.Employee;
public class TestHQL {
private SessionFactory sessionFactory;
private Session session;
private Transaction transaction;
@Before
public void init(){
Configuration configuration = new Configuration().configure();
ServiceRegistry serviceRegistry = new ServiceRegistryBuilder()
.applySettings(configuration.getProperties())
.buildServiceRegistry();
sessionFactory = configuration.buildSessionFactory(serviceRegistry);
session = sessionFactory.openSession();
transaction = session.beginTransaction();
}
@After
public void destroy(){
transaction.commit();
session.close();
sessionFactory.close();
}
@Test
public void testHQL(){
/**
* HQL 语句
* 方式一: 基于位置的参数
* String hql = "FROM Employee e WHERE e.salary > ? AND e.email LIKE ? ";
*
* query.setFloat(0, 6000)
* .setString(1, "%A%");
*
* 方式二 :基于命名的参数
* String hql = "FROM Employee e WHERE e.salary > :sal AND e.email LIKE :email ";
*
* query.setFloat("sal", 6000)
* .setString("email", "%A%");
*
* 可以添加order by 使其排序
* 样式如下:
* String hql = "FROM Employee e WHERE e.salary > :sal order by e.salary ";
*
*
* 注意: 以我现在有限的知识:貌似 基于位置的参数和 基于命名的参数,二者不可混用!
*
* 绑定参数:
* Hibernate 的参数绑定机制依赖于 JDBC API 中的 PreparedStatement 的预定义 SQL 语句功能.
* HQL 的参数绑定由两种形式:
* 按参数名字绑定: 在 HQL 查询语句中定义命名参数, 命名参数以 “:” 开头.
* 按参数位置绑定: 在 HQL 查询语句中用 “?” 来定义参数位置
* 相关方法:
* setEntity(): 把参数与一个持久化类绑定
* setParameter(): 绑定任意类型的参数. 该方法的第三个参数显式指定 Hibernate 映射类型
* HQL 采用 ORDER BY 关键字对查询结果排序
*/
//1. 创建Query 对象 使用实体对象的名称一定要和类中的一致如:Department 的对象名称一定要和 Employee 类中定义的 一致为 dept 而不能是deptm 等其他的名称,否则查询不能成功。
String hql = "FROM Employee e WHERE e.salary > ? AND e.email LIKE ? and e.dept = ? order by e.salary ";
Query query = session.createQuery(hql);
//2. 绑定参数
// Query 对象调用setXxx()方法,支持方法链的编程风格
Department dept = new Department();
dept.setId(80);
query.setFloat(0, 6000)
.setString(1, "%A%")
.setEntity(2, dept);
//3. 执行查询
List<Employee> emps = query.list();
System.out.println(emps.size());
}
/**
* 分页查询:
* setFirstResult(int firstResult): 设定从哪一个对象开始检索, 参数 firstResult
* 表示这个对象在查询结果中的索引位置, 索引位置的起始值为 0. 默认情况下,
* Query 从查询结果中的第一个对象开始检索
* setMaxResults(int maxResults): 设定一次最多检索出的对象的数目. 在默认情况下,
* Query 和 Criteria 接口检索出查询结果中所有的对象
*/
@Test
public void testPageQuery(){
String hql = "FROM Employee";
Query query = session.createQuery(hql);
int pageNo = 22;
int pageSize = 5;
List<Employee> emps = query.setFirstResult((pageNo-1)*pageSize)
.setMaxResults(pageSize)
.list();
System.out.println(emps);
}
/**
* 命名查询语句
*
* 在映射文件中定义命名查询语句
* 1. Hibernate 允许在映射文件中定义字符串形式的查询语句.
* 2. <query> 元素用于定义一个 HQL 查询语句, 它和 <class> 元素并列.
*
* <query name="salaryEmps"><![CDATA[FROM Employee e WHERE e.salary > :minSal AND e.salary < :maxSal ]]></query>
*
* 3. 在程序中通过 Session 的 getNamedQuery() 方法获取查询语句对应的 Query 对象.
*/
@Test
public void testNameQuery(){
Query query = session.getNamedQuery("salaryEmps");
List<Employee> emps = query.setFloat("minSal", 5000)
.setFloat("maxSal", 10000)
.list();
System.out.println(emps.size());
// 相当于的SQL: select * from bb_employees where salary > 5000 and salary < 10000 order by id;
}
/**
* 投影查询: 查询结果仅包含实体的部分属性. 通过 SELECT 关键字实现.
*
* 1. Query 的 list() 方法返回的集合中包含的是数组类型的元素,
* 每个对象数组代表查询结果的一条记录
* String hql = "SELECT e.dept, e.email,e.salary FROM Employee e WHERE e.dept = :dept";
* Query query = session.createQuery(hql);
*
* Department dept = new Department();
* dept.setId(80);
*
* List<Object[]> result = query.setEntity("dept", dept).list();
* for(Object[] objs:result ){
* System.out.println(Arrays.asList(objs));
* }
*
* 2. 可以在持久化类中定义一个对象的构造器来包装投影查询返回的记录,
* 使程序代码能完全运用面向对象的语义来访问查询结果集.
* String hql = "SELECT new Employee(e.dept, e.email,e.salary)"
* + "FROM Employee e "
* + "WHERE e.dept = :dept";
* Query query = session.createQuery(hql);
*
* Department dept = new Department();
* dept.setId(80);
*
* List<Employee> result = query.setEntity("dept", dept).list();
* for(Employee emp:result ){
* System.out.println(emp.getDept()+ ", " + emp.getEmail()+ ", " + emp.getSalary());
* }
*
* 3. 可以通过 DISTINCT 关键字来保证查询结果不会返回重复元素
*
*/
@Test
public void testPropertyQuery(){
String hql = "SELECT new Employee(e.dept, e.email,e.salary)"
+ "FROM Employee e "
+ "WHERE e.dept = :dept";
Query query = session.createQuery(hql);
Department dept = new Department();
dept.setId(80);
List<Employee> result = query.setEntity("dept", dept).list();
for(Employee emp:result ){
System.out.println(emp.getDept()+ ", " + emp.getEmail()+ ", " + emp.getSalary());
}
}
/**
* 报表查询
*
* 1. 报表查询用于对数据分组和统计, 与 SQL 一样, HQL 利用 GROUP BY 关键字对数据分组,
* 用 HAVING 关键字对分组数据设定约束条件.
*
* 2. 在 HQL 查询语句中可以调用以下聚集函数
* count()
* min()
* max()
* sum()
* avg()
*/
@Test
public void testGroupBy(){
String hql = "SELECT min(e.salary),max(e.salary) "
+ "FROM Employee e "
+ "Group BY e.dept "
+ "Having min(salary) > :minSal";
Query query = session.createQuery(hql)
.setFloat("minSal", 5000)
;
List<Object[]> result = query.list();
for(Object[] objs:result ){
System.out.println(Arrays.asList(objs));
}
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~hql 还支持删除和修改 的 操作~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// HQL 的删除
@Test
public void testHQLDelete(){
String hql = "DELETE FROM Department d WHERE d.id = :id";
Query query = session.createQuery(hql);
query.setFloat("id", 280)
.executeUpdate();
}
// HQL 的更新
@Test
public void testHQLUpdate(){
String hql = "UPDATE Department d SET d.name = ? WHERE d.id = ?";
Query query = session.createQuery(hql);
query.setText(0, "ChuckHero")
.setFloat(1, 280)
.executeUpdate();
}
}