sva605
sva605

Reputation: 1691

Hibernate: batch and non-batch inserts generate the same amount of SQL-queries

There is a code sample consisting of two entities with bidirectional mapping.

@Entity
@Table(name = "Post")
@NoArgsConstructor
@Data
public class Post {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private long id;

    @OneToMany(mappedBy = "post", cascade = CascadeType.ALL, orphanRemoval = true)
    private Set<Comment> comments = new HashSet<>();

    public void addComment(Comment comment) {
        comments.add(comment);
    }

    public void removeComment(Comment comment) {
        comments.remove(comment);
    }
}

@Entity
@Table(name = "Comment")
@NoArgsConstructor
@Data
@EqualsAndHashCode(exclude = {"id", "post"})
public class Comment {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private long id;

    @Column(nullable = false)
    private String review;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "post_id", updatable = false, nullable = false)
    private Post post;

    public Comment(Post post, String review) {
        this.post = post;
        this.review = review;
    }
}

Configuration

@SpringBootApplication(exclude = HibernateJpaAutoConfiguration.class)
@PropertySource("classpath:application.properties")
@ComponentScan("jpaDifferent")
public class RootConfig {

    public static void main(String[] args) throws Exception {
        ApplicationContext applicationContext = new AnnotationConfigApplicationContext(RootConfig.class);
        DaoCollections daoCollections = applicationContext.getBean(DaoCollections.class);
        Post post = new Post();
        for (int i = 0; i < 30; i++) {
            post.addComment(new Comment(post, "Comment No. " + i));
        }
        daoCollections.savePost(post);
}

    @Bean
    @ConfigurationProperties(prefix = "db")
    public DataSource dataSource() {
        return new BasicDataSource();
    }

    @Bean
    public LocalSessionFactoryBean sessionFactory() {
        LocalSessionFactoryBean sfb = new LocalSessionFactoryBean();
        sfb.setDataSource(dataSource());
        sfb.setPackagesToScan("jpaDifferent");
        sfb.setHibernateProperties(properties());
        return sfb;
    }

    private Properties properties() {
        Properties properties = new Properties();
        properties.setProperty("hibernate.dialect", "org.hibernate.dialect.MySQL5Dialect");
        properties.setProperty("hibernate.hbm2ddl.auto", "update");
        properties.setProperty("hibernate.show_sql", "true");
        properties.setProperty("hibernate.jdbc.batch_size", "10");
        properties.setProperty("hibernate.order_inserts", "true");
        properties.setProperty("hibernate.order_updates", "true");
        properties.setProperty("hibernate.jdbc.batch_versioned_data", "true");
        return properties;
    }

    @Bean
    public HibernateTransactionManager transactionManager() {
        HibernateTransactionManager transactionManager = new HibernateTransactionManager();
        transactionManager.setSessionFactory(sessionFactory().getObject());
        return transactionManager;
    }
}

Dao

@Repository
@Transactional
public class DaoCollections {

    @Autowired
    private SessionFactory sessionFactory;

    private Session currentSession() {
        return sessionFactory.getCurrentSession();
    }

    public void savePost(Post post) {
        currentSession().persist(post);
    }
}

Hibernate log contains 30 'insert' lines:

Hibernate: insert into Post values ( )
Hibernate: insert into Comment (post_id, review) values (?, ?)
Hibernate: insert into Comment (post_id, review) values (?, ?)
...........
Hibernate: insert into Comment (post_id, review) values (?, ?)

According to Properties in configuration file containing instructions regarding batching, I expect 3 'insert' SQL-queries to be generated. But instead there are 30, one for each 'Comment'. I don't know whether I misunderstood something regarding batching and it is, in fact, not supposed to optimize the number of queries or maybe something is just wrong with configuration.

Upvotes: 0

Views: 392

Answers (2)

kalyan k
kalyan k

Reputation: 19

Its because of the Identity Id. Hibernate does not batch when the Id is of type Identity. Use custom or sequences.

Upvotes: 1

Aleh Maksimovich
Aleh Maksimovich

Reputation: 2650

The Batch Updates is a way of optimizing SQL execution by sending set of update SQL statements to database as a single unit instead of series of database calls.

Setting a batch size just tells Hibernate that it can batch statements up to hibernate.jdbc.batch_size in one batch: ref

A non-zero value enables use of JDBC2 batch updates by Hibernate. e.g. recommended values between 5 and 30

You should not expect less SQL statements generated. It's all about them being send on a single call. More on batching here.

Upvotes: 0

Related Questions