Skip to content

Commit ccd520b

Browse files
committed
GETP-324 feat: 프로젝트 지원 배치 삽입 기능 구현
1 parent 5efa2af commit ccd520b

20 files changed

+461
-23
lines changed
Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
package es.princip.getp.batch;
22

3-
import es.princip.getp.batch.project.BatchDeleteProjectService;
4-
import es.princip.getp.batch.project.ParallelBatchInsertProjectService;
3+
import es.princip.getp.batch.project.commission.BatchDeleteProjectService;
4+
import es.princip.getp.batch.project.commission.ParallelBatchInsertProjectService;
5+
import es.princip.getp.batch.project.apply.BatchDeleteProjectApplicationService;
6+
import es.princip.getp.batch.project.apply.BatchInsertProjectApplicationService;
57
import org.springframework.beans.factory.annotation.Autowired;
68
import org.springframework.boot.CommandLineRunner;
79
import org.springframework.boot.SpringApplication;
@@ -10,16 +12,23 @@
1012
@SpringBootApplication
1113
public class GetpBatchApplication implements CommandLineRunner {
1214

15+
@Autowired private BatchDeleteProjectApplicationService batchDeleteProjectApplicationService;
1316
@Autowired private BatchDeleteProjectService batchDeleteProjectService;
17+
18+
@Autowired private BatchInsertProjectApplicationService batchInsertProjectApplicationService;
1419
@Autowired private ParallelBatchInsertProjectService batchInsertProjectService;
1520

1621
public static void main(String[] args) {
1722
SpringApplication.run(GetpBatchApplication.class, args);
1823
}
1924

25+
private static final int PROJECT_SIZE = 100_000;
2026
@Override
2127
public void run(final String... args) {
28+
batchDeleteProjectApplicationService.delete();
2229
batchDeleteProjectService.delete();
23-
batchInsertProjectService.insert(100_000);
30+
31+
batchInsertProjectService.insert(PROJECT_SIZE);
32+
batchInsertProjectApplicationService.insert(PROJECT_SIZE);
2433
}
2534
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
package es.princip.getp.batch;
2+
3+
import java.util.concurrent.atomic.AtomicLong;
4+
5+
public class UniqueLongGenerator {
6+
private static final AtomicLong counter = new AtomicLong();
7+
8+
public static long generateUniqueLong() {
9+
return counter.incrementAndGet();
10+
}
11+
}

get-p-batch/src/main/java/es/princip/getp/batch/parallel/ParallelBatchInsertService.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,9 @@ public class ParallelBatchInsertService {
1717

1818
@Getter
1919
private final int numThreads = Runtime.getRuntime().availableProcessors();
20-
private final ExecutorService executorService = Executors.newFixedThreadPool(numThreads);
2120

2221
public void insert(final int size, final ParallelBatchInserter batchInserter) {
22+
final ExecutorService executorService = Executors.newFixedThreadPool(numThreads);
2323
final List<CompletableFuture<Void>> futures = new ArrayList<>();
2424
final int batchSize = size / numThreads;
2525
for (int i = 0; i < numThreads; i++) {
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
package es.princip.getp.batch.project.apply;
2+
3+
import lombok.RequiredArgsConstructor;
4+
import lombok.extern.slf4j.Slf4j;
5+
import org.springframework.jdbc.core.JdbcTemplate;
6+
import org.springframework.stereotype.Service;
7+
8+
@Slf4j
9+
@Service
10+
@RequiredArgsConstructor
11+
public class BatchDeleteProjectApplicationService {
12+
13+
private final JdbcTemplate jdbcTemplate;
14+
15+
public void delete() {
16+
jdbcTemplate.execute("delete from team_project_application_teammate");
17+
jdbcTemplate.execute("delete from team_project_application");
18+
jdbcTemplate.execute("delete from individual_project_application");
19+
jdbcTemplate.execute("delete from project_application_attachment_file");
20+
jdbcTemplate.execute("delete from project_application");
21+
log.info("Table \"team_project_application_teammate\" is dropped");
22+
log.info("Table \"team_project_application\" is dropped");
23+
log.info("Table \"individual_project_application\" is dropped");
24+
log.info("Table \"project_application_attachment_file\" is dropped");
25+
log.info("Table \"project_application\" is dropped");
26+
}
27+
}
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
package es.princip.getp.batch.project.apply;
2+
3+
import es.princip.getp.domain.project.apply.model.IndividualProjectApplication;
4+
import es.princip.getp.domain.project.apply.model.ProjectApplication;
5+
import lombok.RequiredArgsConstructor;
6+
import org.springframework.jdbc.core.BatchPreparedStatementSetter;
7+
import org.springframework.jdbc.core.JdbcTemplate;
8+
import org.springframework.stereotype.Service;
9+
10+
import java.sql.PreparedStatement;
11+
import java.sql.SQLException;
12+
import java.util.List;
13+
14+
@Service
15+
@RequiredArgsConstructor
16+
class BatchInsertIndividualProjectApplicationJdbcService {
17+
18+
private final JdbcTemplate jdbcTemplate;
19+
private static final String sql =
20+
"""
21+
insert into individual_project_application (
22+
project_application_id
23+
) values (?);
24+
""";
25+
26+
public void batchUpdate(final List<ProjectApplication> applications) {
27+
final List<IndividualProjectApplication> individuals = applications.stream()
28+
.filter(IndividualProjectApplication.class::isInstance)
29+
.map(IndividualProjectApplication.class::cast)
30+
.toList();
31+
32+
jdbcTemplate.batchUpdate(sql, new BatchPreparedStatementSetter() {
33+
@Override
34+
public void setValues(final PreparedStatement ps, final int i) throws SQLException {
35+
final IndividualProjectApplication application = individuals.get(i);
36+
ps.setLong(1, application.getId().getValue());
37+
}
38+
39+
@Override
40+
public int getBatchSize() {
41+
return individuals.size();
42+
}
43+
});
44+
}
45+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
package es.princip.getp.batch.project.apply;
2+
3+
import es.princip.getp.domain.common.model.AttachmentFile;
4+
import es.princip.getp.domain.project.apply.model.ProjectApplication;
5+
import es.princip.getp.domain.project.apply.model.ProjectApplicationId;
6+
import lombok.RequiredArgsConstructor;
7+
import org.springframework.jdbc.core.BatchPreparedStatementSetter;
8+
import org.springframework.jdbc.core.JdbcTemplate;
9+
import org.springframework.stereotype.Service;
10+
11+
import java.sql.PreparedStatement;
12+
import java.sql.SQLException;
13+
import java.util.List;
14+
15+
@Service
16+
@RequiredArgsConstructor
17+
class BatchInsertProjectApplicationAttachmentFileJdbcService {
18+
19+
private record ProjectApplicationIdAttachmentFile(
20+
ProjectApplicationId applicationId,
21+
AttachmentFile attachmentFile
22+
) {
23+
}
24+
25+
private final JdbcTemplate jdbcTemplate;
26+
private static final String sql =
27+
"""
28+
insert into project_application_attachment_file(
29+
project_application_id,
30+
attachment_files
31+
) values (?, ?);
32+
""";
33+
34+
public void batchUpdate(final List<ProjectApplication> applications) {
35+
final List<ProjectApplicationIdAttachmentFile> attachmentFiles = applications.stream()
36+
.flatMap(application -> application.getAttachmentFiles().stream()
37+
.map(attachmentFile -> new ProjectApplicationIdAttachmentFile(
38+
application.getId(),
39+
attachmentFile
40+
)))
41+
.toList();
42+
43+
jdbcTemplate.batchUpdate(sql, new BatchPreparedStatementSetter() {
44+
@Override
45+
public void setValues(final PreparedStatement ps, final int i) throws SQLException {
46+
final ProjectApplicationId applicationId = attachmentFiles.get(i).applicationId();
47+
final AttachmentFile attachmentFile = attachmentFiles.get(i).attachmentFile();
48+
ps.setLong(1, applicationId.getValue());
49+
ps.setString(2, attachmentFile.getUrl().getValue());
50+
}
51+
52+
@Override
53+
public int getBatchSize() {
54+
return attachmentFiles.size();
55+
}
56+
});
57+
}
58+
}
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
package es.princip.getp.batch.project.apply;
2+
3+
import es.princip.getp.domain.project.apply.model.IndividualProjectApplication;
4+
import es.princip.getp.domain.project.apply.model.ProjectApplication;
5+
import es.princip.getp.domain.project.apply.model.TeamProjectApplication;
6+
import lombok.RequiredArgsConstructor;
7+
import org.springframework.jdbc.core.BatchPreparedStatementSetter;
8+
import org.springframework.jdbc.core.JdbcTemplate;
9+
import org.springframework.stereotype.Service;
10+
11+
import java.sql.Date;
12+
import java.sql.PreparedStatement;
13+
import java.sql.SQLException;
14+
import java.util.List;
15+
16+
@Service
17+
@RequiredArgsConstructor
18+
class BatchInsertProjectApplicationJdbcService {
19+
20+
private final BatchInsertProjectApplicationAttachmentFileJdbcService attachmentFileJdbcService;
21+
private final BatchInsertTeamProjectApplicationJdbcService teamJdbcService;
22+
private final BatchInsertIndividualProjectApplicationJdbcService individualJdbcService;
23+
private final JdbcTemplate jdbcTemplate;
24+
private static final String sql =
25+
"""
26+
insert into project_application (
27+
project_application_id,
28+
expected_end_date,
29+
expected_start_date,
30+
description,
31+
status,
32+
people_id,
33+
project_id,
34+
dtype
35+
) values (?, ?, ?, ?, ?, ?, ?, ?);
36+
""";
37+
38+
public void batchUpdate(final List<ProjectApplication> applications) {
39+
jdbcTemplate.batchUpdate(sql, new BatchPreparedStatementSetter() {
40+
@Override
41+
public void setValues(final PreparedStatement ps, final int i) throws SQLException {
42+
final ProjectApplication application = applications.get(i);
43+
final String dtype = (application instanceof TeamProjectApplication) ?
44+
TeamProjectApplication.TYPE : IndividualProjectApplication.TYPE;
45+
ps.setLong(1, application.getId().getValue());
46+
ps.setDate(2, Date.valueOf(application.getExpectedDuration().getEndDate()));
47+
ps.setDate(3, Date.valueOf(application.getExpectedDuration().getStartDate()));
48+
ps.setString(4, application.getDescription());
49+
ps.setString(5, application.getStatus().toString());
50+
ps.setLong(6, application.getApplicantId().getValue());
51+
ps.setLong(7, application.getProjectId().getValue());
52+
ps.setString(8,dtype);
53+
}
54+
55+
@Override
56+
public int getBatchSize() {
57+
return applications.size();
58+
}
59+
});
60+
61+
attachmentFileJdbcService.batchUpdate(applications);
62+
individualJdbcService.batchUpdate(applications);
63+
teamJdbcService.batchUpdate(applications);
64+
}
65+
}
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
package es.princip.getp.batch.project.apply;
2+
3+
import es.princip.getp.batch.UniqueLongGenerator;
4+
import es.princip.getp.batch.config.ExtendsWithExecutionTimer;
5+
import es.princip.getp.batch.parallel.ParallelBatchInsertService;
6+
import es.princip.getp.domain.people.model.PeopleId;
7+
import es.princip.getp.domain.project.apply.model.*;
8+
import es.princip.getp.domain.project.commission.model.ProjectId;
9+
import lombok.RequiredArgsConstructor;
10+
import lombok.extern.slf4j.Slf4j;
11+
import org.springframework.stereotype.Service;
12+
13+
import java.util.ArrayList;
14+
import java.util.List;
15+
import java.util.Set;
16+
17+
import static es.princip.getp.fixture.project.ProjectApplicationFixture.*;
18+
19+
@Slf4j
20+
@Service
21+
@RequiredArgsConstructor
22+
public class BatchInsertProjectApplicationService {
23+
24+
private final BatchInsertProjectApplicationJdbcService jdbcService;
25+
private final ParallelBatchInsertService batchInsertService;
26+
27+
@ExtendsWithExecutionTimer
28+
public void insert(final int projectSize) {
29+
batchInsertService.insert(projectSize, (start, end) -> {
30+
final List<ProjectApplication> applications = new ArrayList<>();
31+
for (int i = start; i <= end; i++) {
32+
final ProjectId projectId = new ProjectId((long) i);
33+
applications.add(individualProjectApplication(
34+
new ProjectApplicationId(UniqueLongGenerator.generateUniqueLong()),
35+
new PeopleId(1L),
36+
projectId
37+
));
38+
applications.add(teamProjectApplication(
39+
new ProjectApplicationId(UniqueLongGenerator.generateUniqueLong()),
40+
new PeopleId(2L),
41+
projectId,
42+
ProjectApplicationStatus.COMPLETED,
43+
Set.of(
44+
teammate(
45+
new TeammateId(UniqueLongGenerator.generateUniqueLong()),
46+
new PeopleId(3L),
47+
TeammateStatus.APPROVED
48+
),
49+
teammate(
50+
new TeammateId(UniqueLongGenerator.generateUniqueLong()),
51+
new PeopleId(4L),
52+
TeammateStatus.APPROVED
53+
),
54+
teammate(
55+
new TeammateId(UniqueLongGenerator.generateUniqueLong()),
56+
new PeopleId(5L),
57+
TeammateStatus.APPROVED
58+
)
59+
)
60+
));
61+
}
62+
jdbcService.batchUpdate(applications);
63+
});
64+
}
65+
}
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
package es.princip.getp.batch.project.apply;
2+
3+
import es.princip.getp.domain.project.apply.model.ProjectApplication;
4+
import es.princip.getp.domain.project.apply.model.TeamProjectApplication;
5+
import lombok.RequiredArgsConstructor;
6+
import org.springframework.jdbc.core.BatchPreparedStatementSetter;
7+
import org.springframework.jdbc.core.JdbcTemplate;
8+
import org.springframework.stereotype.Service;
9+
10+
import java.sql.PreparedStatement;
11+
import java.sql.SQLException;
12+
import java.util.List;
13+
14+
@Service
15+
@RequiredArgsConstructor
16+
class BatchInsertTeamProjectApplicationJdbcService {
17+
18+
private final BatchInsertTeamProjectApplicationTeammateJdbcService teammateJdbcService;
19+
private final JdbcTemplate jdbcTemplate;
20+
private static final String sql =
21+
"""
22+
insert into team_project_application (
23+
project_application_id
24+
) values (?);
25+
""";
26+
27+
public void batchUpdate(final List<ProjectApplication> applications) {
28+
final List<TeamProjectApplication> teams = applications.stream()
29+
.filter(TeamProjectApplication.class::isInstance)
30+
.map(TeamProjectApplication.class::cast)
31+
.toList();
32+
33+
jdbcTemplate.batchUpdate(sql, new BatchPreparedStatementSetter() {
34+
@Override
35+
public void setValues(final PreparedStatement ps, final int i) throws SQLException {
36+
final TeamProjectApplication application = teams.get(i);
37+
ps.setLong(1, application.getId().getValue());
38+
}
39+
40+
@Override
41+
public int getBatchSize() {
42+
return teams.size();
43+
}
44+
});
45+
46+
teammateJdbcService.batchUpdate(teams);
47+
}
48+
}

0 commit comments

Comments
 (0)