Session session = sessionFactory.openSession();Transaction tx = session.beginTransaction();for ( int i=0; i<100000; i++ ) {Customer customer = new Customer(.....);
session.save(customer);}tx.commit();session.close();
因为hibernate会把实体缓存到session中,会报outofmemory异常
启用批处理之前,启用jdbc batching。通过设置hibernate.jdbc.batch_size在10到50之间。但是当主键策略使用identity的时候,hibernate会透明的在jdbc级别禁用掉批处理。JDBC批处理可以减少与数据库交互,提高性能;但save identity需要马上返回标识符,所以会禁用jdbc batching。
如果此方法不合适,你可以禁用掉二级缓存,通过设置hibernate.cache.use_second_level_cache为false
批量插入
Session session = sessionFactory.openSession();Transaction tx = session.beginTransaction();for ( int i=0; i<100000; i++ ) {Customer customer = new Customer(.....);
session.save(customer);if ( i % 20 == 0 ) { //20, same as the JDBC batch size//flush a batch of inserts and release memory:
session.flush();session.clear();}}tx.commit();session.close();
当持久化新对象的时候,使用flush和clear来控制一级缓存的大小
批量更新
Session session = sessionFactory.openSession(); Transaction tx = session.beginTransaction(); ScrollableResults customers = session.getNamedQuery("GetCustomers") .setCacheMode(CacheMode.IGNORE) .scroll(ScrollMode.FORWARD_ONLY); int count=0; while ( customers.next() ) { Customer customer = (Customer) customers.get(0); customer.updateStuff(...); if ( ++count % 20 == 0 ) { //flush a batch of updates and release memory: session.flush(); session.clear(); } } tx.commit(); session.close();
当你检索数据去更新的时候,同样使用flush和clear来控制一级缓存,当查询到的数据很大时使用scroll来使用server-side缓存,而不使用client-side缓存。
JDBC的resultset有几种类型
默认是forward-only,这种方法不在客户端即jvm作缓存,只在数据库端缓存,而数据库端的cursor不支持后退,定位等操作,所以只能向前取数
scrollable-insensitive,可以后退,定位,实现方式是将数据缓存到jvm内存,所以当数据量大时可能会内存溢出。因为是直接缓存的原始数据,所以对数据库的变化是无法感知的
scrollable-sensitive,同样可以后退,定位等,同时可以感知数据的变化。其实现方式是只缓存数据的rowid到jvm缓存,到实际取字段时才去数据库查询数据。
JDBC的preparedstatement和statement
preparedstatement有3个好处
1.代码可读性和维护性强
2.性能优势,当只是参数改变的时候,可以使用数据库缓存的sql语句
3.安全优势,可以避免sql注入的危险,因为statement需要拼语句
statelesssession
StatelessSession session = sessionFactory.openStatelessSession(); Transaction tx = session.beginTransaction(); ScrollableResults customers = session.getNamedQuery("GetCustomers") .scroll(ScrollMode.FORWARD_ONLY); while ( customers.next() ) { Customer customer = (Customer) customers.get(0); customer.updateStuff(...); session.update(customer); } tx.commit(); session.close();
一个低级的接口,没有persistencecontext的概念,数据一查询出来就是托管的,没有一级缓存的概念,也无法与二级缓存交互。
insert,update,delete会直接触发sql执行,而且这个接口有很多限制,尤其是会忽略集合,一般很少用
HQL
直接使用hql操作insert,update,delete
update中如果要带version,可以使用update versioned,这种情况下,不能使用自定义version类型
语句中如果有别名,所有字段都要带别名
可以支持insert into。。。select