- 浏览: 29296 次
- 性别:
- 来自: 北京
-
最新评论
-
sodmewuhan:
good job!
Tomcat6.0连接器源码分析 -
cairnsfu:
楼主JSF还是很有研究的,,多多学习。
JSF -
usiboy:
这几天我也在研究HashMap,不过HashMap的精华在于算 ...
java HashMap分析 -
love2008:
希望jsf越来越好!
JSF -
fourfire:
是啊,问题很多,没法升级啊
JSF
因为公司要保持上一个员工构建的系统结构,让我接手这个项目,我第一次用起了HIBERNATE.项目是一个日志收集与展现系统.每天要收集与展现的日志一张表就将近30W.用户要求保留3个月的数据,差不多也就2000W吧. 数据的检索基本上要用到时间条件.
我在时间上建了索引,并设为不可为空. 600W数据时我采用分区表了.在PL/SQLD执行,效果还不错.连接到系统上.统计记录数居然要几分钟,有时10几分钟.因为我采用数据库分页,第一步就是统计符合条件的记录数.我感到不对了,HIBERNATE这么差吗.
起初的代码是这样的(只粘了统计记录数这一步):
看别人都用HSQL,我想别用Criteria 了,可能性能真不行吧.换:
这一下终于有了起色,大功告成.然而危险又发生了.终计一天的数据时,起止时间都是'2009-10-15' 居然为0,
库里明显有数据呀(库时是ORACLE的DATE类型).把结束时间换成'2009-10-16'结果出来了.我突然间想到可能是
Hibernate.DATE只传了年月日部分.打开Hibernate源码:
不出所料,果然如此.这时却有了意外收获,不好意思,时间紧文档看得少.
这不正是我要的吗.OK换成 Hibernate.TIMESTAMP吧:
这里性能又降到刚开始的状态.为什么两个都不可用呢,查文档,也没找到可用信息.
通过ORACLE查看绑字信息:
Code
select t.HASH_VALUE,
t.datatype,
t.NAME,
t.LAST_CAPTURED,
t.WAS_CAPTURED,
t.VALUE_STRING,
t.VALUE_ANYDATA
from v$sql_bind_capture t
where sql_id = (select sql_id--,bind_data
from v$sqlarea
where sql_text like '%log.id%')
从输出发现Hibernate.Date时,绑字是Date类型,但时分秒都为0,明显不对.Hibernate.TIMESTAMP时绑定的是
TIMESTAMP类型.据我对ORACLE的理解,肯定是该字段的类型DATE发生了隐式类型转换,导致索引无效了.
验证:
SQL> select * from stmmlog where eventreportedtime = cast(sysdate as timestamp)
2 /
未选定行
已用时间: 00: 06: 40.53
执行计划
----------------------------------------------------------
Plan hash value: 2651278941
--------------------------------------------------------------------------------
---------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
Pstart| Pstop |
--------------------------------------------------------------------------------
---------------
| 0 | SELECT STATEMENT | | 66490 | 55M| 321K (1)| 01:04:18 |
| |
| 1 | PARTITION RANGE ALL| | 66490 | 55M| 321K (1)| 01:04:18 |
1 | 9 |
|* 2 | TABLE ACCESS FULL | STMMLOG | 66490 | 55M| 321K (1)| 01:04:18 |
1 | 9 |
--------------------------------------------------------------------------------
---------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - filter(INTERNAL_FUNCTION("EVENTREPORTEDTIME")=CAST(SYSDATE@! AS timestamp
))
统计信息
----------------------------------------------------------
1 recursive calls
0 db block gets
1883117 consistent gets
1866294 physical reads
116 redo size
1482 bytes sent via SQL*Net to client
389 bytes received via SQL*Net from client
1 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
0 rows processed
果真如此,无办法了,改TO_DATE吧,我最初放弃的(因为与数据库偶合),却是我的最终选择.呵呵,有恋爱的感觉?
Code
我在时间上建了索引,并设为不可为空. 600W数据时我采用分区表了.在PL/SQLD执行,效果还不错.连接到系统上.统计记录数居然要几分钟,有时10几分钟.因为我采用数据库分页,第一步就是统计符合条件的记录数.我感到不对了,HIBERNATE这么差吗.
起初的代码是这样的(只粘了统计记录数这一步):
public int getLogsCount(StmmLog log) throws SyslogException { try { Criteria criteria = getSession().createCriteria(StmmLog.class); attachRestrictions(criteria, log); criteria.setProjection(Projections.rowCount()); return ((Integer) criteria.uniqueResult()).intValue(); } catch (RuntimeException re) { throw new SyslogException(re, this.getClass(), "银企日志条件查询获得纪录数异常"); } finally { getSession().close(); } } private void attachRestrictions(Criteria criteria, StmmLog log) { if (StringUtils.isNotBlank(log.getFromHost())) { criteria.add(Restrictions.like("fromHost", log.getFromHost(), MatchMode.ANYWHERE)); } if (StringUtils.isNotBlank(log.getFromHostIp())) { criteria.add(Restrictions.eq("fromHostIp", log.getFromHostIp())); } if (null != log.getEventReportedTime()) { criteria.add(Restrictions.ge("eventReportedTime", log .getEventReportedTime())); } if (null != log.getEventReportedEndTime()) { criteria.add(Restrictions.le("eventReportedTime", new Date(log .getEventReportedEndTime().getTime() + 1 * 24 * 3600 * 1000 - 1))); } } public int getLogsCount(StmmLog log) throws SyslogException { try { Criteria criteria = getSession().createCriteria(StmmLog.class); attachRestrictions(criteria, log); criteria.setProjection(Projections.rowCount()); return ((Integer) criteria.uniqueResult()).intValue(); } catch (RuntimeException re) { throw new SyslogException(re, this.getClass(), "银企日志条件查询获得纪录数异常"); } finally { getSession().close(); } } private void attachRestrictions(Criteria criteria, StmmLog log) { if (StringUtils.isNotBlank(log.getFromHost())) { criteria.add(Restrictions.like("fromHost", log.getFromHost(), MatchMode.ANYWHERE)); } if (StringUtils.isNotBlank(log.getFromHostIp())) { criteria.add(Restrictions.eq("fromHostIp", log.getFromHostIp())); } if (null != log.getEventReportedTime()) { criteria.add(Restrictions.ge("eventReportedTime", log .getEventReportedTime())); } if (null != log.getEventReportedEndTime()) { criteria.add(Restrictions.le("eventReportedTime", new Date(log .getEventReportedEndTime().getTime() + 1 * 24 * 3600 * 1000 - 1))); } }
看别人都用HSQL,我想别用Criteria 了,可能性能真不行吧.换:
public int getLogsCount(OracleAlarmLog log) throws SyslogException { try { // Criteria criteria = getSession().createCriteria( // OracleAlarmLog.class); // attachRestrictions(criteria, log); // // criteria.setProjection(Projections.count("id")); StringBuffer sb = new StringBuffer( "select count(log.id) from OracleAlarmLog log where 1=1 "); List<SQLParameter> lst = addRestrictions(sb, log); Object[] values = new Object[lst.size()]; Type[] types = new Type[lst.size()]; for (int i = 0; i < lst.size(); i++) { values[i] = lst.get(i).getValue(); types[i] = lst.get(i).getType(); } Query query = getSession().createSQLQuery(sb.toString()); query.setParameters(values, types); BigDecimal ret = (BigDecimal) query.uniqueResult(); return ret.intValue(); // return ((Integer) criteria.uniqueResult()).intValue(); } catch (RuntimeException re) { throw new SyslogException(re, this.getClass(), "获取ORACLE日志记录数异常"); } finally { getSession().close(); } } private List<SQLParameter> addRestrictions(StringBuffer sb, StmmLog log) { List<SQLParameter> lst = new ArrayList<SQLParameter>(); if (StringUtils.isNotBlank(log.getFromHost())) { sb.append(" AND fromHost like ?"); lst.add(new SQLParameter("%" + log.getFromHost() + "%", Hibernate.STRING)); } if (StringUtils.isNotBlank(log.getFromHostIp())) { sb.append(" AND fromHostIp = ?"); lst.add(new SQLParameter(log.getFromHostIp(), Hibernate.STRING)); } if (null != log.getEventReportedTime()) { sb.append(" AND eventReportedTime >= ?"); lst .add(new SQLParameter(log.getEventReportedTime(), Hibernate.DATE)); } if (null != log.getEventReportedEndTime()) { sb.append(" AND eventReportedTime <= ?"); lst.add(new SQLParameter(new Date(log.getEventReportedEndTime() .getTime() + 1 * 24 * 3600 * 1000 - 1), Hibernate.DATE)); } return lst; } public int getLogsCount(OracleAlarmLog log) throws SyslogException { try { // Criteria criteria = getSession().createCriteria( // OracleAlarmLog.class); // attachRestrictions(criteria, log); // // criteria.setProjection(Projections.count("id")); StringBuffer sb = new StringBuffer( "select count(log.id) from OracleAlarmLog log where 1=1 "); List<SQLParameter> lst = addRestrictions(sb, log); Object[] values = new Object[lst.size()]; Type[] types = new Type[lst.size()]; for (int i = 0; i < lst.size(); i++) { values[i] = lst.get(i).getValue(); types[i] = lst.get(i).getType(); } Query query = getSession().createSQLQuery(sb.toString()); query.setParameters(values, types); BigDecimal ret = (BigDecimal) query.uniqueResult(); return ret.intValue(); // return ((Integer) criteria.uniqueResult()).intValue(); } catch (RuntimeException re) { throw new SyslogException(re, this.getClass(), "获取ORACLE日志记录数异常"); } finally { getSession().close(); } } private List<SQLParameter> addRestrictions(StringBuffer sb, StmmLog log) { List<SQLParameter> lst = new ArrayList<SQLParameter>(); if (StringUtils.isNotBlank(log.getFromHost())) { sb.append(" AND fromHost like ?"); lst.add(new SQLParameter("%" + log.getFromHost() + "%", Hibernate.STRING)); } if (StringUtils.isNotBlank(log.getFromHostIp())) { sb.append(" AND fromHostIp = ?"); lst.add(new SQLParameter(log.getFromHostIp(), Hibernate.STRING)); } if (null != log.getEventReportedTime()) { sb.append(" AND eventReportedTime >= ?"); lst .add(new SQLParameter(log.getEventReportedTime(), Hibernate.DATE)); } if (null != log.getEventReportedEndTime()) { sb.append(" AND eventReportedTime <= ?"); lst.add(new SQLParameter(new Date(log.getEventReportedEndTime() .getTime() + 1 * 24 * 3600 * 1000 - 1), Hibernate.DATE)); } return lst; }
这一下终于有了起色,大功告成.然而危险又发生了.终计一天的数据时,起止时间都是'2009-10-15' 居然为0,
库里明显有数据呀(库时是ORACLE的DATE类型).把结束时间换成'2009-10-16'结果出来了.我突然间想到可能是
Hibernate.DATE只传了年月日部分.打开Hibernate源码:
public class DateType extends MutableType implements IdentifierType, LiteralType { private static final String DATE_FORMAT = "dd MMMM yyyy"; public Object get(ResultSet rs, String name) throws SQLException { return rs.getDate(name); } public Class getReturnedClass() { return java.util.Date.class; } public void set(PreparedStatement st, Object value, int index) throws SQLException { Date sqlDate; if ( value instanceof Date) { sqlDate = (Date) value; } else { sqlDate = new Date( ( (java.util.Date) value ).getTime() ); } st.setDate(index, sqlDate); } public int sqlType() { return Types.DATE; } public boolean isEqual(Object x, Object y) { if (x==y) return true; if (x==null || y==null) return false; java.util.Date xdate = (java.util.Date) x; java.util.Date ydate = (java.util.Date) y; if ( xdate.getTime()==ydate.getTime() ) return true; Calendar calendar1 = java.util.Calendar.getInstance(); Calendar calendar2 = java.util.Calendar.getInstance(); calendar1.setTime( xdate ); calendar2.setTime( ydate ); return Hibernate.CALENDAR_DATE.isEqual(calendar1, calendar2); } public int getHashCode(Object x, EntityMode entityMode) { Calendar calendar = java.util.Calendar.getInstance(); calendar.setTime( (java.util.Date) x ); return Hibernate.CALENDAR_DATE.getHashCode(calendar, entityMode); } public String getName() { return "date"; } public String toString(Object val) { return new SimpleDateFormat(DATE_FORMAT).format( (java.util.Date) val ); } } public class DateType extends MutableType implements IdentifierType, LiteralType { private static final String DATE_FORMAT = "dd MMMM yyyy"; public Object get(ResultSet rs, String name) throws SQLException { return rs.getDate(name); } public Class getReturnedClass() { return java.util.Date.class; } public void set(PreparedStatement st, Object value, int index) throws SQLException { Date sqlDate; if ( value instanceof Date) { sqlDate = (Date) value; } else { sqlDate = new Date( ( (java.util.Date) value ).getTime() ); } st.setDate(index, sqlDate); } public int sqlType() { return Types.DATE; } public boolean isEqual(Object x, Object y) { if (x==y) return true; if (x==null || y==null) return false; java.util.Date xdate = (java.util.Date) x; java.util.Date ydate = (java.util.Date) y; if ( xdate.getTime()==ydate.getTime() ) return true; Calendar calendar1 = java.util.Calendar.getInstance(); Calendar calendar2 = java.util.Calendar.getInstance(); calendar1.setTime( xdate ); calendar2.setTime( ydate ); return Hibernate.CALENDAR_DATE.isEqual(calendar1, calendar2); } public int getHashCode(Object x, EntityMode entityMode) { Calendar calendar = java.util.Calendar.getInstance(); calendar.setTime( (java.util.Date) x ); return Hibernate.CALENDAR_DATE.getHashCode(calendar, entityMode); } public String getName() { return "date"; } public String toString(Object val) { return new SimpleDateFormat(DATE_FORMAT).format( (java.util.Date) val ); } }
不出所料,果然如此.这时却有了意外收获,不好意思,时间紧文档看得少.
public static final NullableType TIMESTAMP = new TimestampType(); public class TimestampType extends MutableType implements VersionType, LiteralType { private static final String TIMESTAMP_FORMAT = "yyyy-MM-dd HH:mm:ss"; public Object get(ResultSet rs, String name) throws SQLException { return rs.getTimestamp(name); } public Class getReturnedClass() { return java.util.Date.class; } public void set(PreparedStatement st, Object value, int index) throws SQLException { Timestamp ts; if (value instanceof Timestamp) { ts = (Timestamp) value; } else { ts = new Timestamp( ( (java.util.Date) value ).getTime() ); } st.setTimestamp(index, ts); } } public static final NullableType TIMESTAMP = new TimestampType(); public class TimestampType extends MutableType implements VersionType, LiteralType { private static final String TIMESTAMP_FORMAT = "yyyy-MM-dd HH:mm:ss"; public Object get(ResultSet rs, String name) throws SQLException { return rs.getTimestamp(name); } public Class getReturnedClass() { return java.util.Date.class; } public void set(PreparedStatement st, Object value, int index) throws SQLException { Timestamp ts; if (value instanceof Timestamp) { ts = (Timestamp) value; } else { ts = new Timestamp( ( (java.util.Date) value ).getTime() ); } st.setTimestamp(index, ts); } }
这不正是我要的吗.OK换成 Hibernate.TIMESTAMP吧:
private List<SQLParameter> addRestrictions(StringBuffer sb, StmmLog log) { List<SQLParameter> lst = new ArrayList<SQLParameter>(); if (StringUtils.isNotBlank(log.getFromHost())) { sb.append(" AND fromHost like ?"); lst.add(new SQLParameter("%" + log.getFromHost() + "%", Hibernate.STRING)); } if (StringUtils.isNotBlank(log.getFromHostIp())) { sb.append(" AND fromHostIp = ?"); lst.add(new SQLParameter(log.getFromHostIp(), Hibernate.STRING)); } if (null != log.getEventReportedTime()) { sb.append(" AND eventReportedTime >= ?"); lst .add(new SQLParameter(log.getEventReportedTime(), Hibernate.TIMESTAMP)); } if (null != log.getEventReportedEndTime()) { sb.append(" AND eventReportedTime <= ?"); lst.add(new SQLParameter(new Date(log.getEventReportedEndTime() .getTime() + 1 * 24 * 3600 * 1000 - 1), Hibernate.TIMESTAMP)); } return lst; } private List<SQLParameter> addRestrictions(StringBuffer sb, StmmLog log) { List<SQLParameter> lst = new ArrayList<SQLParameter>(); if (StringUtils.isNotBlank(log.getFromHost())) { sb.append(" AND fromHost like ?"); lst.add(new SQLParameter("%" + log.getFromHost() + "%", Hibernate.STRING)); } if (StringUtils.isNotBlank(log.getFromHostIp())) { sb.append(" AND fromHostIp = ?"); lst.add(new SQLParameter(log.getFromHostIp(), Hibernate.STRING)); } if (null != log.getEventReportedTime()) { sb.append(" AND eventReportedTime >= ?"); lst .add(new SQLParameter(log.getEventReportedTime(), Hibernate.TIMESTAMP)); } if (null != log.getEventReportedEndTime()) { sb.append(" AND eventReportedTime <= ?"); lst.add(new SQLParameter(new Date(log.getEventReportedEndTime() .getTime() + 1 * 24 * 3600 * 1000 - 1), Hibernate.TIMESTAMP)); } return lst; }
这里性能又降到刚开始的状态.为什么两个都不可用呢,查文档,也没找到可用信息.
通过ORACLE查看绑字信息:
Code
select t.HASH_VALUE,
t.datatype,
t.NAME,
t.LAST_CAPTURED,
t.WAS_CAPTURED,
t.VALUE_STRING,
t.VALUE_ANYDATA
from v$sql_bind_capture t
where sql_id = (select sql_id--,bind_data
from v$sqlarea
where sql_text like '%log.id%')
从输出发现Hibernate.Date时,绑字是Date类型,但时分秒都为0,明显不对.Hibernate.TIMESTAMP时绑定的是
TIMESTAMP类型.据我对ORACLE的理解,肯定是该字段的类型DATE发生了隐式类型转换,导致索引无效了.
验证:
SQL> select * from stmmlog where eventreportedtime = cast(sysdate as timestamp)
2 /
未选定行
已用时间: 00: 06: 40.53
执行计划
----------------------------------------------------------
Plan hash value: 2651278941
--------------------------------------------------------------------------------
---------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
Pstart| Pstop |
--------------------------------------------------------------------------------
---------------
| 0 | SELECT STATEMENT | | 66490 | 55M| 321K (1)| 01:04:18 |
| |
| 1 | PARTITION RANGE ALL| | 66490 | 55M| 321K (1)| 01:04:18 |
1 | 9 |
|* 2 | TABLE ACCESS FULL | STMMLOG | 66490 | 55M| 321K (1)| 01:04:18 |
1 | 9 |
--------------------------------------------------------------------------------
---------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - filter(INTERNAL_FUNCTION("EVENTREPORTEDTIME")=CAST(SYSDATE@! AS timestamp
))
统计信息
----------------------------------------------------------
1 recursive calls
0 db block gets
1883117 consistent gets
1866294 physical reads
116 redo size
1482 bytes sent via SQL*Net to client
389 bytes received via SQL*Net from client
1 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
0 rows processed
果真如此,无办法了,改TO_DATE吧,我最初放弃的(因为与数据库偶合),却是我的最终选择.呵呵,有恋爱的感觉?
Code
private List<SQLParameter> addRestrictions(StringBuffer sb, StmmLog log) { SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd"); List<SQLParameter> lst = new ArrayList<SQLParameter>(); if (StringUtils.isNotBlank(log.getFromHost())) { sb.append(" AND fromHost like ?"); lst.add(new SQLParameter("%" + log.getFromHost() + "%", Hibernate.STRING)); } if (StringUtils.isNotBlank(log.getFromHostIp())) { sb.append(" AND fromHostIp = ?"); lst.add(new SQLParameter(log.getFromHostIp(), Hibernate.STRING)); } if (null != log.getEventReportedTime()) { sb .append(" AND eventReportedTime >= to_date(?,'yyyy-MM-dd HH24:mi:ss')"); lst.add(new SQLParameter(sf.format(log.getEventReportedTime()) + " 00:00:00", Hibernate.STRING)); } if (null != log.getEventReportedEndTime()) { sb .append(" AND eventReportedTime <= to_date(?,'yyyy-MM-dd HH24:mi:ss')"); lst.add(new SQLParameter(sf.format(log.getEventReportedTime()) + " 23:59:59", Hibernate.STRING)); } }如果仁兄看过这篇文章之后,有更好的方法.请留言我会代表项目组成员感谢你.
相关推荐
本教程将深入探讨"day36-hibernate检索和优化 02-Hibernate检索方式:简单查询及别名查询"的主题,通过源码分析和实际工具的应用,来提升数据库查询的效率。 首先,我们了解Hibernate的检索方式。在Hibernate中,...
本人在厦门邦初培训时候 使用...Session清理缓存的时间点 对象的临时状态、持久状态和游离状态 用session的update()方法使游离对象转变为持久化对象。 延迟装载 迫切左外链接 HQL检索方式 QBC检索方式 本地SQL检索方式
Hibernate 诞生于 2001 年 11 月,是 Gavin King 业余时间的个人作品,后被 JBoss 采纳,成为其主力推广产品。Gavin King 目前已经成为 EJB3.0 专家委员, JBoss 的核心成员。 3. Hibernate 的核心思想 Hibernate ...
此段代码中,首先设置了时间到2007年的1月1日零时,然后通过`add()` 方法添加两个查询条件:价格大于50元且出版日期晚于2007年1月1日。 ##### 3. 模糊查询 ```java Criteria criteria = session.createCriteria...
这主要是为了解决内存的不稳定性和容量限制问题,并满足业务数据共享、大规模数据检索和数据管理的需求。 在企业级应用中,对象序列化适合少量对象的持久化,但不符合大规模查询和长时间保存的需求。因此,除了对象...
### Hibernate知识点总结 #### 一、Hibernate概述 ...通过以上内容,我们了解了Hibernate的基本概念、配置步骤、核心类以及查询语言和检索策略等内容,这对于高效地使用Hibernate框架是非常有帮助的。
4. **配置 Ehcache**:在 Hibernate 的 `hibernate.cfg.xml` 文件中,需要引入 Ehcache 的配置,包括指定缓存 provider、设置缓存区域、定义缓存策略(如时间过期、大小限制等)。 5. **缓存策略**:Ehcache 提供了...
2. **Session API**:Hibernate 的 Session 接口是数据库操作的核心,负责对象的持久化、检索、更新和删除等操作。Session 提供了事务管理和缓存管理的功能。 3. **Criteria 查询**:除了传统的 HQL(Hibernate ...
通过深入学习Hibernate 4.1.4.Final的源码,我们可以更好地理解其设计思想,提升我们的编程技巧,同时也能为日常开发中遇到的问题提供解决方案。这是一份宝贵的资源,无论是对于初学者还是经验丰富的开发者,都值得...
此外,它还支持对时间序列数据的检索,适合于日志分析、监控系统等领域。 最后,书中会涵盖一些实际案例和最佳实践,帮助读者将所学知识应用于真实项目。读者将学会如何在项目中集成Hibernate Search,避免常见的...
综上所述,“邹波hibernate50讲”视频教程覆盖了Hibernate框架的基础知识、实体类设计、对象-关系映射、查询检索、性能优化以及一些高级特性等内容。对于初学者来说,这是一个全面了解并掌握Hibernate技术的好资源。
通过以上内容的学习,我们可以了解到 Hibernate 的缓存机制不仅可以显著提高应用程序的性能,还能帮助开发者更好地理解和优化数据库交互过程中的性能问题。对于开发基于 Hibernate 的大型应用来说,熟悉和掌握这些...
**hibernate实践** 在Java世界中,Hibernate是一个强大的对象关系映射(ORM)框架,它简化了数据库操作,使得开发者可以使用面向对象的方式...务必花时间仔细研读并实践其中的示例,这将对你的Java开发事业大有裨益。
11.1.2 Java时间和日期类型的Hibernate映射类型 11.1.3 Java大对象类型的Hibernate映射类型 11.1.4 JDK自带的个别Java类的Hibernate映射类型 11.1.5 使用Hibernate内置映射类型 11.2 客户化映射类型 ...
3. **Criteria API** 和 **HQL(Hibernate Query Language)**:Criteria API提供了一种动态构建查询的方式,而HQL则是Hibernate特有的面向对象的查询语言,它们都用于检索数据,提供了比原生SQL更高级别的抽象。...
- **学习曲线较陡峭**: 对于初学者来说,理解ORM和Hibernate的工作原理需要一定时间。 - **效率问题**: 虽然有缓存机制,但过度使用ORM可能导致性能下降。 - **SQL灵活性降低**: 直接编写SQL可以获得更高的控制力,...
3. **Session和Transaction**: Session是Hibernate的主要工作单元,负责保存、更新和检索对象。Transaction管理数据库操作,确保数据一致性。 4. **查询语言**: HQL(Hibernate Query Language)是Hibernate的SQL...
### Hibernate开发指南...通过阅读本书,读者不仅可以学习到如何使用Hibernate来解决常见的数据持久化问题,还可以了解到如何利用Hibernate与其他框架(如Spring)进行高效集成,以构建高性能、高可用性的企业级应用。
此外,Hibernate还提供了数据查询和检索的设施,可以显著减少使用SQL和JDBC手动处理数据的时间。 Hibernate5.2.11是该框架的最新版本之一,它为开发者提供了一个用户手册,详细介绍了各个功能模块和最佳实践。用户...