- 浏览: 236247 次
- 性别:
- 来自: 北京
文章分类
最新评论
-
akka_li:
学习了!但是为什么后续的没有了?!
EJB4:RMI和RMI-IIOP -
springaop_springmvc:
apache lucene开源框架demo使用实例教程源代码下 ...
Lucene学习笔记(一)Lucene入门实例 -
qepipnu:
求solr 客户端 jar包
Solr学习笔记(三)Solr客户端开发实例 -
zhangbc:
是这问题,赞!
Oracle Start Up 2 Oracle 框架构件、启动、解决一个问题 -
feilian09:
查询 select hibernate jdbc 那个效率快
Hibernate,JDBC性能探讨
对Hibernate属性(CascadeType、JoinColumn、JoinTable、ForeignKey等)的研究
- 博客分类:
- JavaEE
本文列出几个“EJB 学习阶段总结:JBoss下发布一个Toy企业应用”开发测试过程中遇到的几个问题。
1. Hibernate 懒加载有一定局限性:EJB远程调运时Hibernate懒加载Session失效
通过实例说明:给Entity类中添加Transformer类,Transformer与UserCard存在一对一的单向关联,如下:
@Entity(name="Transformer")
@Table(name="k_transformer")
public class Transformer implements Serializable{
private Long id;
private UserCard userCard;
@Column
@Id
@GeneratedValue
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
@OneToOne(
targetEntity = com.home.po.UserCard.class,
fetch = FetchType.LAZY,
cascade = { CascadeType.ALL })
@Cascade( { org.hibernate.annotations.CascadeType.ALL } )
@JoinColumn(name = "UserCard_id")
@ForeignKey(name = "TRANSFORMER_TO_USERCARD_FK")
public UserCard getUserCard() {
return userCard;
}
public void setUserCard(UserCard userCard) {
this.userCard = userCard;
}
}
注意OneToOne属性设定FetchType必须是LAZY,因为我们测试的是Hibernate懒加载
添加一个HibernateTest Session Bean,如下:
public interface TransformerService { public void persist(Transformer t); public void analysis(Long id); public Transformer analysisRemote(Long id); }
public interface TransformerServiceLocal extends TransformerService { }
@Stateless
@Remote(TransformerService.class)
@Local(TransformerServiceLocal.class)
public class TransformerServiceSession implements TransformerServiceLocal {
@PersistenceContext(unitName="com.home.po")
protected EntityManager em;
@TransactionAttribute(TransactionAttributeType.REQUIRED)
public void persist(Transformer t) {
em.persist(t);
}
@TransactionAttribute(TransactionAttributeType.REQUIRED)
public void analysis(Long id) {
Transformer t = em.find(Transformer.class, id);
analysisEntity(t);
}
private void analysisEntity(Transformer t) {
System.out.println(t.getUserCard());
}
@TransactionAttribute(TransactionAttributeType.REQUIRED)
public Transformer analysisRemote(Long id) {
return em.find(Transformer.class, id);
}
}
在客户端先向数据库中插入一条数据,在运行如下代码段:
public void analysis() throws NamingException {
……
TransformerService service = (TransformerService) ctx.lookup("home-test-all/TransformerServiceSession/remote");
service.analysis(new Long(1));
Transformer tra = service.analysisRemote(new Long(1));
analysisEntityInRemote(tra);
}
private void analysisEntityInRemote(Transformer t) {
System.out.println(t.getUserCard());
}
注意上述加红倾斜的代码段描述的方法analysisEntity,analysisEntityInRemote作用都是相同的,取出Transformer中UserCard属性,但是运行结果却如下,TransformerServiceSession 中的analysisEntity运行良好,Jboss Console控制台打印输出如下信息:
而Remote端Eclipse Console口抛出Session无效的异常:
Exception in thread "main" org.hibernate.LazyInitializationException: could not initialize proxy - no Session at org.hibernate.proxy.AbstractLazyInitializer.initialize(AbstractLazyInitializer.java:62) at org.hibernate.proxy.AbstractLazyInitializer.getImplementation(AbstractLazyInitializer.java:116) at org.hibernate.proxy.pojo.javassist.JavassistLazyInitializer.invoke(JavassistLazyInitializer.java:166) at com.home.po.UserCard_$$_javassist_0.toString(UserCard_$$_javassist_0.java) at java.lang.String.valueOf(Unknown Source) at java.io.PrintStream.println(Unknown Source) at com.home.ear.test.HibernateTestClient.analysisEntityInRemote(HibernateTestClient.java:41) at com.home.ear.test.HibernateTestClient.analysis(HibernateTestClient.java:37) at com.home.ear.test.HibernateTestClient.main(HibernateTestClient.java:47)
具体原因,继续研究中……
2 hibernate.jdbc.batch_size与 hibernate.jdbc.fetch_size初始值大小对Hibernate工作效率的影响:
修改Persistence Entity EJB模块中persistence.xml中Properties属性可以改变hibernate.jdbc.batch_size与 hibernate.jdbc.fetch_size的值,我做了如下两组测试,如下:
如下一,改变hibernate.jdbc.batch_size的大小,插入1000条User连续三次,记录每次插入时间,并计算出三次平均时间:
如下二改变Change hibernate.jdbc.fetch_size大小,从数据库中取出2000条和4000条数据,记录取出时间,如下:
如上两组数据,可以得出结论,在这个应用中hibernate.jdbc.batch_size设置为20-30之间Hibernate工作效率最好;而hibernate.jdbc.fetch_size是值设置为40左右Hibernate的工作效率最好
3 比较@OneToMany下@JoinColumn和@JoinTable的差别(对性能的影响)
@JoinColumn不产生级联表,将一方的主键存放在另一方的表中,如下,为JoinColumn的Entity Bean配置
以User与Friend为例:
@OneToMany ( targetEntity=com.home.po.Friend.class, fetch=FetchType.LAZY, cascade = { CascadeType.ALL }) @Cascade( { org.hibernate.annotations.CascadeType.ALL } ) @JoinColumn(name="userId") @ForeignKey(name="USER_TO_FRIEND_FK") public List<Friend> getFriends() { return friends; }
这种配置下 产生表如下图:
@JoinTable产生级联表,将双方的主键存放在一张独立的表中,如下为@JoinTable的配置
@OneToMany ( targetEntity=com.home.po.Friend.class, fetch=FetchType.LAZY, cascade = { CascadeType.ALL }) @Cascade( { org.hibernate.annotations.CascadeType.ALL } ) @JoinTable(name="k_user_friend", joinColumns = @JoinColumn(name = "USER_ID"), inverseJoinColumns = @JoinColumn(name = "FRIEND_ID")) @ForeignKey(name = "k_user_friend_FK", inverseName = "k_user_friend_FK_R") public List<Friend> getFriends() { return friends; }
这种配置下 产生表如下图:
如上用直线标出的5张表就是5对一对多关系产生的级联表,它里面存储两个表的主键。
这两种处理对数据的插入和存取有什么影响,就这一问题做如下测试:
1 分别在两种配置下通过EJB向数据库中插入2000个User 5次,记录每次时间,求出平均时间;
2 分别在两种配置下通过EJB从数据库中取出10000条数据5次,记录每次时间,求出平均时间;
结果如下两组图分别是JoinTable和JoinColumn下的测试数据
从上图比较可以得出结论:
1 JoinTable下操作数据库花费的时间要长于JolinColumn;
2 JolinColumn下节省的时间约为JoinTable下的2.5%;
分析原因:JoinTable花费时间多的原因是JoinTable下生成的中间表,要存取数据时都要查询中间的级联表,所以花费时间多;
4 测试建立外键与不建立外键两种情况下对存取数据库的影响
如上面3中都是设置外键的情况下测试的,下面我们在JoinColumn下做一组不设置外键的测试,不设置外键Annotation相当简单就是在原来的基础上去掉@ForeignKey标记,如下
@OneToMany ( targetEntity=com.home.po.Friend.class, fetch=FetchType.LAZY, cascade = { CascadeType.ALL }) @Cascade( { org.hibernate.annotations.CascadeType.ALL } ) @JoinColumn(name="userId") public List<Friend> getFriends() { return friends; }
为了对比我们假设两种情况,一是JolinColumn下配置ForeignKey,二是JolinColumn下不配置ForeignKey,在两种情况下做如下测试:
1 分别在两种配置下通过EJB向数据库中插入2000个User 5次,记录每次时间,求出平均时间;
2 分别在两种配置下通过EJB从数据库中取出10000条数据5次,记录每次时间,求出平均时间;
测试结果如下面两张表所示:
从上面两组图我们可以得出如下结论:
1 ForeignKey对数据库的存取影响比较大,特别是数据库的查询
2 设置ForeignKey可以减少数据库存取的时间
3 设置ForeignKey插入数据库节省的时间是不设置ForeignKey的5.5%,查询时则可以节省6.5%
--------------------------------------------------------------------------------------------------
说明:以上时间有一定局限性,只是在当前这种情况下测试的结果,不过可以当做参考。
发表评论
-
Oracle - Add Exist Validation Before Create Table
2011-11-07 13:49 1405Usually we need to check the ta ... -
JMX Architecture & "Hello Word" the JMX way
2011-10-25 20:07 1748JMX Architecture Overview: JMX ... -
Jboss-eap-5.1 Messaging
2011-08-02 21:50 2403This section I will concertate ... -
Jboss-eap-5.1 starting up note
2011-07-26 22:46 2545Jboss enterprise platform 5 hav ... -
EJB Security & JAAS Demo
2011-05-21 19:39 1577PROLOGUE: When deploying ... -
JBoss LoginInitialContext Factory Implementation
2011-05-15 16:05 1466Jboss has a series of imp ... -
Jboss Reference Exception Gallery
2011-04-27 14:08 28521. Unable to locate a login con ... -
Hibernate Annotation 的一个问题,给点意见
2011-03-10 12:43 22问题:org.hibernate.annotations. ... -
大家说说BBC的网站用的是什么技术做的
2011-02-22 05:01 1395最近在英国出差,发现这里的一些网站做的相当有特色,有些网站不是 ... -
Hibernate OneToMany 单向和双向配置对数据存取性能的比较
2011-02-08 17:06 22431. 开篇说明:今天是春 ... -
EJB 学习阶段总结:JBoss下发布一个Toy企业应用
2010-12-25 12:11 2549解释题目:为什 ... -
EJB7: Message Driven Bean
2010-12-21 22:42 2099在企业系统中需要使用 ... -
EJB6: EntityBean例子
2010-11-26 14:48 1442本例子描述向EJB容器(JBoss)部署http: ... -
JPA dev: 几个问题总结(续)
2010-11-25 18:02 24052. 如何由PoJo类生成数据库中的表 首先可以根据实体间关 ... -
JPA dev: 几个问题总结
2010-11-25 16:56 3353最近工作中遇到几个与JPA相关的问题,本文通过一个例子总结一下 ... -
JAXB学习
2010-11-24 22:35 01 什么是JAXB? JAXB全称Java Ar ... -
EJB5: JPA扩展-J2SE环境下使用EntityManager
2010-11-10 19:07 2643好久没有写博客了,最近比较忙,今天抽时间写点,最近 ... -
EJB4:RMI和RMI-IIOP
2010-11-02 21:14 4069计划提纲:引入→RMI概念→RMI HelloWorld程序→ ... -
EJB3: JBOSS 企业版、JBOSS服务器构架、EJB2.0 HelloWrold实例
2010-10-26 22:43 6415本文的研究基于jboss-eap- ... -
jboss-eap-4.3 启动停止在Configuring from URL: resource:jboss-log4j.xml 问题
2010-10-25 14:49 4009如题,我改用jboss-eap-4.3, 启动时停止在Conf ...
相关推荐
hibernate的_CascadeType属性说明
详解Hibernate cascade级联属性的CascadeType的用法 cascade(级联) 级联在编写触发器时经常用到,触发器的作用是当 主控表信息改变时,用来保证其关联表中数据同步更新。若对触发器来修改或删除关联表相记录,必须...
Hibernate 可以对类的属性或者方法进行注解。属性对应field类别,方法的 getXxx()对应property类别。 定义表 通过 @Table 为实体Bean指定对应数据库表,目录和schema的名字。 @Entity @Table(name="tbl_sky") ...
通过联接表处理单向一对多关联是首选方式,这种关联通过@JoinTable批注进行描述 @Entity Public class Trainer{ @OneToMany @JoinTable( name = "TrainedMonkeys", jonColumns = {@JoinColumn(name = "trainer_id...
很奇怪),分别是CascadeType.PERSIST(级联新建),CascadeType.REMOVE(级联删除),CascadeType.REFRESH(级联刷新),CascadeType.MERGE(级联更新),CascadeType.ALL(全部四项) * 方法一 * 主表: ?@OneToOne...
javax.persistence.JoinTable.class javax.persistence.Lob.class javax.persistence.LockModeType.class javax.persistence.LockTimeoutException.class javax.persistence.ManyToMany.class javax.persistence....
JPA的几个例子,一对一,一对多。 @ManyToOne(cascade = {CascadeType.ALL}, fetch = FetchType.LAZY) @JoinColumn(name = "personid", unique = false, nullable = true, insertable = true, updatable = true) ...
在前面的例子中,我们演示了一对多和多对一的例子,在本章将演示多对多和一对一的关系。 学生和老师就是多对多的关系。一个学生有多个老师,一个老师教多个学生。 学生和档案就是一对一的关系(不知道国外的学生有...
@OneToOne( cascade = { CascadeType.PERSIST, CascadeType.REMOVE }) @JoinColumn(name= "airplane_fk") private Airplane airplaneDetail; 现在,这可以使排期列表自动更新。 这也意味着,如果将飞行员添加到...
本文介绍自己最近做省市级联的类似的级联功能的实现思路,为了尽...CascadeType. PERSIST 级联持久化 ( 保存 ) 操作 CascadeType. MERGE 级联更新 ( 合并 ) 操作 CascadeType. REFRESH 级联刷新操作,只会查询获取操作