Hibernate知识点总结

来源:互联网 发布:mac翻墙回国软件 编辑:程序博客网 时间:2024/05/02 01:11

Hibernate

对象的三种状态

 

Hibernate 中Java对象的状态

1.临时状态 (transient)

特征:

   1】不处于Session缓存中

   2】数据库中没有对象记录

Java如何进入临时状态

   1】通过new语句刚创建一个对象时

   2】当调用Session的delete()方法,从Session 缓存中删除一个对象时。 

 

2.持久化状态(persisted)

特征:

   1】处于Session缓存中

   2持久化对象数据库中设有对象记录

   3】Session在特定时刻会保持二者同步

Java如何进入持久化状态

   1】Session的save()把临时-》持久化状态

   2】Session的load(),get()方法返回的对象

   3】Session的find()返回的list集合中存放的对象

   4】Session的update(),saveOrupdate()使游离-》持久化

3.游离状态(detached)

特征:

   1】不再位于Session缓存中

   2游离对象由持久化状态转变而来,数据库中可能还有对应记录。

Java如何进入持久化状态-》游离状态

   1】Session的close()方法

   2】Session的evict()方法,从缓存中删除一个对象。提高性能。少用。

 

顺序问题

在实际应用中,一般是先建表后用反向工程生成类。

slf(日志)

它是一套规范。其实现有这几种:slf4j-nodep,log4j,jdk logging api,apachecommons-logging

Log4J日志环境搭建

1、         slf4j-api-1.6.1.jar是一个规范,需要加log4j-1.2.15.jar,不可以有slf4j-nop-1.6.1.jar(slf自己的实现)文件,否则会有两个实现,出错!

2、         添加slf4j-1.6.1目录下的slf4j-log4j12-1.6.1.jar(slf接口转换为log4j接口)

3、         从hibernate-distribution-3.3.2.GA-dist\project\etc目录下复制log4j.properties文件到src下。

4、         可以修改log4j.properties文件,按自己要求输出信息。

注解位置

应放在get方法上。放在字段上的话破坏封装。不能放在set方法上面。

hbm2ddl(查文档)

 四中状态:create:每次都将原来的删除,重新建新表

          update:检查是否发生变化,变化就更新

ID生成策略

1、  XML

标签id的子标签:<generator class="native"/>

常用的类型:native、uuid、sequence、identity

2、  Annotation

@GeneratedValue,默认为aoto,也可以这么写:@GeneratedValue(strategy=GenerationType.AUTO)

可指定生成器Generator(在Oracle中自动生成的序列名为hibernate_sequence,指定生成器就可命名序列)。两种生成器:

1)@SequenceGenerator

2)@TableGenerator   (跨平台)

 这两种生成器需写在类上,在主键字段上指定策略为sequence并用generator引用生成器名

联合字段做主键(查文档)不重要

1、Annotation

1、将组件类注解为@Embeddable,并将组件的属性(实体类中而非主键类)注解为@Id

2、将组件的属性注解为@EmbeddedId

3、将类注解为@IdClass,并将该实体中所有属于主键的属性都注解为@Id

2、XML

<composite-id……>

<key-property……/>

<key-property……/>

</composite-id>

openSession()和getCurrentSession()的区别

1、前者需要手动关闭session,后者不需要手动关闭session,在线程消亡后自动关闭。

2、前者永远都打开新的session,后者先从上下文找,如果没有找到则产生新的session,在事务提交之前永远都是同一个session。

3、getCurrentSession()可以用来界定事务边界。

几种类型属性的映射:

@Transient//透明,意思是说不映射到表

1、XML:

       指定其type

2、Annotation:

枚举类型:

        @Enumerated(EnumType.STRING)

日期类型:

        @Temporal(TemporalType.DATE)

映射类型

核心开发接口

1、 Configuration管理配置文件

Config()  buildSessionFactoty()

2、 sessionFactory管理多个连接池,产生session

3、 Session可以理解为一个数据库连接

4、 AnnotationConfiguration  用注解@来映射的时候要newAnnotationConfiguration();

5、 hibernate.cfg.xml文件可以直接放在src下,配置的时候可以直接用config(),不需要参数;也可以放在包下面,这时候就要将包的路径加入,如:com/bjsxt/hibernate/hibernate.cfg.xml。其他的文件类似的效果。

6、 hibernate中的mapping标签,当用xml文件的时候:resource=” com/bjsxt/hibernate/hibernate.cfg.xml”;当用注解@的时候:class=“com.bjsxt.hibernate.Teacher”,要用完整的类名。

CRUD(时刻注意对象的状态)

get和load都是先从缓存找,如果没有,才去数据库中找。

1、get()和load()的区别:

1、            get()是直接从数据库加载,不会延迟,而load()获取到的是代理对象,只有当用到对象中的内容时才会发送sql语句。

2、            get()方法将从数据库加载的数据存放到对象中,事务提交后对象中还可以取到值

3、            如果未能发现符合条件的记录,Hibernate get方法返回null,而load方法会抛出一个ObjectNotFoundException。

1)  在使用getCurrentSession()方法时,load()方法事务提交后就不能获取值,会报LazyInitializationException异常,因为此时线程已经消亡,找不到session,不能初始化代理。因为getCurrentSession会自动close。

2)  在使用openSession()时,在session.close()之前,load()方法获取的代理对象中的内容还可以使用。

3)  总之一句话:不管是openSession()还是getCurrentSession()。在session关闭之后,load()方法获取的代理对象中的内容不可以使用,异常,get()可以。

update():

     注意:session.get()时,对象状态为persistent,在事务提交之前如果更改了对象的属性值(调用set方法),事务提交后会自动发送一条update语句(即使没有session.update(*))。保持缓存和数据库的同步。

 

     如果个别字段不需要更改:

1、 可以注解@Column(updatable = false)或XML中property标签属性update=”false”

2、 XML中指定class标签的属性dynamic-update=”true”

3、 跨session:(上个session1.get()的对象obj)在session2中可以这样调用session2.merge(obj),意思是合并。(了解即可)

2、saveOrUpdate()

3、clear()  清空session缓存

4、flush() 强制让缓存内容和数据库同步,用session.flushMode()方法指定flush时间,性能调优

5、find 过时

SchemaExport

可以在应用程序中创建表。

newSchemaExport(new Configuration().configure()).create(true,true);

关系映射(文档里有很全的例子说明)

一个异常:Exceptionin thread "main" java.lang.NoSuchMethodError:javax.persistence.OneToOne.orphanRemoval()Z

原因hibernate的jar包里面加了那个ejb3的jar包与JPA包冲突 ejb删就OK了。

对象之间的关系:

1、  多对多

2、  多对一

3、  一对一

严格来说只有一个那就是 多对多

多对一是多对多的一种特殊情况

一对一是多对一的一种特殊情况

数据库的表和表之间只有一种关系:外键

1、 一对一

1)     单向外键关联:

Annotation:在持有外键引用的类中:@OneToOne可用 @JoinColumn指定关联字段

XML:<many-to-onename="wife" column="wifeId" unique="true"/>

2)     双向外键关联:

Annotation:在两个实体类中都注解:@OneToOne ,mappedBy 意思是说对方是主导,由对方引用自己。

XML:<many-to-onename="wife" column="wifeId" unique="true"/>

被引用的实体类配置文件:

<one-to-onename="husband" property-ref="wife"></one-to-one>

3) 单向主键关联:

Annotation: @OneToOne@PrimaryKeyJoinColumn

XML:通常使用一个特定的id生成器

3)     联合主键关联

@joinColumns(

        {

@joinColumn(name=”wifeId”,referencedColumnName=”id”),

@joinColumn(name=”wifeName”,referencedColumnName=”name”)

}

)

2、 组件映射(只生成一张表)

1) Annotation:一个实体类持一个组件类的外键引用,在被引用组件对象的get方法上@Embedded,配置文件中只映射持有引用的那个类。

Xml:<componentname="wife">

               <propertyname="wifeId"></property>

               <propertyname="wifeName"></property>

        </component>

3、 多对一

建表时,可以在多的一方持有一的外键,会减少冗余

1)     多对一单向关联:

Annotation:在多的一方@ManyToOne

Xml:<many-to-one name=”person” />

2)     一对多单向关联:

Annotation:在一的一方@OneToMany

@JoinColumn(name="personId"),”personId”是随便写的。如果没有@JoinColumn则会生成一个中间表。

Xml: <setname="dreams">

      <keycolumn="personId"></key>

                     <one-to-manyclass="Dream"/>

              </set>

3) 多对一,一对多双向关联:

Annotation: @ManyToOne

              @JoinColumn(name="personId")

     在一的一方:

                     @OneToMany(mappedBy="person")

Xml:在一的一方:

<set name="dreams">

        <keycolumn="personId"></key>

                            <one-to-many class="Dream"/>

                     </set>

在多的一方:<many-to-onename="person" column="personId" />

4、 多对多

1) 多对多单向关联:

Annotation:  @ManyToMany

       @JoinTable(name="t_s",

                     joinColumns={@JoinColumn(name="studentId")},

                     inverseJoinColumns={@JoinColumn(name="teacherId")}

       )

Xml:<set name="teachers" table="t_s">

                     <keycolumn="studentId"></key>

                     <many-to-manyclass="Teacher" column="teacherId"/>

</set>

2)多对多双向关联:

 

说下Hibernate的缓存机制:

Hibernate缓存的作用:

    Hibernate是一个持久层框架,经常访问物理数据库,为了降低应用程序对物理数据源访问的频次,从而提高应用程序的运行性能。缓存内的数据是对物理数据源中的数据的复制,应用程序在运行时从缓存读写数据,在特定的时刻或事件会同步缓存和物理数据源的数据

Hibernate缓存分类:

  Hibernate缓存包括两大类:Hibernate一级缓存和Hibernate二级缓存

Hibernate一级缓存又称为“Session的缓存”,它是内置的,意思就是说,只要你使用hibernate就必须使用session缓存。由于Session对象的生命周期通常对应一个数据库事务或者一个应用事务,因此它的缓存是事务范围的缓存。在第一级缓存中,持久化类的每个实例都具有唯一的OID。

Hibernate二级缓存又称为“SessionFactory的缓存”,由于SessionFactory对象的生命周期和应用程序的整个过程对应,因此Hibernate二级缓存是进程范围或者集群范围的缓存,有可能出现并发问题,因此需要采用适当的并发访问策略,该策略为被缓存的数据提供了事务隔离级别。第二级缓存是可选的,是一个可配置的插件,在默认情况下,SessionFactory不会启用这个插件。

什么样的数据适合存放到第二级缓存中?   

1 很少被修改的数据   

2 不是很重要的数据,允许出现偶尔并发的数据   

3 不会被并发访问的数据   

4 常量数据   

不适合存放到第二级缓存的数据?   

1经常被修改的数据   

2 .绝对不允许出现并发访问的数据,如财务数据,绝对不允许出现并发   

3 与其他应用共享的数据。

 

如何优化Hibernate?
1.使用双向一对多关联,不使用单向一对多
2.灵活使用单向一对多关联
3.不用一对一,用多对一取代
4.配置对象缓存,不使用集合缓存
5.一对多集合使用Bag,多对多集合使用Set
6. 继承类使用显式多态

7. 表字段要少,表关联不要怕多,有二级缓存撑腰

 

0 0
原创粉丝点击