现在的位置: 首页 > 综合 > 正文

Hibernate相关小知识点

2018年04月07日 ⁄ 综合 ⁄ 共 5450字 ⁄ 字号 评论关闭

Hibernate相关小知识点

1、Hibernate框架主键生成方式

这里需要选择主键生成方式,主要有以下几种:

1)  assigned:通过程序添加。

2)  sequence:通过Oracle的序列生成主键值

3)  native:通过数据库表中自带的关键字生成主键值,例如:MySQL,SQLServer,DB2,HSQL等

4)  increment:自增长,通过程序实现自增长功能。

5)  UUID:生成一个32的位随机值作为主键。

具体如下:

1)assigned:

由应用程序负责生成主键标识符,往往使用在数据库中没有代理主键,使用的主键与业务相关的情况,如:<id name="id" column="id" type=" java.lang.Integer">

    <generator class="assigned"/>

</id>

这种主键的生成方式不建议使用,在数据库表设计时就应该使用代理主键(surrogate key),不应使用自然主键(natural key具有业务含义),在没有指定<generator>标签时,默认就是assigned主键的生成方式,在插入数据的时候主键由用户自己添加,hibernate也不管

2)sequence:

在ORACLE等数据库中使用sequence生成主键。sequence的特点是于数据库的相关性

a)         先在数据库中建立好序列:CREATE SEQUENCE news_seq;

b)        修改配置文件

        <id name="id" type="java.lang.Integer">

              <column name="ID" precision="8" scale="0" />

              <!--

              主键生成方式

            -->

              <generator class="sequence">

                  <param name="sequence">news_seq</param>

              </generator>

         </id>

3 )native:

由hibernate根据不同的数据库方言,自动选择不同的主键生成方式,native的优点是与底层性无关,便于不同数据库之间的移植,由hibernate根据不同数据库选择主键的生成方式

4)increment:

当向数据库中插入新的纪录时,主键会自动增长1。increment主键生成方式的特点是与底层数据库无关性,大部分数据库如 Mysql,MSSQL 和ORACLE等都支持increament生成方式。increment方式的不足之处是只能有一个hibernate进程访问数据库,若是多个线程并发对数据库表进行写操作时,可能出现相同的主键值,发生主键重复的冲突,因此多线程并发操作时,不应该使用此方法

5)uuid.hex:

采用基于128位的算法生成唯一值,并编制成32位长度的唯一字符串作为主键值,uuid.hex的优点是支持大部分数据库,缺点就是要占用较大的存储空间

 

 

2、Hibernate中提供了三种查询方式:

1)  Session的查询:按主键查询查询,方法为get或load

2)  Query的查询:使用HQL语句或SQL语句完成查询

3)  Criteria的查询:通过方法和类中属性的关系,来设置查询条件,完成查询。(不常用)

 

3、Session中get和load方法的区别?

1)  如果没有查询到数据,get会返回null,而load则直接提示错误。

2)  使用load查询时,可能会出现以下错误,因为load方式使用的是懒汉式加载方法。执行load方法时,不立刻查询数据库。当用到查询出的对象的属性时,才加载数据。

使用load时会出现以下这种错误:

org.hibernate.LazyInitializationException: could not initialize proxy - no Session

解决这个异常的方法:

1)  不关连接

2)  不用load,就使用get就可以了。

 

4、Session操作过程中的pojo对象存在三种状态:

1)  瞬时态:该对象在数据库中没有对应的数据

2)  持久态:数据库中存在该对象对应的数据,同时操作该对象的Session也存在。

3)  游离态:数据库中包含该对象对应的数据,但操作此对象的Session已经不存在或被关闭了。

三种状态之间的转换:

瞬时 à 持久:save(),saveOrUpdate()

持久 à 瞬时:delete()

持久 à 游离:close()

游离 à 持久:update(),saveOrUpdate()

针对持久态对象,Hibernate还存在以下两个特点:

1)  持久态对象,在同一Session中只存在同一个。

a)         如果连接不关闭,多次查询同一条数据,只返回同一个对象,也就是只查询一次数据库。

b)        此功能也被称为一级缓存,但实际开发中实用性很低。

2)  修改持久态对象的属性,可以自动同步到数据库对应的数据中。

a)         当修改了一个持久态对象的属性,而且提交了事务,则数据库自动调用更新操作,也一起修改。

b)        当登陆后,要求将当前系统时间,作为最后登陆时间保存到数据库中时,可以使用。

 

5、简单的几个HQL语句

DELETEFROM News AS n WHERE n.id = ?

 UPDATE News AS n SET n.title = ?,n.content= ? WHERE n.id = ?"

SELECT n.id AS id,n.titleAS title FROM News AS n

 FROM Person ad p innerjoin p.myEvent e with p.id=e.id

 

 

 

 

6、hibernate集合映射inverse和cascade

<!--Province中存在一个名称为citiesSet集合-->

        <setname="cities"inverse="true">

        <!--关联外键是PROVINCE_ID-->

            <key>

                <columnname="PROVINCE_ID"precision="8"scale="0"/>

            </key>

            <!--表示当前类(Province)City类存在一对多关系-->

            <one-to-manyclass="org.liky.primary.pojo.City"/>

        </set>

Inverse=true表示:关联关系反转,也就是关联关系由对方进行维护。关联关系在这里指的是外键字段province_id,该字段是city表的,也就是说修改city表,才可以修改这个字段,也就可以说city表维护着关联关系。对于Province来说,对方就是city,也就是说关联关系由对方(city)来维护。

 

cascade指的是Hibernate中配置的级联操作。

<set name="courses"table="USER_COURSE" cascade="all" schema="SUNXUN"> 

配置上这个以后,当用户选择课程时,不光处理中间表,同时对课程也进行一样的操作

 

7、一级缓存和二级缓存

在之前,使用Session的get或load查询同一对象时,存在一级缓存,但由于连接需要关闭,而且需求一般不会有某一个用户反复查询同一数据,因此使用性不强,基本用不到。

而Hibernate还提供了SessionFactory级别的二级缓存,这个缓存默认并没有打开,需要手工通过配置打开,而且默认也只支持按主键查询功能。

为了解决查询多条数据的缓存问题,Hibernate还提供了Query查询缓存。

 

二级缓存功能的实现并不是由Hibernate自己独立完成的,需要依赖于一些第三方数据插件来完成,结合的最好的插件是ehcache,除了这个缓存插件还支持oscache

使用缓存的步骤:

1)在hibernate.cfg.xml中加入以下属性配置

a)      设置缓存支持类:      property 文本框中写cache.provider_class

                                    value 文本框中写org.hibernate.cache.EhCacheProvider     

b)       打开二级缓存功能: property 文本框中写cache.use_second_level_cache

                                    value 文本框中写true 

c)       使用Query查询缓存:property 文本框中写cache.use_query_cache

                                    value 文本框中写true 

2)在需要进行缓存的pojo的映射文件中加入以下配置

<class name="org.liky.pojo.News" table="NEWS" schema="PP">

    <cache usage="read-only"/>

a)         这里的read-only表示缓存的类型,分为以下四种:

                        i.             Read-only:只读缓存,数据不允许进行修改操作,如果修改,则直接报错

                       ii.             Read-write:可读写缓存,数据允许修改,当数据库数据修改时,缓存立刻重新生成。

                     iii.             Nonstrict-read-write:不严格的可读写缓存,数据允许修改,但数据库改变后,缓存不变,而是在一定时间后再与数据库同步。

                     iv.             Transactional:支持事务的缓存,但现在不用了,合并到read-write中了。

3)需要将缓存核心配置文件加入到项目的src目录下。

<ehcache>

 

    <!--

    硬盘保存缓存数据的临时目录.

    -->

    <diskStore path="java.io.tmpdir"/>

 

 

    <!--

 

        maxInMemory       - 限制内存中允许保存的对象最大数量.

        eternal           - 缓存数据是否永久保存,一直不销毁,建议false

        timeToIdleSeconds - 空闲释放时间.

        timeToLiveSeconds - 缓存的生命时间,配合不严格可读写使用的.

        overflowToDisk    - 如果数据量过大,是否将溢出数据保存到硬盘上.

 

        -->

    <defaultCache

       maxElementsInMemory="10000"

       eternal="false"

       timeToIdleSeconds="120"

       timeToLiveSeconds="300"

       overflowToDisk="true"

       />

 

</ehcache>

 

现在已经完成了二级缓存的配置,支持按主键查询的缓存功能。

 

测试时,会提示错误,缺少支持jar包,这里需要找到一个commons-logging.jar支持包。

这种缺少包的错误,可以根据缺少的类明,在
http://www.findjar.com
中查找对应的支持包,并下载。

如果想使用Query查询缓存,还需要在编写DAO时,设置Query对象的属性,允许使用该功能。

public List<News> findAll(int pageNo,int pageSize, String keyword,

           String column) throws Exception {

       String hql = "FROM NewsAS n WHERE n." + column +" LIKE ?";

       Query query = HibernateSessionFactory.getSession().createQuery(hql); 

        query.setCacheable(true);      

       query.setString(0, "%" + keyword +"%");

       query.setFirstResult((pageNo - 1) * pageSize);

       query.setMaxResults(pageSize);

       return query.list();

    }

 

8、Hibernate提高性能的方法有哪些?

1)使用缓存

2)使用懒汉式

3)SQL语句

4)Fetch=”select”

 

Oracle数据库提高性能的方法有哪些?

1)创建Index索引

2)创建View视图

3)SQL语句内大写

4)比较时尽量使用>=和<=,而不是>和<

5)日期类型不要直接比较,可以转换成long类型进行比较。

 

【上篇】
【下篇】

抱歉!评论已关闭.