在数据库中条件查询速度很慢的时候如何优化?
建索引
减少表之间的关联
优化sql尽量让sql很快定位数据不要让sql做全表查询应该走索引把数据量大的表排在前面
简化查询字段没用的字段不要已经对返回结果的控制尽量返回少量数据
在hibernate中进行多表查询每个表中各取几个字段也就是说查询出来的结果集并没有一个实体类与之对应如何解决这个问题?
解决方案一按照Object[]数据取出数据然后自己组bean
解决方案二对每个表的bean写构造函数比如表一要查出fieldfield两个字段那么有一个构造函数就是Bean(type filedtype field) 然后在hql里面就可以直接生成这个bean了具体怎么用请看相关文档我说的不是很清楚
sessionload()和sessionget()的区别
Sessionload/get方法均可以根据指定的实体类和id从数据库读取记录并返回与之对应的实体对象其区别在于
如果未能发现符合条件的记录get方法返回null而load方法会抛出一个ObjectNotFoundException
Load方法可返回实体的代理类实例而get方法永远直接返回实体类
load方法可以充分利用内部缓存和二级缓存中的现有数据而get方法则仅仅在内部缓存中进行数据查找如没有发现对应数据将越过二级缓存直接调用SQL完成数据读取
Session在加载实体对象时将经过的过程
首先Hibernate中维持了两级缓存第一级缓存由Session实例维护其中保持了Session当前所有关联实体的数据也称为内部缓存而第二级缓存则存在于
SessionFactory层次由当前所有由本SessionFactory构造的Session实例共享出于性能考虑避免无谓的数据库访问Session在调用数据库查询功能之前会
先在缓存中进行查询首先在第一级缓存中通过实体类型和id进行查找如果第一级缓存查找命中且数据状态合法则直接返回
之后Session会在当前NonExists记录中进行查找如果NonExists记录中存在同样的查询条件则返回null NonExists记录了当前Session实例在之前所有查询操作中未能查询到有效数据的查询条件(相当于一个查询黑名单列表)如此一来如果 Session中一个无效的查询条件重复出现即可迅速作出判断从而获得最佳的性能表现
对于load方法而言如果内部缓存中未发现有效数据则查询第二级缓存如果第二级缓存命中则返回
如在缓存中未发现有效数据则发起数据库查询操作(Select SQL)如经过查询未发现对应记录则将此次查询的信息在NonExists中加以记录并返回null
根据映射配置和Select SQL得到的ResultSet创建对应的数据对象
将其数据对象纳入当前Session实体管理容器(一级缓存)
执行InterceptoronLoad方法(如果有对应的Interceptor)
将数据对象纳入二级缓存
如果数据对象实现了LifeCycle接口则调用数据对象的onLoad方法
返回数据对象
Hibernate的主键生成机制
) assigned
主键由外部程序负责生成无需Hibernate参与
) hilo
通过hi/lo 算法实现的主键生成机制需要额外的数据库表保存主键生成历史状态
) seqhilo
与hilo 类似通过hi/lo 算法实现的主键生成机制只是主键历史状态保存在Sequence中适用于支持Sequence的数据库如Oracle
) increment
主键按数值顺序递增此方式的实现机制为在当前应用实例中维持一个变量以保存着当前的最大值之后每次需要生成主键的时候将此值加作为主键这种方式可能产生的问题是如果当前有多个实例访问同一个数据库那么由于各个实例各自维护主键状态不同实例可能生成同样的主键从而造成主键重复异常因此如果同一数据库有多个实例访问此方式必须避免使用
) identity
采用数据库提供的主键生成机制如DBSQL ServerMySQL中的主键生成机制
) sequence
采用数据库提供的sequence 机制生成主键如Oralce 中的Sequence
) native
由Hibernate根据底层数据库自行判断采用identityhilosequence其中一种作为主键生成方式
) uuidhex
由Hibernate基于 位唯一值产生算法生成 进制数值(编码后以长度 的字符串表示)作为主键
) uuidstring
与uuidhex 类似只是生成的主键未进行编码(长度)在某些数据库中可能出现问题(如PostgreSQL)
) foreign
使用外部表的字段作为主键一般而言利用uuidhex方式生成主键将提供最好的性能和数据库平台适应性
这中生成OID标识符的方法increment 比较常用把标识符生成的权力交给Hibernate处理但是当同时多个Hibernate应用操作同一个数据库甚至同一张表的时候就推荐使用identity 依赖底层数据库实现但是数据库必须支持自动增长当然针对不同的数据库选择不同的方法如果你不能确定你使用的数据库具体支持什么的情况下可以选择用native 让Hibernate来帮选择identitysequence或hilo
另外由于常用的数据库如OracleDBSQLServerMySql 等都提供了易用的主键生成机制(AutoIncrease 字段或者Sequence)我们可以在数据库提供的主键生成机制上采用generatorclass=native的主键生成方式
不过值得注意的是一些数据库提供的主键生成机制在效率上未必最佳大量并发insert数据时可能会引起表之间的互锁数据库提供的主键生成机制往往是通过在一个内部表中保存当前主键状态(如对于自增型主键而言此内部表中就维护着当前的最大值和递增量)之后每次插入数据会读取这个最大值然后加上递增量作为新记录的主键之后再把这个新的最大值更新回内部表中这样一次Insert操作可能导致数据库内部多次表读写操作同时伴随的还有数据的加锁解锁操作这对性能产生了较大影响因此对于并发Insert要求较高的系统推荐采用uuidhex 作为主键生成机制