hibernate批处理

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

你可能感兴趣的:(hibernate批处理)