public class Customer implements Serializable { private static final long serialVersionUID = 5431991012351413505L; private Long id; private String name; private String email; …… public Customer() { } public Long getId() { return id; } public void setId(Long id) { this .id = id; } public String getName() { return name; }
Hibernate 入门
创建数据库
drop database if exists SAMPLEDB; create database SAMPLEDB; use SAMPLEDB; create table CUSTOMERS ( ID bigint not null primary key, NAME varchar(15) not null, EMAIL varchar(128) not null, PASSWORD varchar(8) not null, PHONE int , ADDRESS varchar(255), SEX char(1) , IS_MARRIED bit, DESCRIPTION text, IMAGE blob, BIRTHDAY date, REGISTERED_TIME timestamp );
TIMESTAMP REGISTERED_TIME timestamp java.sql.TimeStamp registeredTime DATE BIRTHDAY date java.sql.Date birthday BLOB CLOB BIT CHAR(1) INT Varchar(15) Sql 类型 IMAGE DESCRIPTION IS_MARRIED SEX PHONE NAME Cutomers 字段名 binary text boolean character int string hibernate byte[] java.lang.String boolean char int java.lang.String java Phone Sex Married Description Name image Customer 类属性
class Customer{ … .. private String firstname ; private String lastname ; public String getName(){ return firstname + “ ” + lastname ; } public void setName(String name){ StringTokenizer t = new StringTokenizer(name); firstname = t.nextToken(); lastname = t.nextToken(); } }
第四章 对象 - 关系映射基础
持久化类的属性及访问方法
在持久化类的方法中加入程序逻辑
在 customer.hbm.xml 文件中无需映射 firstname 和 lastname 属性,而是映射 name 属性 。
<property name =“name” column=“NAME” /> 尽管类中并没有 name 属性,由于 hibernate 不是直接访问 Name 属性,而是调用 get 、 set 方法,因此建立了 Firstname 、 Lastname 和表之间的联系。 Hibernate getName() setName() CUSTOMERS 表 Name 字段 Customer 类 firstname lastname
第四章 对象 - 关系映射基础
持久化类的属性及访问方法
在持久化类的方法中加入程序逻辑
不管在类中是否存在 name 属性,只要在 Customer.hbm.xml 文件中映射了 name 属性,在 hql 语句中就能访问他。
Session.find(“from customer as c where c.name=‘tom’”) 如果改成: <property name=“name” column=“NAME” access=“field”> 后过如何?
第四章 对象 - 关系映射基础
持久化类的属性及访问方法
在持久化类的方法中加入程序逻辑
在 customer 类的 setOrders ()方法中加入程序逻辑。
Public void setOrders(Set orders){ this.orders = orders ; calprice(); } Public calprice(){ …… setAvgPrice(avgprice); }
第四章 对象 - 关系映射基础
持久化类的属性及访问方法
在持久化类的方法中加入程序逻辑
在 setSex ()方法中加入数据验证逻辑
Public void setSex(char sex){ if(sex != ‘M’ && sex != ‘F’){ throw new IllegalArgumentException(“Invalid sex”); } this.sex = sex; }
第四章 对象 - 关系映射基础
持久化类的属性及访问方法
设置派生属性
利用 <property> 元素的 formula 属性,用来设置一个 sql 表达式, hibernate 将根据它来计算出派生属性的值。
<property name=“totalprice” formula=“(select sum(o.PRICE) from ORDERS o where o.CUSTOMER_ID=ID)” /> <property name=“unitprice” formula=“BASE_PRICE*QUANTITY” />
select max(id) from table; <id name=“id” type=“long” column=“ID”> <generator class=“increment”/> </id> 适用范围: 1 。由于不依赖与底层数据库,适合所有的数据库系统。 2 。单个进程访问同一个数据库的场合,集群环境下不推荐适用。 3 。 OID 必须为 long 、 int 或 short 类型,如果把 OID 定义为 byte 类型,抛异常。
第五章 映射对象表示符
Hibernate 内置标识符用法
Identity
由底层数据库生成标识符 . 需要把字段定义成自增型。
my sql 中为 auto_increment
ms sql server 中为 identity
<generator class=“identity” />
第五章 映射对象表示符
Hibernate 内置标识符用法
sequence
<id name=“id” type=“long” column=“ID”> <generator class=“sequence”> <param name=“sequence”>tester_id_seq</param> </generator> </id> 适用范围: 地层数据库要支持序列。 Oracle DB2 SAP 等。 OID 必须为 long 、 int 或 shot 类型。
第五章 映射对象表示符
Hibernate 内置标识符用法
hilo
<id name=“id” type=“long” clomn=“ID”> <generator name=“hilo”> <param name=“table”>hi_value</param> <param name=“column”>next_value</param> <param name=“max_lo”>100</param> </generator> </id> 使用范围: 该机制不依赖于地层数据库,因此适用于所有的数据库系统。 OID 必须为 long 、 int 、 short 类型,如果为 byte 类型的话,会抛出异常。 Net.sf.hibernate.id.IdentifierGeneratorException:this id generator generates Long 、 integer 、 short 。
第六章 映射一对多关联关系 tx = session.beginTransaction(); Customer c = new Customer(); c.setName("TOM"); session.save(c); ? 会有什么后果 Order o1 = new Order(); o1.setOrderNumber("1"); o1.setCustomer(c); Order o2 = new Order(); o2.setOrderNumber("1"); o2.setCustomer(c); session.save(o1); session.save(o2); tx.commit();
第六章 映射一对多关联关系
建立多对一的单向关联关系
<many-to-one>not-null 属性
tx = session.beginTransaction(); Customer c = new Customer(); c.setName("TOM"); //session.save(c); ? 会有什么后果 Order o1 = new Order(); o1.setOrderNumber("1"); o1.setCustomer(c); Order o2 = new Order(); o2.setOrderNumber("1"); o2.setCustomer(c); session.save(o1); session.save(o2); tx.commit();
Class Customer{ … public Set orders = new Set(); public Set getOrders(){ return orders; } public void setOrders(Set orders){ this.orders = orders; } … } <set name=“orders” cascade=“save-update”> <key column=“CUSTOMER_ID” /> <one-to-many class=“..Order” /> </set> Customer c = new Customer(“TOM”); Order o1 = new Order(“11”); O1.setCustomer(c); c.getOrders().add(o1); session.save(c); tx.commit();
Customer c = (Customer)session .load(Customer.class,new Long(2)); Order o = (Order)session.load(Order.class,new Long(2)); o.setCustomer(c); c.getOrders().add(o); tx.commit(); -------------------------------------------------------------- Update orders set …... Update orders set …… hibernate 执行两条更新语句。
Customer c = (Customer)session.load(…)); Order o = (Order)session.load(…); o.setCustomer(c); //c.getOrders().add(c); tx.commit(); -------------------------------------------------------------------- 以上代码仅设置了 order 对象的 customer 属性, hibernate 仍然会按照 order 对象的状态 的变化来同步更新数据库,执行以下 sql 语句: Update orders set order_number=‘…’,customer_id=2 where id = 2
第六章 映射一对多关联关系
映射一对多双向关联关系
<set> 元素的 inverse 属性 ( 续 )
Customer c = (Customer)session.load(……); Order o = (Order)session.load(……); //o.setCustomer(c); c.getOrders().add(c); tx.commit(); -------------------------------------------------------------------- 以上代码仅设置了 customer 对象的 orders 属性,由于 <set> 元素的 inverse 属性为 true ,因此, hibernate 不会按照 customer 对象的状态 变化来同步更新数据库。
Customer c = new Customer(“TOM”,new HashSet()); Order o1 = new Order(“Tom_order001”,null); Order o2 = new Order(“Tom_order002”,null); o1.setCustomer(c); c.getOrders().add(o1); o1 = null; o2 = null; c = null;
Query query = session.createSQLQuery(“select {c.*} from CUSTOMERS c where c.NAME like :customerName and c.AGE=:customerAge”,”c”, Customer.class); // 动态绑定参数 query.setString(“customerName”,”T%”); query.setInteger(“customerAge”,new Integer()21); // 执行 sql select 语句,返回查询结果。 List list = query.list();
第十一章 hibernate 检索方式
检索方式简介
使用别名
from Customer as c where c.name = :customerName as 可省略。
第十一章 hibernate 检索方式
检索方式简介
多态查询
session.createQuery(“from Employee”); 查询出所有的实体 from java.lang.serializable (支持接口) from java.lang.Object
第十一章 hibernate 检索方式
检索方式简介
对查询结果排序
hql 查询: session.createQuery(“from Employee c order by c.name”); qbc 查询: session.createCriteria(Customer.class) .addOrder(Order.asc(“name”));
检索方式简介
分页查询
hql 查询: session.createQuery(“from Employee c order by c.name”).setFirstResult(97) .setMaxResults(10); qbc 查询: session.createCriteria(Customer.class) .addOrder(Order.asc(“name”)) .setFirstResult(97).setMaxResult(10).list();
第十一章 hibernate 检索方式
检索方式简介
检索单个对象
hql 查询: session.createQuery(“from Employee c order by c.name”) .setMaxResults(1).uniqueResult(); qbc 查询: session.createCriteria(Customer.class) .addOrder(Order.asc(“name”)) .setMaxResult(1).uniqueResult();
第十一章 hibernate 检索方式
检索方式简介
绑定参数
hql 查询: session.createQuery(“from Employee c where c.name =:customerName”); query.setString(“customer”,”Tom”); ---------------------------------------------------- ............................c.name=? query.setString(0,”Tom”);
第十一章 hibernate 检索方式
检索方式简介
在影射文件中定义命名查询语句
<class> ....... </class> <query name=“findCustomersByName”> <![CDATA[from Cusomter c where c.name like:name]]> </query> ------------------------------------------------------------------ query = session.getNamedQuery(“findCustomersByName”); query.setString(“name”,”Tom”); query.list();
第十一章 hibernate 检索方式
设定查询条件
Express.not(Express.in()) not in Express.between() between Express.not(Express.between()) not between 含义 Express.in() Express.isNotNull() Express.isNull() Express.le() Express.lt() Express.ge() Express.not(Express.eq()) Express.eq() QBC 运算方法 in is not null is null <= < >= <> = HQL 运算符 比较运算 范围运算符 运算类型
第十一章 hibernate 检索方式
设定查询条件 ( 续 )
Expression.or()| Expression.disjunction() or Expression.not() not 含义 Expression.and()| Expression.conjunction() Expression.like() QBC 运算方法 and like HQL 运算符 字符串模式匹配 逻辑 运算类型
第十一章 hibernate 检索方式
连接查询
适用于不存在关联关系的持久化类 不支持 ClassA,ClassB 交叉连接 不支持 right out join | out join 右外连接 迫切左外连接 左外连接 隐式内连接 不支持 不支持 left out join out join FetchMode.EAGER left out join fetch out join fetch 适用于由关联关系的持久化类 适用范围 不支持 Criteria.createAlias() QBC 语法 inner join fetch | join fetch inner join | join HQL 语法 内连接 迫切内连接 程序中指定的连接查询类型
第十一章 hibernate 检索方式
连接查询
迫切左外连接
HQL: createQuery(“from Customer c left outer join fetch c.orders o where c.name like ‘T%’”); QBC: createCriteria(Customer.class).setFetchMode(“orders”,FetchMode.EAGER) .add(Expression.like(“name”,”T”,MatchMode.START))
第十一章 hibernate 检索方式
连接查询
左外连接
HQL: createQuery(“from Customer c left join c.orders o where c.name like ‘T%’”);
第十一章 hibernate 检索方式
连接查询
内连接
HQL: createQuery(“from Customer c inner join c.orders o where c.name like ‘T%’”); HQL: createQuery(“from Customer c join c.orders o where c.name like ‘T%’”); QBC: createCriteria(Customer.class). .add(Expression.like(“name”,”T”,MatchMode.START)) .createCriteria(“orders”) .add(Expression.like(“orderNumber”,”T”,MatchMode.START));
第十一章 hibernate 检索方式
连接查询
迫切内连接
HQL: createQuery(“from Customer c inner join fetch c.orders o where c.name like ‘T%’”); QBC: createCriteria(Customer.class). .setFetchMode(“orders”,FetchMode.EAGER) .createAlias(“orders”,”o”) .add(Expression.like(“this.name”,”T”,MatchMode.START)) .add(Expression.like(“o.orderNumber”,”T”,MatchMode.START))
第十一章 hibernate 检索方式
连接查询
隐式内连接
HQL: createQuery(“from Order o where o.customer.name like ‘T%’“); 等价于 : from Order o join o.customer c where c.name like ‘T%’ QBC: 不支持
第十一章 hibernate 检索方式
连接查询
右外连接
HQL: from Customer c right outer join c.orders o where o.name like ‘T%’ 等价于 : from Customer c right join c.orders o where o.name like ‘T%’
第十一章 hibernate 检索方式
连接查询
使用 SQL 风格的交叉连接和隐式内连接
HQL: 交叉连接查询 :from Customer,Order 标准 SQL 风格的内连接 :from Customer c inner join c.orders SQL 风格的隐式内连接查询 :from Customer c,Order o where c.id = o.customer_id
第十一章 hibernate 检索方式
连接查询
关联级别运行时的检索策略
1. 若在 HQL 、 QBC 代码中没有显式指定检索策
略,使用映射文件中的检索策略。但 HQL 总是忽略
映射文件中设置的迫切左外连接检索策略。
2. 若代码中显示指定了检索策略,则覆盖映射文件中
的检索策略。
3. 目前的 hibernate 版本只允许在一个查询语句中迫切
左外连接检索一个集合。
4.HQL 支持各种各样的连接查询。
第十一章 hibernate 检索方式
报表查询
投影查询
指查询结果仅包括部分实体或实体的部分属
性。通过 select 来实现。
from Customer c join c.orders o where o.orderNumber like ‘T%’ 如果希望查询结果中只包含 Customer 对象,可使用以下形式: select c from Customer c join c.orders o where o.orderNumber like T%’ session.createQuery(“select c.id,c.name,o.orderNumber from Customer c join c.orders o where o.orderNumber like ‘T%’”) ----------------------------------------------------------------------------------- 对应的 sql 语句为: select c.ID,c.NAME,o.ORDER_NUMBER from CUSTOMERS c inner join ORDERS o on c.ID-=o.CUSTOMER_ID where o.ORDER_NUMBER like’T%’ ------------------------------------------------------------------------------------ 过滤重复元素 createQuery(“select distinct c.name from customer c”);
第十一章 hibernate 检索方式
报表查询
使用聚集函数
createQuery(“select count(*) from Customer
c”).uniqueResult();
createQuery(“select avg(c.age) from Customer
c”).uniqueResult();
createQuery(“select max(c.age),min(c.age) from
Customer c”).uniqueResult();
分组查询 :
createQuery(“select c.name,count(c) from Customer group by
c.name”);
第十一章 hibernate 检索方式
高级查询技巧
动态查询: session.createCriteria(Customer.class) .add(Expression.like(“name”,name.toLowerCase()),MatchMode.ANYWHERE) .add(Expression.eq(“age”,new Integer(11))); 集合过滤: hql : createQuery(“from Order o where o.customer=:customer and o.price>100 order by o.price”).setEntity(“customer”,customer).list(); 使用集合过滤: session.createFilter(customer.getOrders(),”where this.price > 100 order by this.price”).list(); 子查询: from Customer c where 1 < (select count(o) from c.orders o); 本地 SQL 查询: String sql=“select cs.ID as {c.id},cs.NAME as {c.name},cs.AGE as {c.age} from CUSTOMERS cs where cs.ID = 1”; Query query = session.createSQLQuery(sql,”c”,Customer.class); 第二个参数是类的别名,在 SQL 语句中,每个字段的别名必须位于打括号内。
第十一章 hibernate 检索方式
查询性能优化
iterate 方法
query1=session.createQuery(“from Customer c”); List result1 = query1.list(); Query query2 = session.createQuery(“from Customer c where c.age < 30”); Iterator it = query2.iterator(); query 接口的 iterate 方法首先检索 ID 字段,然后根据 ID 字段到一级缓存、二级缓存中查 找,有则返回,否则查库。
第十一章 hibernate 检索方式
查询性能优化
查询缓存
在 hibernate.properties 中的 hibernate.cache.use_query_cache=true query = session.createQuery(“from Cusotmer c where c.age>:age”); query.setInteger(“age”,new Integer(1)); query.setCacheable(true); ------ 如果想更加细粒度的控制查询缓存,可设置缓存区域 query.setCacheRegion(“customer”)
0 comments
Post a comment