使用hibernate.jdbc.work高性能处理批量数据


本文介绍如何使用Hibernate.jdbc.Work批量处理大量的数据(QCUD)

简介

为何使用原生的批量处理数据操作而不用现有的hibernate框架实现呢,因为hibernate对插入和更新的处理方式在大量数据插入式并不能更好的支持。

需求分析,如果你希望将一个对象的集合全部插入到数据库,但使用hibernate框架的批处理速度回比较慢,hibernate其实是一条一条的插入数据的,JDBC的BATCH不同是JDBC的bactch会先将sql预编译,再将集合的值SET进去,大大节省了编译SQL的时间。

经过测试:使用hibernate插入10条数据,需要预编译SQL10次,而原始JDBC的batch只需要预编译一次,且随着需要插入的数据增长需要的时间区别也越来越大,使用hibernate默认batch插入10000条数据需要1-2秒,优化后只需要200毫秒左右.

hibernate de persist he merge

     /**
         * Make an instance managed and persistent.
         * @param entity  entity instance
         * @throws EntityExistsException if the entity already exists.
         * (If the entity already exists, the <code>EntityExistsException</code> may
         * be thrown when the persist operation is invoked, or the
         * <code>EntityExistsException</code> or another <code>PersistenceException</code> may be
         * thrown at flush or commit time.)
         * @throws IllegalArgumentException if the instance is not an
         *         entity
         * @throws TransactionRequiredException if invoked on a
         *         container-managed entity manager of type
         *         <code>PersistenceContextType.TRANSACTION</code> and there is
         *         no transaction
         */
        public void persist(Object entity);

        /**
         * Merge the state of the given entity into the
         * current persistence context.
         * @param entity  entity instance
         * @return the managed instance that the state was merged to
         * @throws IllegalArgumentException if instance is not an
         *         entity or is a removed entity
         * @throws TransactionRequiredException if invoked on a
         *         container-managed entity manager of type
         *         <code>PersistenceContextType.TRANSACTION</code> and there is
         *         no transaction
         */
        public <T> T merge(T entity);

通过Hibernate的缓存进行批量插入

    public class HibernateTest {
        public static void main(String args[]){
            SessionFactory sessionFactory = hibernateTemplate.getSessionFactory();
            Session session = sessionFactory.openSession();
            Transaction tx  = session.beginTransaction(); //开启事务
            for(int i=0;i<50;i++){
                Usertable user = new Usertable();
                user.setPassword("100"+i);
                session.save(user);
                if(i%100==0){
                    session.flush();  
                    session.clear(); 
                }
            }
            ts.commit();
            HibernateSessionFactory.closeSession();
        }
    }

直接调用JDBC

    @Transactional(rollbackFor = Exception.class)
        public RpcServiceResult createSubThings(ArrayNode insertArray) {

            SessionFactory sessionFactory = hibernateTemplate.getSessionFactory();
            Session session = sessionFactory.openSession();
            Transaction tx  = session.beginTransaction(); //开启事务

            try {
                //do something
                String sqlStr = new String("INSERT INTO  table       ( `attribute1`,"
                                                                    + " `attribute2`, "
                                                                    + " `attribute3`"
                                                                    + ") "
                                        +  "VALUES (?, ?, ?);");

                Work work = new Work() {//Contract for performing a discrete piece of org.hibernate.jdbc.Work;
                    @Override
                    public void execute(Connection connection) throws SQLException {
                        PreparedStatement statement = connection.prepareStatement(sqlStr);
                        for (int i = 0; i < insertArray.size(); i++) {
                            JsonNode subThingJsonNode = insertArray.get(i);
                            String value1     = subThingJsonNode.get("key1").asText();
                            String value2   = subThingJsonNode.get("key2").asText();
                            String value3   = subThingJsonNode.get("key3").asText();
                            statement.setString(1,value1);
                            statement.setString(2,value2);
                            statement.setString(3,value3);
                            statement.addBatch();
                        }
                        statement.executeBatch();
                    }
                };
                session.doWork(work);
                tx.commit(); //提交事务
                ObjectNode responseNode = JsonNodeFactory.instance.objectNode();
                return new RpcServiceResult(HttpStatus.SC_OK, responseNode);
            } catch(HibernateException en) {
                tx.rollback();
                logger.error("Failed to save the ...");
                return new RpcServiceResult(HttpStatus.SC_INTERNAL_SERVER_ERROR);
            } catch (Exception en) {
                logger.error("Failed to save the ...");
                tx.rollback();
                return new RpcServiceResult(HttpStatus.SC_INTERNAL_SERVER_ERROR);
            } finally {
                session.close();
            }
        }

总结

使用此方法批量提交插入操作,不仅可以提高效率,也可以防止SQL注入, 同时UPDATE, DELETE 等操作也可以使用此方式.



   Reprint policy


《使用hibernate.jdbc.work高性能处理批量数据》 by jackromer is licensed under a Creative Commons Attribution 4.0 International License
 Previous
STORM介绍,集群搭建以及topology使用 STORM介绍,集群搭建以及topology使用
本文主要介绍STORM,以及storm集群的安装和使用 什么是storm Apache Storm是自由开源的分布式实时计算系统,擅长处理海量数据,适用于数据实时处理而非批处理。批处理使用的大多是鼎鼎大名的hadoop或者hive,作为一
2019-08-27
Next 
KAFKA介绍和集群搭建安装 KAFKA介绍和集群搭建安装
简介本文介绍KAFKA的特性和集群安装以及配合ACTIVEMQ使用 什么是KAFKA Kafka是由Apache软件基金会开发的一个开源流处理平台,由Scala和Java编写。Kafka是一种高吞吐量的分布式发布订阅消息系统,它可以处
2019-08-27
  目录