Hibernate属性中 @JoinColumn与@JoinTable、是否使用ForeignKey的操作数据库的效率区别
2014-08-26 20:39
447 查看
转自:http://kylinsoong.iteye.com/blog/852213
1. Hibernate 懒加载有一定局限性:EJB远程调运时Hibernate懒加载Session失效
通过实例说明:给Entity类中添加Transformer类,Transformer与UserCard存在一对一的单向关联,如下:
Java代码
![](https://oscdn.geek-share.com/Uploads/Images/Content/201909/19/45a4382a9d51382b73e0d996fdaa31f5.gif)
![](https://oscdn.geek-share.com/Uploads/Images/Content/201308/ce5a4c65b56138afd3326d6b149c7510.png)
![](https://oscdn.geek-share.com/Uploads/Images/Content/201909/19/179582369a77358ef22d735d5054c4a9.gif)
@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,
<strong><span style="color: rgb(255, 0, 0);"><em>fetch = FetchType.LAZY</em></span></strong>,
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,如下:
Java代码
![](https://oscdn.geek-share.com/Uploads/Images/Content/201909/19/45a4382a9d51382b73e0d996fdaa31f5.gif)
![](https://oscdn.geek-share.com/Uploads/Images/Content/201308/ce5a4c65b56138afd3326d6b149c7510.png)
![](https://oscdn.geek-share.com/Uploads/Images/Content/201909/19/179582369a77358ef22d735d5054c4a9.gif)
public interface TransformerService {
public void persist(Transformer t);
public void analysis(Long id);
public Transformer analysisRemote(Long id);
}
Java代码
![](https://oscdn.geek-share.com/Uploads/Images/Content/201909/19/45a4382a9d51382b73e0d996fdaa31f5.gif)
![](https://oscdn.geek-share.com/Uploads/Images/Content/201308/ce5a4c65b56138afd3326d6b149c7510.png)
![](https://oscdn.geek-share.com/Uploads/Images/Content/201909/19/179582369a77358ef22d735d5054c4a9.gif)
public interface TransformerServiceLocal extends TransformerService {
}
Java代码
![](https://oscdn.geek-share.com/Uploads/Images/Content/201909/19/45a4382a9d51382b73e0d996fdaa31f5.gif)
![](https://oscdn.geek-share.com/Uploads/Images/Content/201308/ce5a4c65b56138afd3326d6b149c7510.png)
![](https://oscdn.geek-share.com/Uploads/Images/Content/201909/19/179582369a77358ef22d735d5054c4a9.gif)
@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);
}
<span style="color: rgb(0, 0, 0);">private void analysisEntity(Transformer t) {
System.out.println(t.getUserCard());
}</span>
@TransactionAttribute(TransactionAttributeType.REQUIRED)
public Transformer analysisRemote(Long id) {
return em.find(Transformer.class, id);
}
}
在客户端先向数据库中插入一条数据,在运行如下代码段:
Java代码
![](https://oscdn.geek-share.com/Uploads/Images/Content/201909/19/45a4382a9d51382b73e0d996fdaa31f5.gif)
![](https://oscdn.geek-share.com/Uploads/Images/Content/201308/ce5a4c65b56138afd3326d6b149c7510.png)
![](https://oscdn.geek-share.com/Uploads/Images/Content/201909/19/179582369a77358ef22d735d5054c4a9.gif)
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);
}
<span style="color: rgb(0, 0, 0);">private void analysisEntityInRemote(Transformer t) {
System.out.println(t.getUserCard());
}</span>
注意上述加红倾斜的代码段描述的方法analysisEntity,analysisEntityInRemote作用都是相同的,取出Transformer中UserCard属性,但是运行结果却如下,TransformerServiceSession 中的analysisEntity运行良好,Jboss Console控制台打印输出如下信息:
![](https://oscdn.geek-share.com/Uploads/Images/Content/201911/04/9ff1807cab4372e9d587370a5c67afa1.png)
而Remote端Eclipse Console口抛出Session无效的异常:
Java代码
![](https://oscdn.geek-share.com/Uploads/Images/Content/201909/19/45a4382a9d51382b73e0d996fdaa31f5.gif)
![](https://oscdn.geek-share.com/Uploads/Images/Content/201308/ce5a4c65b56138afd3326d6b149c7510.png)
![](https://oscdn.geek-share.com/Uploads/Images/Content/201909/19/179582369a77358ef22d735d5054c4a9.gif)
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连续三次,记录每次插入时间,并计算出三次平均时间:
![](https://oscdn.geek-share.com/Uploads/Images/Content/201911/04/a2f0cbbe65bb7ba957e2c327c812370e.png)
如下二改变Change hibernate.jdbc.fetch_size大小,从数据库中取出2000条和4000条数据,记录取出时间,如下:
![](https://oscdn.geek-share.com/Uploads/Images/Content/201911/04/b5c2bd41f693136e9c4385931dc392f9.png)
如上两组数据,可以得出结论,在这个应用中hibernate.jdbc.batch_size设置为20-30之间Hibernate工作效率最好;而hibernate.jdbc.fetch_size是值设置为40左右Hibernate的工作效率最好
3 比较@OneToMany下@JoinColumn和@JoinTable的差别(对性能的影响)
@JoinColumn不产生级联表,将一方的主键存放在另一方的表中,如下,为JoinColumn的Entity Bean配置
以User与Friend为例:
Java代码
![](https://oscdn.geek-share.com/Uploads/Images/Content/201909/19/45a4382a9d51382b73e0d996fdaa31f5.gif)
![](https://oscdn.geek-share.com/Uploads/Images/Content/201308/ce5a4c65b56138afd3326d6b149c7510.png)
![](https://oscdn.geek-share.com/Uploads/Images/Content/201909/19/179582369a77358ef22d735d5054c4a9.gif)
@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;
}
这种配置下 产生表如下图:
![](https://oscdn.geek-share.com/Uploads/Images/Content/201911/04/43d007592f87dcdd066aacc108cfe9af.png)
@JoinTable产生级联表,将双方的主键存放在一张独立的表中,如下为@JoinTable的配置
Java代码
![](https://oscdn.geek-share.com/Uploads/Images/Content/201909/19/45a4382a9d51382b73e0d996fdaa31f5.gif)
![](https://oscdn.geek-share.com/Uploads/Images/Content/201308/ce5a4c65b56138afd3326d6b149c7510.png)
![](https://oscdn.geek-share.com/Uploads/Images/Content/201909/19/179582369a77358ef22d735d5054c4a9.gif)
@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;
}
这种配置下 产生表如下图:
![](https://oscdn.geek-share.com/Uploads/Images/Content/201911/04/ef1cee9074ef3c7789e2b9aa0babcad7.png)
如上用直线标出的5张表就是5对一对多关系产生的级联表,它里面存储两个表的主键。
这两种处理对数据的插入和存取有什么影响,就这一问题做如下测试:
1 分别在两种配置下通过EJB向数据库中插入2000个User 5次,记录每次时间,求出平均时间;
2 分别在两种配置下通过EJB从数据库中取出10000条数据5次,记录每次时间,求出平均时间;
结果如下两组图分别是JoinTable和JoinColumn下的测试数据
![](https://oscdn.geek-share.com/Uploads/Images/Content/201911/04/bc25bc6ba62b6fae20e1803e555274a9.png)
![](https://oscdn.geek-share.com/Uploads/Images/Content/201911/04/97178891378ae33cf6ad442950241afb.png)
从上图比较可以得出结论:
1 JoinTable下操作数据库花费的时间要长于JolinColumn;
2 JolinColumn下节省的时间约为JoinTable下的2.5%;
分析原因:JoinTable花费时间多的原因是JoinTable下生成的中间表,要存取数据时都要查询中间的级联表,所以花费时间多;
4 测试建立外键与不建立外键两种情况下对存取数据库的影响
如上面3中都是设置外键的情况下测试的,下面我们在JoinColumn下做一组不设置外键的测试,不设置外键Annotation相当简单就是在原来的基础上去掉@ForeignKey标记,如下
Java代码
![](https://oscdn.geek-share.com/Uploads/Images/Content/201909/19/45a4382a9d51382b73e0d996fdaa31f5.gif)
![](https://oscdn.geek-share.com/Uploads/Images/Content/201308/ce5a4c65b56138afd3326d6b149c7510.png)
![](https://oscdn.geek-share.com/Uploads/Images/Content/201909/19/179582369a77358ef22d735d5054c4a9.gif)
@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次,记录每次时间,求出平均时间;
测试结果如下面两张表所示:
![](https://oscdn.geek-share.com/Uploads/Images/Content/201911/04/97178891378ae33cf6ad442950241afb.png)
![](https://oscdn.geek-share.com/Uploads/Images/Content/201911/04/c3aa85826b9b8cc7c22615b267358bf7.png)
从上面两组图我们可以得出如下结论:
1 ForeignKey对数据库的存取影响比较大,特别是数据库的查询
2 设置ForeignKey可以减少数据库存取的时间
3 设置ForeignKey插入数据库节省的时间是不设置ForeignKey的5.5%,查询时则可以节省6.5%
Hibernate注解关系映射
转自:http://blog.163.com/wzx_dd/blog/static/194285072201282095713850/
西游记中的领导和被领导
excel中设定一列为下拉框,同时设定下拉框内容
| 标签:hibernate |举报|字号大中小 订阅
Hibernate Annotation关系映射的几种类型映射用法及使用方法(说明:以前实例的实体是user和role,主键分别是userid和roleid)
1)一对一外键关联映射(单向)
@OneToOne(cascade=CascadeType.ALL) //一对一外键关联,使用@OneToOne,并设置了级联操作
@JoinColumn(name="userid",unique=true) //@JoinColum设置了外键的名称为userid(数据库字段名),如果不设置,则默认为另一类的属性名+ _id。外键的值是唯一的(unique),不可重复,与另一类的主键一直
2)一对一外键关联映射(双向)
@OneToOne(mappedBy=" role",cascade=CascadeType.ALL) //一对一双向关联关系,使用@OneToOne。注意:需要加上mappedBy="role",如果不加上的话,role 也会生成一个外键(user_id),mappedby="role"需要指向与他关联对象的一个属性,说明双向关联关系中,有且仅有一端是作为主体(owner)端存在的,主体端负责维护联接列,对于不需要维护这种关系的从表则通过mappedBy属性进行声明,mappedBy的值指向主体的关联属性
//规律:只有是双向关联关系,都加上mappedby,cascade=CascadeType.ALL级联
3)一对一主键关联映射(不重要)
在实际中很少用,使用注解@PrimaryKeyJoinColumn,意思是说,我的主键去参考另外一张表中的主键,作为我的主键,但是在我测试
//多对多映射:注解@ManyToMany(单向),默认情况下,hibernate会自动的创建一张中间表来维护多对多关系
1. Hibernate 懒加载有一定局限性:EJB远程调运时Hibernate懒加载Session失效
通过实例说明:给Entity类中添加Transformer类,Transformer与UserCard存在一对一的单向关联,如下:
Java代码
![](https://oscdn.geek-share.com/Uploads/Images/Content/201909/19/45a4382a9d51382b73e0d996fdaa31f5.gif)
![](https://oscdn.geek-share.com/Uploads/Images/Content/201308/ce5a4c65b56138afd3326d6b149c7510.png)
![](https://oscdn.geek-share.com/Uploads/Images/Content/201909/19/179582369a77358ef22d735d5054c4a9.gif)
@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,
<strong><span style="color: rgb(255, 0, 0);"><em>fetch = FetchType.LAZY</em></span></strong>,
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;
}
}
@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, <strong><span style="color: rgb(255, 0, 0);"><em>fetch = FetchType.LAZY</em></span></strong>, 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,如下:
Java代码
![](https://oscdn.geek-share.com/Uploads/Images/Content/201909/19/45a4382a9d51382b73e0d996fdaa31f5.gif)
![](https://oscdn.geek-share.com/Uploads/Images/Content/201308/ce5a4c65b56138afd3326d6b149c7510.png)
![](https://oscdn.geek-share.com/Uploads/Images/Content/201909/19/179582369a77358ef22d735d5054c4a9.gif)
public interface TransformerService {
public void persist(Transformer t);
public void analysis(Long id);
public Transformer analysisRemote(Long id);
}
public interface TransformerService { public void persist(Transformer t); public void analysis(Long id); public Transformer analysisRemote(Long id); }
Java代码
![](https://oscdn.geek-share.com/Uploads/Images/Content/201909/19/45a4382a9d51382b73e0d996fdaa31f5.gif)
![](https://oscdn.geek-share.com/Uploads/Images/Content/201308/ce5a4c65b56138afd3326d6b149c7510.png)
![](https://oscdn.geek-share.com/Uploads/Images/Content/201909/19/179582369a77358ef22d735d5054c4a9.gif)
public interface TransformerServiceLocal extends TransformerService {
}
public interface TransformerServiceLocal extends TransformerService { }
Java代码
![](https://oscdn.geek-share.com/Uploads/Images/Content/201909/19/45a4382a9d51382b73e0d996fdaa31f5.gif)
![](https://oscdn.geek-share.com/Uploads/Images/Content/201308/ce5a4c65b56138afd3326d6b149c7510.png)
![](https://oscdn.geek-share.com/Uploads/Images/Content/201909/19/179582369a77358ef22d735d5054c4a9.gif)
@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);
}
<span style="color: rgb(0, 0, 0);">private void analysisEntity(Transformer t) {
System.out.println(t.getUserCard());
}</span>
@TransactionAttribute(TransactionAttributeType.REQUIRED)
public Transformer analysisRemote(Long id) {
return em.find(Transformer.class, id);
}
}
@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); } <span style="color: rgb(0, 0, 0);">private void analysisEntity(Transformer t) { System.out.println(t.getUserCard()); }</span> @TransactionAttribute(TransactionAttributeType.REQUIRED) public Transformer analysisRemote(Long id) { return em.find(Transformer.class, id); } }
在客户端先向数据库中插入一条数据,在运行如下代码段:
Java代码
![](https://oscdn.geek-share.com/Uploads/Images/Content/201909/19/45a4382a9d51382b73e0d996fdaa31f5.gif)
![](https://oscdn.geek-share.com/Uploads/Images/Content/201308/ce5a4c65b56138afd3326d6b149c7510.png)
![](https://oscdn.geek-share.com/Uploads/Images/Content/201909/19/179582369a77358ef22d735d5054c4a9.gif)
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);
}
<span style="color: rgb(0, 0, 0);">private void analysisEntityInRemote(Transformer t) {
System.out.println(t.getUserCard());
}</span>
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); } <span style="color: rgb(0, 0, 0);">private void analysisEntityInRemote(Transformer t) { System.out.println(t.getUserCard()); }</span>
注意上述加红倾斜的代码段描述的方法analysisEntity,analysisEntityInRemote作用都是相同的,取出Transformer中UserCard属性,但是运行结果却如下,TransformerServiceSession 中的analysisEntity运行良好,Jboss Console控制台打印输出如下信息:
![](https://oscdn.geek-share.com/Uploads/Images/Content/201911/04/9ff1807cab4372e9d587370a5c67afa1.png)
而Remote端Eclipse Console口抛出Session无效的异常:
Java代码
![](https://oscdn.geek-share.com/Uploads/Images/Content/201909/19/45a4382a9d51382b73e0d996fdaa31f5.gif)
![](https://oscdn.geek-share.com/Uploads/Images/Content/201308/ce5a4c65b56138afd3326d6b149c7510.png)
![](https://oscdn.geek-share.com/Uploads/Images/Content/201909/19/179582369a77358ef22d735d5054c4a9.gif)
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)
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连续三次,记录每次插入时间,并计算出三次平均时间:
![](https://oscdn.geek-share.com/Uploads/Images/Content/201911/04/a2f0cbbe65bb7ba957e2c327c812370e.png)
如下二改变Change hibernate.jdbc.fetch_size大小,从数据库中取出2000条和4000条数据,记录取出时间,如下:
![](https://oscdn.geek-share.com/Uploads/Images/Content/201911/04/b5c2bd41f693136e9c4385931dc392f9.png)
如上两组数据,可以得出结论,在这个应用中hibernate.jdbc.batch_size设置为20-30之间Hibernate工作效率最好;而hibernate.jdbc.fetch_size是值设置为40左右Hibernate的工作效率最好
3 比较@OneToMany下@JoinColumn和@JoinTable的差别(对性能的影响)
@JoinColumn不产生级联表,将一方的主键存放在另一方的表中,如下,为JoinColumn的Entity Bean配置
以User与Friend为例:
Java代码
![](https://oscdn.geek-share.com/Uploads/Images/Content/201909/19/45a4382a9d51382b73e0d996fdaa31f5.gif)
![](https://oscdn.geek-share.com/Uploads/Images/Content/201308/ce5a4c65b56138afd3326d6b149c7510.png)
![](https://oscdn.geek-share.com/Uploads/Images/Content/201909/19/179582369a77358ef22d735d5054c4a9.gif)
@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;
}
@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; }
这种配置下 产生表如下图:
![](https://oscdn.geek-share.com/Uploads/Images/Content/201911/04/43d007592f87dcdd066aacc108cfe9af.png)
@JoinTable产生级联表,将双方的主键存放在一张独立的表中,如下为@JoinTable的配置
Java代码
![](https://oscdn.geek-share.com/Uploads/Images/Content/201909/19/45a4382a9d51382b73e0d996fdaa31f5.gif)
![](https://oscdn.geek-share.com/Uploads/Images/Content/201308/ce5a4c65b56138afd3326d6b149c7510.png)
![](https://oscdn.geek-share.com/Uploads/Images/Content/201909/19/179582369a77358ef22d735d5054c4a9.gif)
@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;
}
@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; }
这种配置下 产生表如下图:
![](https://oscdn.geek-share.com/Uploads/Images/Content/201911/04/ef1cee9074ef3c7789e2b9aa0babcad7.png)
如上用直线标出的5张表就是5对一对多关系产生的级联表,它里面存储两个表的主键。
这两种处理对数据的插入和存取有什么影响,就这一问题做如下测试:
1 分别在两种配置下通过EJB向数据库中插入2000个User 5次,记录每次时间,求出平均时间;
2 分别在两种配置下通过EJB从数据库中取出10000条数据5次,记录每次时间,求出平均时间;
结果如下两组图分别是JoinTable和JoinColumn下的测试数据
![](https://oscdn.geek-share.com/Uploads/Images/Content/201911/04/bc25bc6ba62b6fae20e1803e555274a9.png)
![](https://oscdn.geek-share.com/Uploads/Images/Content/201911/04/97178891378ae33cf6ad442950241afb.png)
从上图比较可以得出结论:
1 JoinTable下操作数据库花费的时间要长于JolinColumn;
2 JolinColumn下节省的时间约为JoinTable下的2.5%;
分析原因:JoinTable花费时间多的原因是JoinTable下生成的中间表,要存取数据时都要查询中间的级联表,所以花费时间多;
4 测试建立外键与不建立外键两种情况下对存取数据库的影响
如上面3中都是设置外键的情况下测试的,下面我们在JoinColumn下做一组不设置外键的测试,不设置外键Annotation相当简单就是在原来的基础上去掉@ForeignKey标记,如下
Java代码
![](https://oscdn.geek-share.com/Uploads/Images/Content/201909/19/45a4382a9d51382b73e0d996fdaa31f5.gif)
![](https://oscdn.geek-share.com/Uploads/Images/Content/201308/ce5a4c65b56138afd3326d6b149c7510.png)
![](https://oscdn.geek-share.com/Uploads/Images/Content/201909/19/179582369a77358ef22d735d5054c4a9.gif)
@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;
}
@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次,记录每次时间,求出平均时间;
测试结果如下面两张表所示:
![](https://oscdn.geek-share.com/Uploads/Images/Content/201911/04/97178891378ae33cf6ad442950241afb.png)
![](https://oscdn.geek-share.com/Uploads/Images/Content/201911/04/c3aa85826b9b8cc7c22615b267358bf7.png)
从上面两组图我们可以得出如下结论:
1 ForeignKey对数据库的存取影响比较大,特别是数据库的查询
2 设置ForeignKey可以减少数据库存取的时间
3 设置ForeignKey插入数据库节省的时间是不设置ForeignKey的5.5%,查询时则可以节省6.5%
Hibernate注解关系映射
转自:http://blog.163.com/wzx_dd/blog/static/194285072201282095713850/
西游记中的领导和被领导
excel中设定一列为下拉框,同时设定下拉框内容
Hibernate注解关系映射
2012-09-20 11:14:08| 分类:java学习| 标签:hibernate |举报|字号大中小 订阅
Hibernate Annotation关系映射的几种类型映射用法及使用方法(说明:以前实例的实体是user和role,主键分别是userid和roleid)
1)一对一外键关联映射(单向)
@OneToOne(cascade=CascadeType.ALL) //一对一外键关联,使用@OneToOne,并设置了级联操作
@JoinColumn(name="userid",unique=true) //@JoinColum设置了外键的名称为userid(数据库字段名),如果不设置,则默认为另一类的属性名+ _id。外键的值是唯一的(unique),不可重复,与另一类的主键一直
2)一对一外键关联映射(双向)
@OneToOne(mappedBy=" role",cascade=CascadeType.ALL) //一对一双向关联关系,使用@OneToOne。注意:需要加上mappedBy="role",如果不加上的话,role 也会生成一个外键(user_id),mappedby="role"需要指向与他关联对象的一个属性,说明双向关联关系中,有且仅有一端是作为主体(owner)端存在的,主体端负责维护联接列,对于不需要维护这种关系的从表则通过mappedBy属性进行声明,mappedBy的值指向主体的关联属性
//规律:只有是双向关联关系,都加上mappedby,cascade=CascadeType.ALL级联
3)一对一主键关联映射(不重要)
在实际中很少用,使用注解@PrimaryKeyJoinColumn,意思是说,我的主键去参考另外一张表中的主键,作为我的主键,但是在我测试
//多对多映射:注解@ManyToMany(单向),默认情况下,hibernate会自动的创建一张中间表来维护多对多关系
相关文章推荐
- 使用properties属性文件做连接数据库的操作代码
- 使用Spring+Hibernate同时操作两个数据库
- Hibernate的注释该如何使用? 属性 数据库中 字段 实体 级联删除
- Java的Hibernate框架数据库操作中锁的使用和查询类型
- 使用Struts的Action来通过Hibernate对数据库进行增、删、改、查四项操作
- Hibernate 入门 使用Hibernate查询语言对数据库操作
- 使用Hibernate 操作数据库笔记
- 使用table自带方法和DOM方法操作HTML table的区别
- Hibernate不能使用@Table和@JoinColumn的问题
- Hibernate使用property-ref属性解决遗留数据库One To Many关系的问题。
- 在servicemix下,使用hibernate操作数据库
- 使用Hibernate编写通用数据库操作代码
- 使用Hibernate操作数据库需要七个…
- 使用Hibernate编写通用数据库操作代码
- Hibernate提供的操作数据库的方法使用和比较
- Spring中使用HibernateDaoSupport来进行数据库的操作
- 操作数据库(getHibernateTemplate()的使用)
- hibernate的hbm文件配置中set元素的fetch属性和outer-join属性有什么区别和联系?
- Hibernate – Many-to-Many example – join table + extra column (Annotation)
- 3.数据库操作相关术语,Oracle认证,insert into,批量插入,update tablename set,delete和truncate的区别,sql文件导入