hibernate陷阱
来源:互联网 发布:java ee web.xml 编辑:程序博客网 时间:2024/04/29 16:33
今天写代码被师傅教育了
service层不要操作持久化对象
service
List<RequestDateTemplate> oldList=requestDateTemplateDao.find(systemBookCode, branchNums,null );
比如 这个,获取了一个hibernate持久化对象,我想获取里面属性,将其中某一个属性改变,把改变后的list 克隆成新的list,返回。
看似没啥问题,其实报错
如果改变这个oldlist,那么在事务结束时,hibernate会自动把这个持久化对象跟新成最新的数据,然后保存,所以有句话,在service层里面不要改变对象除非你真想改变他
所以我的做法是,先克隆一个对象,在把克隆的对象改了,原持久化oldlist对象不管,拿出来原封不动放回去即可。如果在事务之外操作则不会有啥问题
例子
ApplicationContext context = new ClassPathXmlApplicationContext( "application.xml"); SessionFactory factory = (SessionFactory) context .getBean("sessionFactroy"); Session s=factory.openSession(); Transaction t=s.beginTransaction(); SQLQuery query = s.createSQLQuery("select {i.*} from TEACHER {i}").addEntity("i",teacher.class); List<teacher> tt=query.list(); for(int i = 0;i<tt.size();i++){ System.out.println(tt.get(i)); tt.get(i).setAge(99); }t.commit();s.close();结果:
Hibernate: select i.teaid as teaid1_1_0_, i.name as name2_1_0_, i.course as course3_1_0_, i.age as age4_1_0_ from TEACHER iHibernate: select student0_.teaid as teaid4_1_1_, student0_.stuid as stuid1_0_1_, student0_.stuid as stuid1_0_0_, student0_.name as name2_0_0_, student0_.age as age3_0_0_, student0_.teaid as teaid4_0_0_ from student student0_ where student0_.teaid=?teacher [teaid=2, name=w, course=sqds, age=99, student=[]]Hibernate: select student0_.teaid as teaid4_1_1_, student0_.stuid as stuid1_0_1_, student0_.stuid as stuid1_0_0_, student0_.name as name2_0_0_, student0_.age as age3_0_0_, student0_.teaid as teaid4_0_0_ from student student0_ where student0_.teaid=?teacher [teaid=3, name=ssd, course=sqds, age=99, student=[]]Hibernate: select student0_.teaid as teaid4_1_1_, student0_.stuid as stuid1_0_1_, student0_.stuid as stuid1_0_0_, student0_.name as name2_0_0_, student0_.age as age3_0_0_, student0_.teaid as teaid4_0_0_ from student student0_ where student0_.teaid=?teacher [teaid=4, name=w, course=dfa, age=99, student=[]]Hibernate: select student0_.teaid as teaid4_1_1_, student0_.stuid as stuid1_0_1_, student0_.stuid as stuid1_0_0_, student0_.name as name2_0_0_, student0_.age as age3_0_0_, student0_.teaid as teaid4_0_0_ from student student0_ where student0_.teaid=?teacher [teaid=5, name=w, course=rr, age=99, student=[]]
这里也可以看出hibernate延迟加载的特性
我的teacher 有个list关联了student的
hibernate默认延迟加载为true,所以上面每个输出teacher.tostring时候会用到student,所以每次输出前查询
我设置如下后 改了延迟加载为false
<set name="student" table="student" inverse="true" lazy="false"> <key column="teaid"/> <one-to-many class="com.nhsoft.demo.model.student"/> </set>showsql如下
Hibernate: select i.teaid as teaid1_1_0_, i.name as name2_1_0_, i.course as course3_1_0_, i.age as age4_1_0_ from TEACHER iHibernate: select student0_.teaid as teaid4_1_1_, student0_.stuid as stuid1_0_1_, student0_.stuid as stuid1_0_0_, student0_.name as name2_0_0_, student0_.age as age3_0_0_, student0_.teaid as teaid4_0_0_ from student student0_ where student0_.teaid=?Hibernate: select student0_.teaid as teaid4_1_1_, student0_.stuid as stuid1_0_1_, student0_.stuid as stuid1_0_0_, student0_.name as name2_0_0_, student0_.age as age3_0_0_, student0_.teaid as teaid4_0_0_ from student student0_ where student0_.teaid=?Hibernate: select student0_.teaid as teaid4_1_1_, student0_.stuid as stuid1_0_1_, student0_.stuid as stuid1_0_0_, student0_.name as name2_0_0_, student0_.age as age3_0_0_, student0_.teaid as teaid4_0_0_ from student student0_ where student0_.teaid=?Hibernate: select student0_.teaid as teaid4_1_1_, student0_.stuid as stuid1_0_1_, student0_.stuid as stuid1_0_0_, student0_.name as name2_0_0_, student0_.age as age3_0_0_, student0_.teaid as teaid4_0_0_ from student student0_ where student0_.teaid=?teacher [teaid=2, name=w, course=sqds, age=99, student=[]]teacher [teaid=3, name=ssd, course=sqds, age=99, student=[]]teacher [teaid=4, name=w, course=dfa, age=99, student=[]]teacher [teaid=5, name=w, course=rr, age=99, student=[]]
lazy,延迟加载
Lazy的有效期:只有在session打开的时候才有效;session关闭后lazy就没效了。
lazy策略可以用在:
* <class>标签上:可以取值true/false
* <property>标签上,可以取值true/false,这个特性需要类增强
* <set>/<list>等集合上,可以取值为true/false/extra
* <one-to-one>/<many-to-one>等标签上,可以取值false/proxy/no-proxy
6.1 get和load的区别:
* get不支持延迟加载,而load支持。
* 当查询特定的数据库中不存在的数据时,get会返回null,而load则抛出异常。
6.2 类(Class)的延迟加载:
* 设置<class>标签中的lazy="true",或是保持默认(即不配置lazy属性)
* 如果lazy的属性值为true,那么在使用load方法加载数据时,只有确实用到数据的时候才会发出sql语句;这样有可能减少系统的开销。
* //不会发出查询sql
这里有一个问题,为什么加载主键的时候不需要发出sql语句。
6.3 集合(collection)的延迟加载:可以取值true,false,extra
* 保持集合上的lazy的默认值,此时的效果和lazy="extra"是基本一样的。
* 设置集合上的lazy=false
true:默认取值,它的意思是只有在调用这个集合获取里面的元素对象时,才发出查询语句,加载其集合元素的数据
false:取消懒加载特性,即在加载对象的同时,就发出第二条查询语句加载其关联集合的数据
extra:一种比较聪明的懒加载策略,即调用集合的size/contains等方法的时候,hibernate
并不会去加载整个集合的数据,而是发出一条聪明的SQL语句,以便获得需要的值,只有在真正需要用到这些集合元素对象数据的时候,才去发出查询语句加载所有对象的数据
6.4 Hibernate单端关联懒加载策略:即在<one-to-one>/<many-to-one>标签上可以配置
懒加载策略。可以取值为:false/proxy/no-proxy
false:取消懒加载策略,即在加载对象的同时,发出查询语句,加载其关联对象
proxy:这是hibernate对单端关联的默认懒加载策略,即只有在调用到其关联对象的方法的时候才真正发出查询语句查询其对象数据,其关联对象是代理类
no-proxy:这种懒加载特性需要对类进行增强,使用no-proxy,其关联对象不是代理类
注意:在class标签上配置的lazy属性不会影响到关联对象!!!
MERGE
merge的作用是:新new一个对象,如果该对象设置了ID,则这个对象就当作游离态处理:
当ID在数据库中不能找到时,用update的话肯定会报异常,然而用merge的话,就会insert。
当ID在数据库中能找到的时候,update与merge的执行效果都是更新数据,发出update语句;
如果没有设置ID的话,则这个对象就当作瞬态处理:
用update的话,由于没有ID,所以会报异常,merge此时则会保存数据,根据ID生产策略生成一条数据;
hibernate不允许同一个session中有两个相同的持久化对象,merge调用后不持久化调用的对象,直接更新数据库。
- hibernate陷阱
- Hibernate 的 Proxy 陷阱
- “陷阱”
- 陷阱!!!!!!!!!
- Spring与Hibernate调整自动扫描时的陷阱
- 在weblogic中使用spring查找hibernate映射文件的陷阱
- 在weblogic中使用spring查找hibernate映射文件的陷阱
- 理想陷阱
- AJAX陷阱
- Deque陷阱
- DB2陷阱
- 美人陷阱
- 词法陷阱
- 语法陷阱
- 语义陷阱
- SQLServer陷阱
- 财务报表陷阱
- ACE陷阱
- ios企业开发者证书无效
- Qt :libpng warning: iCCP: known incorrect sRGB profile警告信息之解决方法
- 线程的生命周期
- iOS推送的问题
- 猎奇过后,VR还有什么能让用户买单?
- hibernate陷阱
- Spring Boot下Druid连接池的使用配置分析
- 走向灵活的软件之路--面向对象六大基本原则
- Android-25种开源炫酷动画框架
- excel转html
- 精通 CSS+DIV 网页样式与布局 142
- android studio 开发java工程遇到的问题
- python/pandas/numpy(十二)数据加载、存储与文件格式
- 解决 融云java.lang.NoClassDefFoundError: io.rong.imkit错误