hibernate 一级缓存:(缓存的是实体对象)

一级缓存很短和session的生命周期一致,一级缓存也叫session级的缓存或事务缓存

 

哪些方法支持一级缓存:

*get()

*load()

*iterate()  (查询实体对象)

 

如何管理一级缓存:

* session.clear() session.evict()

 

如何避免一次性大量的实体数据入库导致内存溢出

*先flush,再clear

 

如果数据量特别大,考虑采用jdbc实现,如果jdbc也不能满足要求,可以考虑采用数据库本身的特定导入工具

 

一.Load测试: 在同一个session中发出两次load查询

       Student sutdent = (Student)session.load(Student.class,1);

       System.out.println(student.getName());

 

       sutdent = (Student)session.load(Student.class,1);

       System.out.println(student.getName());

       在同一个session中发出两次load查询,第一次load的时候不会去查询数据库,因为他是LAZY的,当使用的时候才去查询数据库,  第二次load的时候也不会,当使用的时候也不会查询数据库,因为他在缓存里找到,不会发出sql

 

 

Load测试: 开启两个session中发出两次load查询

Student sutdent = (Student)session.load(Student.class,1);

       System.out.println(student.getName());

sessioin.close();

………..

       sutdent = (Student)session.load(Student.class,1);

       System.out.println(student.getName());

       开启两个session中发出两次load查询,第一次load的时候不会去查询数据库,因为他是LAZY的,当使用的时候才去查询数据库,  第二次load的时候也不会,当使用的时候查询数据库,因为session间不能共享一级缓存的数据,因为他会随session的生命周期存在和消亡

 

 

二.Get测试: 在同一个session中发出两次get查询

    Student sutdent = (Student)session.get(Student.class,1);

       System.out.println(student.getName());

 

       sutdent = (Student)session.get(Student.class,1);

       System.out.println(student.getName());

       在同一个session中发出两次get查询, 第一次get的时候去查询数据库,第二次get的时候不会查询数据库,因为他在缓存里找到,不会发出sql

 

 

三.iterate测试: 在同一个session中发出两次iterator查询

Student student = (Student)session.createQuery(“from Student s where s.id=1”).iterate().next();

System.out.println(student.getName());

 

student = (Student)session.createQuery(“from Student s where s.id=1”).iterate().next();

System.out.println(student.getName());

       在同一个session中发出两次iterator查询,第一次iterate().next()的时候会发出查询id的sql,使用的时候会发出相应的查询实体对象,第二次iterate().next()的时候会发出查询id的sql,不会发出查询实体对象的sql,因为iterate使用缓存,不会发出sql

 

 

四.Iterate查询属性测试: 同一个session中发出两次查询属性

String name = (String)session.createQuery(“select s.name from Student s where s.id=1”).iterate().next();

System.out.println(name);

 

String name = (String)session.createQuery(“select s.name from Student s where s.id=1”).iterate().next();

System.out.println(name);

       在同一个session中发出两次查询属性, 第一次iterate().next()的时候会发出查询属性的sql,第二次iterate().next()的时候会发出查询属性的sql,iterate查询普通属性,一级缓存不会缓存,所以会发出sql

 

 

五.同一个session中先save,再发出load查询save过的数据

 

       Student stu = new Student();

       stu.setName(“王五”);

 

   Serializable id = session.save(stu);

 

Student sutdent = (Student)session.load(Student.class,id);

       System.out.println(student.getName());

 

      

save的时候,他会在缓存里放一份,不会发出sql,因为save是使用缓存的

六.同一个session中先调用load查询,然后执行sessio.clear()session.evict(),再调用load查询

 

Student sutdent = (Student)session.load(Student.class,1);

       System.out.println(student.getName());

       session.clear();

 

Student sutdent = (Student)session.load(Student.class,1);

       System.out.println(student.getName());

 

 

       sessio.clear()或session.evict()可以管理一级缓存,一级缓存无法取消,但可以管理.

上面的语句都会发出sql 因为一级缓存中的实体被清除了

 

七.向数据库中批量加入1000条数据

 

for(int i=0;i<1000;i++){

       Student student = new Student();

       student.setName(“s” + i);

       session.save(student);

//每20条数据就强制session将数据持久化,同时清除缓存,避免大量数据造成内存溢出

       if( i %20 == 0 ){

              session.flush();

              session.clear();

}

}

 

posted @ 2009-04-06 11:59 胡鹏 阅读(403) | 评论 (0)编辑 收藏

 

hibernate查询缓存(hibernate默认是关闭的)

 

查询缓存是针对普通属性结果集的缓存

对实体对象的结果集只缓存id

 

查询缓存的生命周期,当前关联的表发生修改,那么查询缓存生命周期结束

 

查询缓存的配置和使用:

1. 启用查询缓存:在hibernate.cfg.xml中加入:

<property name=”hibernate.cache.use_query_cache”>true</property>

  2. 在程序中必须手动启用查询缓存,如:query.setCacheable(true);

 

 

测试查询缓存:

一.  开启查询缓存,关闭二级缓存,开启一个session,分别调用query.list  (查询属性)

 

Query query = session.createQuery(“select s.name from Student s”);

//启用查询缓存

query.setCacheable(true);

 

List names = query.list();

for(Iterator iter = names.terator();iter.hasNext();){

       String name = (String)iter.next();

       System.out.println(name);

}

 

System.out.println(“------------------------------------------”);

 

query = session.createQuery(“select s.name from Student s”);

//启用查询缓存

query.setCacheable(true);

 

names = query.list();

for(Iterator iter = names.terator();iter.hasNext();){

       String name = (String)iter.next();

       System.out.println(name);

}

第二次没有去查询数据库,因为启用了查询缓存

 

二.  开启查询缓存,关闭二级缓存,开启两个session,分别调用query.list  (查询属性)

 

Query query = session.createQuery(“select s.name from Student s”);

//启用查询缓存

query.setCacheable(true);

 

List names = query.list();

for(Iterator iter = names.terator();iter.hasNext();){

       String name = (String)iter.next();

       System.out.println(name);

}

 

session.close();

 

System.out.println(“------------------------------------------”);

………

Query query = session.createQuery(“select s.name from Student s”);

//启用查询缓存

query.setCacheable(true);

 

List names = query.list();

for(Iterator iter = names.terator();iter.hasNext();){

       String name = (String)iter.next();

       System.out.println(name);

}

第二次没有去查询数据库,因为查询缓存生命周期与session生命周期无关

 

三.  开启查询缓存,关闭二级缓存,开启两个session,分别调用query.iterate (查询属性)

 

Query query = session.createQuery(“select s.name from Student s”);

//启用查询缓存

query.setCacheable(true);

 

for(Iterator iter =query.iterate();iter.hasNext();){

       String name = (String)iter.next();

       System.out.println(name);

}

 

session.close();

 

System.out.println(“------------------------------------------”);

………

Query query = session.createQuery(“select s.name from Student s”);

//启用查询缓存

query.setCacheable(true);

 

for(Iterator iter = query.iterate();iter.hasNext();){

       String name = (String)iter.next();

       System.out.println(name);

}

第二去查询数据库,因为查询缓存只对query.list()起作用,对query.iterate()不起作用,也就是说query.iterate()不使用查询缓存

 

四.  关闭查询缓存,关闭二级缓存,开启两个session,分别调用query.list (查询实体对象)

 

Query query = session.createQuery(“ from Student s”);

//query.setCacheable(true);

List students = query.list();

for(Iterator iter = students.iterate();iter.hasNext();){

       Student stu = (Student)iter.next();

       System.out.println(stu.getName());

}

 

session.close();

 

System.out.println(“------------------------------------------”);

………

Query query = session.createQuery(“ from Student s”);

//query.setCacheable(true);

List students = query.list();

for(Iterator iter = students.iterate();iter.hasNext();){

       Student stu = (Student)iter.next();

       System.out.println(stu.getName());

}

第二去查询数据库,因为list默认每次都会发出查询sql

 

五.  开启查询缓存,关闭二级缓存,开启两个session,分别调用query.list (查询实体对象)

 

Query query = session.createQuery(“ from Student s”);

query.setCacheable(true);

List students = query.list();

for(Iterator iter = students.iterate();iter.hasNext();){

       Student stu = (Student)iter.next();

       System.out.println(stu.getName());

}

 

session.close();

 

System.out.println(“------------------------------------------”);

………

Query query = session.createQuery(“ from Student s”);

query.setCacheable(true);

List students = query.list();

for(Iterator iter = students.iterate();iter.hasNext();){

       Student stu = (Student)iter.next();

       System.out.println(stu.getName());

第二去查询数据库时,会发出N条sql语句,因为开启了查询缓存,关闭了二级缓存,那么查询缓存会缓存实体对象的id,所以hibernate会根据实体对象的id去查询相应的实体,如果缓存中不存在相应的实体,那么将发出根据实体id查询的sql语句,否则不会发出sql,使用缓存中的数据

 

六.  开启查询缓存,开启二级缓存,开启两个session,分别调用query.list (查询实体对象)

 

Query query = session.createQuery(“ from Student s”);

query.setCacheable(true);

List students = query.list();

for(Iterator iter = students.iterate();iter.hasNext();){

       Student stu = (Student)iter.next();

       System.out.println(stu.getName());

}

 

session.close();

 

System.out.println(“------------------------------------------”);

………

Query query = session.createQuery(“ from Student s”);

query.setCacheable(true);

List students = query.list();

for(Iterator iter = students.iterate();iter.hasNext();){

       Student stu = (Student)iter.next();

       System.out.println(stu.getName());

}

 

第二不会发出sql,因为开启了二级缓存和查询缓存,查询缓存缓存了实体对象的id列表,hibernate会根据实体对象的id列表到二级缓存中取得相应的数据

posted @ 2009-04-06 11:58 胡鹏 阅读(4876) | 评论 (0)编辑 收藏

悲观锁

      

       悲观锁的实现,通常依赖于数据库机制,在整个过程中将数据锁定,其它任何用户都不能读取或修改。

 

举个例子:

//查询id=1的那条记录,使用悲观锁

User user = (User)session.load(User.class, 1 ,  LockMode.UPGRADE);

使用了数据库中的 for update  锁定

 

乐观锁

大多数基于数据版本记录机制(version)实现,一半是在数据库表加入一个version字段,读取数据时将版本号一同读出,之后更新数据时版本号加一,如果提交数据时版本号小于或等于数据库表中的版本号,则认为数据是过期的,否则给予更新。

 

其实并非是锁,是一种冲突检测  (没有hibernate也可以使用的,自己要在数据库中建字段来控制,使用hibernate方便些,封装好了)

 

在*.hm.xml中 添加红色部分:

                                            

<class

name="com.tao3c.orm.TbBusinessInfo"  table="tb_business_info"  optimistic-lock=”version”>

 

其中version是com.tao3c.orm.TbBusinessInfo类的属性,hiernbate会去维护的,不用自己去该

 

 

posted @ 2009-04-06 11:57 胡鹏 阅读(218) | 评论 (0)编辑 收藏

悲观锁

      

       悲观锁的实现,通常依赖于数据库机制,在整个过程中将数据锁定,其它任何用户都不能读取或修改。

 

举个例子:

//查询id=1的那条记录,使用悲观锁

User user = (User)session.load(User.class, 1 ,  LockMode.UPGRADE);

使用了数据库中的 for update  锁定

 

乐观锁

大多数基于数据版本记录机制(version)实现,一半是在数据库表加入一个version字段,读取数据时将版本号一同读出,之后更新数据时版本号加一,如果提交数据时版本号小于或等于数据库表中的版本号,则认为数据是过期的,否则给予更新。

 

其实并非是锁,是一种冲突检测  (没有hibernate也可以使用的,自己要在数据库中建字段来控制,使用hibernate方便些,封装好了)

 

在*.hm.xml中 添加红色部分:

                                            

<class

name="com.tao3c.orm.TbBusinessInfo"  table="tb_business_info"  optimistic-lock=”version”>

 

其中version是com.tao3c.orm.TbBusinessInfo类的属性,hiernbate会去维护的,不用自己去该

 

 

posted @ 2009-04-06 11:57 胡鹏 阅读(174) | 评论 (0)编辑 收藏

hibernate中设置:

查询数据库每次最多返回50条结果:

<property name=”hibernate.jdbc.fetch_size”>50</property>

30条更新数据库一次:

<property name= ”hibernatejdbc.batch_size”>30</property>

 但不是所有的数据库都支持的,sqlServer orcale 都支持的。

 

一.hibernate 抓取策略(Fetch) 单端代理批量抓取

 

1.fetch=”select” 关联实体

//fetch 默认是select

<many-to-one name="businessId" column="business_id" insert="true" update="true" fetch="select">

 

Student student = (Student)session.load(Student.class,1);

System.out.println(student.getName());

System.out.println(student.getClasses().getName()); //多对一中的属性班级,获取班级名称

 

Fetch=”select” ,上面程序会发2条sql语句,第二条发送一条select语句抓取当前对象关联实体或集合 (这里指是班级名称)

 

2.fetch=” join” 关联实体

//fetch 设置成 join

<many-to-one name="businessId" column="business_id" insert="true" update="true"

fetch=" join ">

 

Student student = (Student)session.load(Student.class,1);

System.out.println(student.getName());

System.out.println(student.getClasses().getName()); //多对一中的属性班级,获取班级名称

 

fetch=” join” , 上面程序会发1条sql语句, hibernate会通过select使用外链接来加载其关联实体或集合,此时lazy会失效 

 

二.hibernate 抓取策略(Fetch) 集合代理批量抓取

 

1.     fetch=”select”

//fetch 默认是select

<set name="students" inverse="true" cascade="all" fetch="select">

            <key column="classid" />

            <one-to-many class="com.Student" />

</set>

 

Classes cla = (Classes)session.load(Classes.class,1);

System.out.println(cla.getName());

for(Iterator iter = cla.getStudents().iterator();iter.hasNext();){

       Student student = (Student)iter.next();

       System.out.println(student.getName());

}

 

fetch=”select” ,上面程序用到了就发sql语句,第二从循环中发了N条,如果:fetch=”subselect”,则只是发送一条语句,见下面

 

2 fetch=”join”

//fetch 设置成join

<set name="students" inverse="true" cascade="all" fetch="join">

            <key column="classid" />

            <one-to-many class="com.Student" />

</set>

 

Classes cla = (Classes)session.load(Classes.class,1);

System.out.println(cla.getName());

for(Iterator iter = cla.getStudents().iterator();iter.hasNext();){

       Student student = (Student)iter.next();

       System.out.println(student.getName());

}

 

Fetch=”select” ,上面程序只发了一条sql语句

 

 

三.hibernate 抓取策略(Fetch) 集合代理批量抓取

 

2.     fetch=”subselect”

//fetch设置成subselect

<set name="students" inverse="true" cascade="all" fetch="subselect">

            <key column="classid" />

            <one-to-many class="com.Student" />

</set>

 

List classesList = session.createQuery(“select c from Classes c where c.id in(1,2,3)”);

for(Iterator iter=classesList.iterator();iter.hasNext();){

       Classess classess = (Classess)iter.next();

       System.out.println(“classes.name=”+ classes.getName());

       for(Iterator iter1 = classess.getStudents().iterator();iter1.hasNext();){

              Student student = (Student)iter1.next();

              System.out.println(student.getName());

}

}

 

Fetch=”subselct” ,另外发送一条select语句抓取在前面查询到的所有实体对象的关联集合

 

 

四.hibernate 批量策略batch-size属性,可以批量加载实体类,

参见Classes.hbm.xml,同时集合也可以是使用,如:

 <set name="students" inverse="true" cascade="save-update" batch-size=”5”>

 

在配置文件hbm.xml 设置中:

<class name="com.Classes " table="tb_classes" batch-size=”3”>

 

List students = session.createQuery(“select s from Student s where s.id in(:ids)”).setParameterList(“:ids”,new Object[]{1,11,21,31,41,51,61,71,81,91}).list();

 

for(Iterator iter=students.iterator();iter.hasNext();){

       Student student = (Sutdent)iter.next();

       System.out.println(student.getName());

       System.out.println(student.getClassess().getName());

 

}

 

当第二个for循环时,每次加载 之前设置的 数量 实体对象,  如:现在设置3,那么当Iterator iter=students.iterator();iter.hasNext();时候,他会查询出3个student对象

posted @ 2009-04-06 11:57 胡鹏 阅读(415) | 评论 (0)编辑 收藏

一.hibernate多对多映射(单项),自动产生第三张表

User--à Role

user(id,name)    role(id,name)

User类:

private int  id;   private String name;  private  Set roles;

 

Role类:

private int id;    private String name;

 

User.hbm.xml中:

<set name=”roles” table=”t_user_role”>

       <key column=”userid” />

       <many-to-many class=”com.Role” column=”roleid” />

</set>

 

这样,hibernate会自动产生中间表t_user_role(userid,roleid) 并且是复合主键,userid为t_user的外键,roleid为t_role的外键

 

 

二.hibernate多对多的存储

 

Role r1 = new Role();

r1.setName(“数据录入人员”);

 

Role r2 = new Role();

r2.setName(“商务主管”);

 

Role r3 = new Role();

r3.setName(“大区经理”);

 

 

User u1 = new User();

u1.setName(“10”);

Set u1Roles = new HashSet();

u1Roles.add(r1);

u1Roles.add(r2);

u1.setRoles(u1Roles);

 

User u2 = new User();

u1.setName(“祖儿”);

Set u2Roles = new HashSet();

u2Roles.add(r2);

u2Roles.add(r3);

u2.setRoles(u2Roles);

User u3 = new User();

u3.setName(“杰伦”);

Set u3Roles = new HashSet();

u3Roles.add(r1);

u3Roles.add(r2);

u3Roles.add(r3);

u3.setRoles(u3Roles);

 

 

session.save(r1);

session.save(r2);

session.save(r3);

 

session.save(u1);

session.save(u2);

session.save(u3);

 

结束之后,在第三张表中也有数据

 

 

 

三.hibernate多对多的加载

 

User user = (User)session.load(User.class,1);

System.out.println(user.getName());

for(Iterator iter = user.getRoles().iterator();iter.hasNext();){

       Role role = (Role)iter.next();

       System.out.println(role.getName());

 

}

 每次加载都会发出sql语句

 

三.hibernate多对多的 双向映射

 

User ß--.-àRole

user(id,name)    role(id,name)

User类:

private int  id;   private String name;  private Set roles;

 

Role类:

private int id;    private String name; private Set users;

 

User.hbm.xml中:

<set name=”roles” table=”t_user_role”>

       <key column=”userid” />

       <many-to-many class=”com.Role” column=”roleid” />

</set>

 

Role.hbm.xml中:

<set name=”roles” table=”t_user_role”>   //这里可以设置order-by=”userid”,根据userid排序

       <key column=”roleid” />

       <many-to-many class=”com.User” column=”userid” />

</set>

 

注意,上面中间表名字是一样的

这样,hibernate也会自动产生中间表t_user_role(userid,roleid) 并且是复合主键,userid为t_user的外键,roleid为t_role的外键

 

posted @ 2009-04-06 11:56 胡鹏 阅读(1146) | 评论 (0)编辑 收藏

一.hibernate多对多映射(单项),自动产生第三张表

User--à Role

user(id,name)    role(id,name)

User类:

private int  id;   private String name;  private  Set roles;

 

Role类:

private int id;    private String name;

 

User.hbm.xml中:

<set name=”roles” table=”t_user_role”>

       <key column=”userid” />

       <many-to-many class=”com.Role” column=”roleid” />

</set>

 

这样,hibernate会自动产生中间表t_user_role(userid,roleid) 并且是复合主键,userid为t_user的外键,roleid为t_role的外键

 

 

二.hibernate多对多的存储

 

Role r1 = new Role();

r1.setName(“数据录入人员”);

 

Role r2 = new Role();

r2.setName(“商务主管”);

 

Role r3 = new Role();

r3.setName(“大区经理”);

 

 

User u1 = new User();

u1.setName(“10”);

Set u1Roles = new HashSet();

u1Roles.add(r1);

u1Roles.add(r2);

u1.setRoles(u1Roles);

 

User u2 = new User();

u1.setName(“祖儿”);

Set u2Roles = new HashSet();

u2Roles.add(r2);

u2Roles.add(r3);

u2.setRoles(u2Roles);

User u3 = new User();

u3.setName(“杰伦”);

Set u3Roles = new HashSet();

u3Roles.add(r1);

u3Roles.add(r2);

u3Roles.add(r3);

u3.setRoles(u3Roles);

 

 

session.save(r1);

session.save(r2);

session.save(r3);

 

session.save(u1);

session.save(u2);

session.save(u3);

 

结束之后,在第三张表中也有数据

 

 

 

三.hibernate多对多的加载

 

User user = (User)session.load(User.class,1);

System.out.println(user.getName());

for(Iterator iter = user.getRoles().iterator();iter.hasNext();){

       Role role = (Role)iter.next();

       System.out.println(role.getName());

 

}

 每次加载都会发出sql语句

 

三.hibernate多对多的 双向映射

 

User ß--.-àRole

user(id,name)    role(id,name)

User类:

private int  id;   private String name;  private Set roles;

 

Role类:

private int id;    private String name; private Set users;

 

User.hbm.xml中:

<set name=”roles” table=”t_user_role”>

       <key column=”userid” />

       <many-to-many class=”com.Role” column=”roleid” />

</set>

 

Role.hbm.xml中:

<set name=”roles” table=”t_user_role”>   //这里可以设置order-by=”userid”,根据userid排序

       <key column=”roleid” />

       <many-to-many class=”com.User” column=”userid” />

</set>

 

注意,上面中间表名字是一样的

这样,hibernate也会自动产生中间表t_user_role(userid,roleid) 并且是复合主键,userid为t_user的外键,roleid为t_role的外键

 

posted @ 2009-04-06 11:56 胡鹏 阅读(171) | 评论 (0)编辑 收藏

   

单态定义:

Singleton模式主要作用是保证在Java应用程序中,一个类Class只有一个实例存在。

在很多操作中,比如建立目录 数据库连接都需要这样的单线程操作。

还有, singleton能够被状态化; 这样,多个单态类在一起就可以作为一个状态仓库一样向外提供服务,比如,你要论坛中的帖子计数器,每次浏览一次需要计数,单态类能否保持住这个计数,并且能synchronize的安全自动加1,如果你要把这个数字永久保存到数据库,你可以在不修改单态接口的情况下方便的做到。

另外方面,Singleton也能够被无状态化。提供工具性质的功能,

Singleton模式就为我们提供了这样实现的可能。使用Singleton的好处还在于可以节省内存,因为它限制了实例的个数,有利于Java垃圾回收(garbage collection)。

我们常常看到工厂模式中类装入器(class loader)中也用Singleton模式实现的,因为被装入的类实际也属于资源。

如何使用?

一般Singleton模式通常有几种形式:

public class Singleton {

  private Singleton(){}

  //在自己内部定义自己一个实例,是不是很奇怪?

  //注意这是private 只供内部调用

  private static Singleton instance = new Singleton();

  //这里提供了一个供外部访问本class的静态方法,可以直接访问  

  public static Singleton getInstance() {

    return instance;   

   }

}

第二种形式:

public class Singleton {

  private static Singleton instance = null;

  public static synchronized Singleton getInstance() {

  //这个方法比上面有所改进,不用每次都进行生成对象,只是第一次     

  //使用时生成实例,提高了效率!

  if (instance==null)

    instance=new Singleton();

  return instance;   }

}

使用Singleton.getInstance()可以访问单态类。

上面第二中形式是lazy initialization,也就是说第一次调用时初始Singleton,以后就不用再生成了。

注意到lazy initialization形式中的synchronized,这个synchronized很重要,如果没有synchronized,那么使用getInstance()是有可能得到多个Singleton实例。关于lazy initialization的Singleton有很多涉及double-checked locking (DCL)的讨论,有兴趣者进一步研究。

一般认为第一种形式要更加安全些。

使用Singleton注意事项:

有时在某些情况下,使用Singleton并不能达到Singleton的目的,如有多个Singleton对象同时被不同的类装入器装载;在EJB这样的分布式系统中使用也要注意这种情况,因为EJB是跨服务器,跨JVM的。

我们以SUN公司的宠物店源码(Pet Store 1.3.1)的ServiceLocator为例稍微分析一下:

在Pet Store中ServiceLocator有两种,一个是EJB目录下;一个是WEB目录下,我们检查这两个ServiceLocator会发现内容差不多,都是提供EJB的查询定位服务,可是为什么要分开呢?仔细研究对这两种ServiceLocator才发现区别:在WEB中的ServiceLocator的采取Singleton模式,ServiceLocator属于资源定位,理所当然应该使用Singleton模式。但是在EJB中,Singleton模式已经失去作用,所以ServiceLocator才分成两种,一种面向WEB服务的,一种是面向EJB服务的。

Singleton模式看起来简单,使用方法也很方便,但是真正用好,是非常不容易,需要对Java的类 线程内存等概念有相当的了解。

总之:如果你的应用基于容器,那么Singleton模式少用或者不用,可以使用相关替代技术。

posted @ 2009-04-06 11:55 胡鹏 阅读(314) | 评论 (0)编辑 收藏
  
   

1.两种配置文件:

A.hibernate.cfg.xml和B.hibernate.properties

 

A中可含映射文件的配置,而B中hard codes加映射文件。

 

A.Configuration config=new Configuration().config();

B. Configuration config=new Configuration();

config.addClass(TUser.class);

 

2.你不必一定用hibernate.cfg.xml或hibernate.properties这两文件名,你也不一定非得把配置文件放在Classes下, File file=new File("c:\\sample\\myhibernate.xml"); Configuration config=new Configuration().config(file);

 

3. session.Flush() 强制数据库立即同步,当用事务时,不必用flush,事务提交自动调用flush在session关闭时也会调用flush

 

4. Hibernate总是使用对象类型作为字段类型

 

5. XDoclet专门建立了hibernate doclet,就是在java代码上加上一些java docTag,后来再让XDoclet分析该java代码,生成映射文件;

 

6.HQL子句本身大小写无关,但是其中出现的类名和属性名必须注意大小写区分。

 

7.关系: Constrained : 约束,表明主控表的主键上是否存在一个外键(foreigh key)对其进行约束。

 

property-ref:关联类中用于与主控类相关联的属性名,默认为关联类的主键属性名

 

单向一对多需在一方配置,双向一对多需在双方进行配置

 

8.lazy=false:被动方的记录由hibernate负责记取,之后存放在主控方指定的Collection类型属性中

 

9. java.util.Set或net.sof.hibernate.collecton.Bag类型的Collection

 

10.重要:inverse:用于标识双向关联中的被动方一端。

 

inverse=false的一方(主控方)负责维护关联关系.默认值:false

 

11.batch-size:采用延迟加载特征时,一次读入的数据数昨。

 

12.一对多通过主控方更新(主控方为一方时)

 

user.getAddresses().add(addr);

 

session.save(user);//通过主控对象级联更新

 

13.在one-to-many 关系中,将many 一方设为主动方(inverse=false)将有助性能的改善。在一方设置关系时,inverse=true,即将主控权交给多方, 这样多方可主动从一方获得foreign key,然后一次insert即可完工。

 

addr.setUser(user);//设置关联的TUser对象

 

user.getAddresses().add(addr);

 

session.save(user);//级联更新

 

14.只有设为主控方的一方才关心(访问)对方的属性,被动方是不关心对方的属性的。

 

15.one-to-many与many-to-one节点的配置属性不同:

 

一对多关系多了lazy和inverse两个属性多对多节点属性:

 

column:中间映射表中,关联目标表的关联字段

 

class:类名,关联目标类

 

outer-join:是否使用外联接

 

注意:access是设置属性值的读取方式。

 

column是设置关联字段。

 

16.多对多,注意两方都要设置inverse和lazy,cascade只能设为insert-update

 

多对多关系中,由于关联关系是两张表相互引用,因此在保存关系状态时必须对双方同时保存。

 

group1.getRoles().add(role1); role1.getGroups().add(group1);

 

session.save(role1); session.save(group1);

 

17.关于vo和po vo经过hibernate容量处理,就变成了po(该vo的引用将被容器保存,并且在session关闭时flush,因此po如果再传到其它地方改变了,就危险了) vo和po相互转换:BeanUtils.copyProperties(anotherUser,user);

 

18.对于save操作而言,如果对象已经与Session相关联(即已经被加入Session的实体容器中),则无需进行具体的操作。因为之后的Session.flush过程中,Hibernate 会对此实体容器中的对象进行遍历,查找出发生变化的实体,生成并执行相应的update 语句。

 

19.如果我们采用了延迟加载机制,但希望在一些情况下,实现非延迟加载时的功能,也就是说,我们希望在Session关闭后,依然允许操作user的addresses 属性 Hibernate.initialize方法可以通过强制加载关联对象实现这一功能: 这也正是我们为什么在编写POJO时,必须用JDK Collection接口(如Set,Map), 而非特定的JDK Collection实现类(如HashSet、HashMap)申明Collection属性的 原因。

 

20.事务:从sessionFactory获得session,其自动提交属性就已经关闭(AutoCommit=false),此时若执行了jdbc操作,如果不显式调用session.BeginTransaction(),是不会执行事务操作的。

 

jdbc transaction:基于同一个session(就是同一个connection)的事务;

 

jta transaction:跨session(跨connection)事务.

 

对于jta事务,有三种实现方法:

 

A。UserTransaction tx=new InitialContext().lookup("...");

tx.commit();

 

B. 使用hibernate封装的方法:(不推荐)

 

Transaction tx=session.beginTransaction();

tx.commit();

C. 使用ejb之sessionBean的事务技持方法,你只要在把需要在发布描述符中,把需要jta事务的方法声明为require即可

 

21.悲观锁,乐观锁: 乐观锁一般通过version来实现,注意version节点必须出现在id后。

 

22.Hibernate中,可以通过Criteria.setFirstResult和Criteria.setFetchSize方法设定分页范围。

 

Query接口中也提供了与其一致的方法,hibernate主要在dialect类中实现在这个功能。

 

23.cache

 

……

 

net.sf.ehcache.hibernate.Provider 

 

还需对ecache本身进配置

 

 

 

之后在映射文件中指定各个映射实体的cache策略

 

 

....

 

 

....

 

 

***************************************************** Query.list()跟Query.iterate()的不同:对于query.list()总是通过一条sql语句获取所有记录,然后将其读出,填入pojo返回; 但是query.iterate(),则是首先通过一条Select SQL 获取所有符合查询条件的记录的 id,再对这个id 集合进行循环操作,通过单独的Select SQL 取出每个id 所对应的记 录,之后填入POJO中返回。

 

也就是说,对于list 操作,需要一条SQL 完成。而对于iterate 操作,需要n+1 条SQL。,list方法将不会从Cache中读取数据。iterator却会。

 

24.ThreadLocal:它会为每个线程维护一个私有的变量空间。实际上, 其实现原理是在JVM 中维护一个Map,这个Map的key 就是当前的线程对象,而value则是线程通过ThreadLocal.set方法保存的对象实例。当线程调用ThreadLocal.get方法时, ThreadLocal会根据当前线程对象的引用,取出Map中对应的对象返回。

 

这样,ThreadLocal通过以各个线程对象的引用作为区分,从而将不同线程的变量隔离开来。

 

25.Hibernate官方开发手册标准示例:

 

public class HibernateUtil { private static SessionFactory sessionFactory;

static { try { // Create the SessionFactory sessionFactory = new Configuration().configure().buildSessionFactory();

} catch (HibernateException ex) { throw new RuntimeException( "Configuration problem: " + ex.getMessage(), ex );

} } public static final ThreadLocal session = new ThreadLocal();

public static Session currentSession() throws HibernateException { Session s = (Session) session.get();

// Open a new Session, if this Thread has none yet if (s == null) { s = sessionFactory.openSession();

session.set(s);

} return s;

} public static void closeSession() throws HibernateException { Session s = (Session) session.get();

session.set(null);

if (s != null) s.close();

} }

 

26.通过filter实现session的重用:

 

public class PersistenceFilter implements Filter { protected static ThreadLocal hibernateHolder = new ThreadLocal();

public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { hibernateHolder.set(getSession());

try { …… chain.doFilter(request, response);

…… } finally { Session sess = (Session)hibernateHolder.get();

if (sess != null) { hibernateHolder.set(null);

try { sess.close(); } catch (HibernateException ex) { throw new ServletException(ex);

} } } } ……}

posted @ 2009-04-06 11:53 胡鹏 阅读(203) | 评论 (0)编辑 收藏
Eclipse快捷键指南   

有些还是比叫有用的,不过不是很全


编辑
作用域 功能 快捷键
全局 查找并替换 Ctrl+F
文本编辑器 查找上一个 Ctrl+Shift+K
文本编辑器 查找下一个 Ctrl+K
全局 撤销 Ctrl+Z
全局 复制 Ctrl+C
全局 恢复上一个选择 Alt+Shift+↓
全局 剪切 Ctrl+X
全局 快速修正 Ctrl1+1
全局 内容辅助 Alt+/
全局 全部选中 Ctrl+A
全局 删除 Delete
全局 上下文信息 Alt+?
Alt+Shift+?
Ctrl+Shift+Space
Java编辑器 显示工具提示描述 F2
Java编辑器 选择封装元素 Alt+Shift+↑
Java编辑器 选择上一个元素 Alt+Shift+←
Java编辑器 选择下一个元素 Alt+Shift+→
文本编辑器 增量查找 Ctrl+J
文本编辑器 增量逆向查找 Ctrl+Shift+J
全局 粘贴 Ctrl+V
全局 重做 Ctrl+Y

查看
作用域 功能 快捷键
全局 放大 Ctrl+=
全局 缩小 Ctrl+-


窗口
作用域 功能 快捷键
全局 激活编辑器 F12
全局 切换编辑器 Ctrl+Shift+W
全局 上一个编辑器 Ctrl+Shift+F6
全局 上一个视图 Ctrl+Shift+F7
全局 上一个透视图 Ctrl+Shift+F8
全局 下一个编辑器 Ctrl+F6
全局 下一个视图 Ctrl+F7
全局 下一个透视图 Ctrl+F8
文本编辑器 显示标尺上下文菜单 Ctrl+W
全局 显示视图菜单 Ctrl+F10
全局 显示系统菜单 Alt+-


导航
作用域 功能 快捷键
Java编辑器 打开结构 Ctrl+F3
全局 打开类型 Ctrl+Shift+T
全局 打开类型层次结构 F4
全局 打开声明 F3
全局 打开外部javadoc Shift+F2
全局 打开资源 Ctrl+Shift+R
全局 后退历史记录 Alt+←
全局 前进历史记录 Alt+→
全局 上一个 Ctrl+,
全局 下一个 Ctrl+.
Java编辑器 显示大纲 Ctrl+O
全局 在层次结构中打开类型 Ctrl+Shift+H
全局 转至匹配的括号 Ctrl+Shift+P
全局 转至上一个编辑位置 Ctrl+Q
Java编辑器 转至上一个成员 Ctrl+Shift+↑
Java编辑器 转至下一个成员 Ctrl+Shift+↓
文本编辑器 转至行 Ctrl+L


搜索
作用域 功能 快捷键
全局 出现在文件中 Ctrl+Shift+U
全局 打开搜索对话框 Ctrl+H
全局 工作区中的声明 Ctrl+G
全局 工作区中的引用 Ctrl+Shift+G


文本编辑
作用域 功能 快捷键
文本编辑器 改写切换 Insert
文本编辑器 上滚行 Ctrl+↑
文本编辑器 下滚行 Ctrl+↓


文件
作用域 功能 快捷键
全局 保存 Ctrl+X
Ctrl+S

posted @ 2009-04-06 11:46 胡鹏 阅读(267) | 评论 (0)编辑 收藏
仅列出标题
共10页: First 上一页 2 3 4 5 6 7 8 9 10 下一页 

导航

<2024年11月>
272829303112
3456789
10111213141516
17181920212223
24252627282930
1234567

统计

常用链接

留言簿(3)

随笔分类

随笔档案

agile

搜索

最新评论

阅读排行榜

评论排行榜