Spring Data Jpa bulk insert 하는 방법

itbuddy·2024년 3월 18일

기본적인 Batch insert 설정


 ~~ jdbcUrl: jdbc:mysql://localhost:3306/one?serverTimezone=Asia/Seoul&rewriteBatchedStatements=true
spring:
	jpa:
		properties:
			hibernate.jdbc.batch_size: 100
			hibernate.order_inserts: true
			hibernate.order_updates: true

위와 같이 설정한 후에 saveAll을 사용하면 된다.

Mysql + autoincrement GenerationType.IDENTITY

이 경우는 bulk insert가 비활성화 되기 때문에 JdbcTemplate으로 수행해야 한다.
이유는 JPA는 insert할 row의 pk를 한번 또는 여러번에 걸쳐 채번하여 쿼리를 완성시킨후에 insert를 수행하는데
autoincrement 전략은 채번을 하기 위해서는 각각의 row의 insert를 수행해줘야 하기 때문이다.

~~
		 @Transactional(readOnly = false)
		 public void bulkMerge(List<SurveyReportSheet> surveyReportSheets) {
				 String sql = "INSERT INTO tb_pinesurvey_survey_report_sheet (report_key, question_id, answer_id, answer_essay) VALUES (?, ?, ?, ?) ON DUPLICATE KEY UPDATE answer_essay = ?";
				 getJdbcTemplate().batchUpdate(sql, new BatchPreparedStatementSetter() {

						 @Override
						 public void setValues(PreparedStatement ps, int i) throws SQLException {
								 SurveyReportSheet surveyReportSheet = surveyReportSheets.get(i);
								 ps.setLong(1, surveyReportSheet.getId().getReportKey());
								 ps.setInt(2, surveyReportSheet.getId().getQuestionId());
								 ps.setInt(3, surveyReportSheet.getId().getAnswerId());
								 ps.setString(4, surveyReportSheet.getAnswerEssay());
								 ps.setString(5, surveyReportSheet.getAnswerEssay());
						 }

						 @Override
						 public int getBatchSize() {
								 return surveyReportSheets.size();
						 }
				 });
				 entityManager.clear();
		 }
~~

mysql에서 saveAll을 사용하는 방법

GenerationType.TABLE 방식을 사용하면 된다.
채번 할때 select를 하여 성능 손실이 발생한다는 단점이 있지만.
이렇게 사용하는 것이 어떤 DB에서도 작동하여서 호환성이 좋다.


@Entity
@EntityListeners(AuditingEntityListener.class)
/*
* name = (Required) A unique generator name that can be referenced by one or more classes to be the generator for id values.
* table = (Optional) Name of table that stores the generated id values.
Defaults to a name chosen by persistence provider
* pkColumnValue = (Optional) The primary key value in the generator table that distinguishes this set of generated values from others that may be stored in the table.
Defaults to a provider-chosen value to store in the primary key column of the generator table
* allocationSize = (Optional) The amount to increment by when allocating id numbers from the generator.
*/
@TableGenerator(
		name = "seq_survey",
		table = "tb__seq",
		pkColumnValue = "seq_survey",
		allocationSize = 50)
@Table(name = "tb_survey")
public class Survey implements Serializable, Comparable<Survey> {

/* ############################################# Mybatis Generator 생성 at 20230323_112501 ############################################# */
	@Id
	@GeneratedValue(strategy = GenerationType.TABLE, generator = "seq_survey")
	@NotNull
	@Column(name = "survey_key", nullable = false)
	private Long id;

	@NotNull
	@Column(name = "survey_title", nullable = false, length = 100)
	private String surveyTitle;

	@NotNull
	@Column(name = "survey_desc", nullable = false, length = 500)
	private String surveyDesc;

	@NotNull
	@Column(name = "survey_type", nullable = false, length = 20)
	private String surveyType;

	@NotNull
	@Column(name = "survey_status", nullable = false, length = 20)
	private String surveyStatus;

	@NotNull
	@Column(name = "start_at", nullable = false)
	private Instant startDt;

	@NotNull
	@Column(name = "end_at", nullable = false)
	private Instant endDt;

	@NotNull
	@Column(name = "visible_yn", nullable = false, length = 1)
	private String visibleYn;

	@NotNull
	@CreatedDate
	@Column(name = "created_at", nullable = false)
	private Instant regDt;

	@NotNull
	@LastModifiedDate
	@Column(name = "updated_at", nullable = false)
	private Instant modDt;
	

}

JPA를 사용할때 GenerationType.SEQUENCE 를 사용할수 있는 DB를 고르도록 하자

profile
프론트도 조금 아는 짱구 같은 서버 프로그래머

0개의 댓글