博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
转载:EntityManager的find()与getReference()的区别
阅读量:6264 次
发布时间:2019-06-22

本文共 1812 字,大约阅读时间需要 6 分钟。

  hot3.png

先说相同点

    这两个方法都接受实体的 class和代表实体主键的对象作为参数。由于它们使用了泛型方法,无需任何显示的类型转换即可获得特定类型的实体对象。其中,在primaryKey上面普遍使用了java5的autoboxing(自动装箱)的特性。

    再者,就是两者都会在EntityManager关闭的情况下抛出 - if this EntityManager has been closed. 在传入的第一个参数不是实体或者第二个参数不是一个有效的主键的情况下抛出

 - if the first argument does not denote an entity type or the second argument is not a valid type for that entity's primary key

不同点:

    find()返回指定OID的实体,如果这个实体存在于当前的persistence context中,那么返回值是被缓存的对象;否则会创建一个新的实体,并从数据库中加载相关的持久状态。如果数据库不存在指定的OID的记录,那么find()方法返回null。

    getReference()方法和find()相似。不同的是:如果缓存中没有指定的实体,EntityManager会创建一个新的实体,但是不会立即访问数据库来加载持久状态,而是在第一次访问某个属性的时候才加载。此外,getReference()方法不返回null,如果数据库找不到相应的实体,这个方法会抛出javax.persistence.EntityNotFoundException。

EntityNotFoundException - if the entity state cannot be accessed

某些场合下使用getReference()方法可以避免从数据库加载持久状态的性能开销。

   这里要着重提出的是两句话:

   如果缓存中没有指定的实体,EntityManager会创建一个新的实体,但是不会立即访问数据库来加载持久状态,而是在第一次访问某个属性的时候才加载。

   比如,em.find()返回的实体,我们就可以对它进行各种操作,而若对em.getReference()返回的实体,由于不会立即访问数据库来加载持久状态,对它进行的操作很可能就会出现Exception,比如在对它返回的实体做getter操作时,由于EntityManager对此采用延时加载,就会抛出org.hibernate.lazyinitializationexception could not initialize proxy no session

   因此将一个新的实体传递给事务的时候通常使用find()方法,而当不连接数据库,不使用getter方法,即使用setter方法改变状态时才使用getReference()方法。(这是由于getReference返回是一个Proxy实体,即没有加载持久状态)

   某些场合下使用getReference()方法可以避免从数据库加载持久状态的性能开销。

    这也完全是由于getReference返回是一个Proxy实体.

    比如一个简单的update操作,先使用find()获取实体,而后使用实体的setter方法;或者是getReference()方法,而后使用实体的setter方法。

    对于前者JPA调用的SQL:select ****,而后才是update ****

    对于后者:仅为update *****

又如:

操作                                                                            执行的SQL

em.remove(em.getReference(Person.class,1))         delete from Person where personid = 1

em.remove(em.find(Person.class,1))                 select * from Person where personid =1

                                                   delete from Person where personid =1

   由此可以看出,find()做了一次select的操作,而getReference并没有做有关数据库的操作,而是返回一个代理,这样它就减少了连接数据库和从数据库加载持久状态的开销。

  引用出处:

转载于:https://my.oschina.net/cwalet/blog/35746

你可能感兴趣的文章
给架构师骂了
查看>>
ajax提交form表单资料详细汇总
查看>>
Excel——使用INDEX和SMALL实现条件筛选
查看>>
c#迭代器 转载
查看>>
JQuery与JavaScript
查看>>
Jmeter--正则表达式提取器
查看>>
设置Slider Control 控件的取值范围
查看>>
struts2 启动tomcat时报错:org.apache.catalina.core.StandardContext filterStart
查看>>
asp.net导入后台代码
查看>>
java web dev知识积累
查看>>
Flex 经纬度匹配正则表达式
查看>>
在SSIS包中使用 Checkpoint从失败处重新启动包[转]
查看>>
为什么开通博客?
查看>>
深入浅出Mybatis系列(四)---配置详解之typeAliases别名(mybatis源码篇)
查看>>
LVS+Keepalived实现高可用负载均衡(转)
查看>>
Django学习【第14篇】:Django之Form组件补充
查看>>
在web.xml中配置初始化参数
查看>>
Java多线程下 ThreadLocal 的应用实例
查看>>
Serializable:序列化代理
查看>>
SQL中表约束是什么意思
查看>>