I have sample project using spring-boot-2.0.3
with spring-data-jpa-2.0.3
and postgresql-9.5.13
. It has only three classes: @Entity
, @Repository
and main class. DB has only one table with two fields: id
and name
.
I'm trying to INSERT
100 000
records in the loop into the table and measure execution time - enabling or disabling flush()
method from EntityManager
class for each 100 records.
Expected result is that execution time with enabled flush()
method is much less then with disabled one, but actually I have the opposite result.
Question: What am I doing wrong?
Project structure:
application.properties
spring.datasource.driver-class-name=org.postgresql.Driver
spring.datasource.url=jdbc:postgresql://localhost:5432/twofold
spring.datasource.username=postgres
spring.datasource.password=postgres
User.java
package twofold.data;
import javax.persistence.*;
@Entity
@Table(name = "users", schema = "public")
public class User {
private Long id;
private String name;
public User() {}
public User(String name) {
this.name = name;
}
@Id
@SequenceGenerator(name = "users_id_seq", sequenceName = "users_id_seq", allocationSize = 1)
@GeneratedValue(strategy = GenerationType.TABLE, generator = "users_id_seq")
@Column(name = "id", nullable = false)
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
@Column(name = "name", nullable = false, length = 50)
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "id: " + id + "; name: " + name + ";";
}
}
UserRepository.java
package twofold.data;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
@Repository
public interface UserRepository extends JpaRepository<User, Long> {
}
Application.java
package twofold;
import twofold.data.User;
import twofold.data.UserRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.transaction.annotation.Transactional;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
@Autowired
private UserRepository userRepository;
@PersistenceContext
private EntityManager entityManager;
@Bean
public CommandLineRunner addUsers() {
return new CommandLineRunner() {
@Transactional
public void run(String... args) throws Exception {
long incoming = System.currentTimeMillis();
for (int i = 1; i <= 100000; i++) {
userRepository.save(new User(i + "_name"));
if (i % 100 == 0) {
entityManager.flush();
entityManager.clear();
}
}
System.out.println("Time: " + (System.currentTimeMillis()-incoming));
}
};
}
}
You have to set following hibernate properties.
<property name="hibernate.jdbc.batch_size" value="25" />
<property name="hibernate.order_inserts" value="true" />
<property name="hibernate.order_updates" value="true" />
Then do like this:
int entityCount = 50;
int batchSize = 25;
EntityManager entityManager = entityManagerFactory().createEntityManager();
EntityTransaction entityTransaction = entityManager.getTransaction();
try {
entityTransaction.begin();
for (int i = 0; i < entityCount; i++) {
if (i > 0 && i % batchSize == 0) {
entityTransaction.commit();
entityTransaction.begin();
entityManager.clear();
}
Post post = new Post(
String.format("Post %d", i + 1)
);
entityManager.persist(post);
}
entityTransaction.commit();
} catch (RuntimeException e) {
if (entityTransaction.isActive()) {
entityTransaction.rollback();
}
throw e;
} finally {
entityManager.close();
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.