묻고 답해요
130만명의 커뮤니티!! 함께 토론해봐요.
인프런 TOP Writers
-
해결됨[스프링 배치 입문] 예제로 배우는 핵심 Spring Batch
다중DB 접속 설정 에러
안녕하세요!강의 잘 봤습니다!강의 보고 다중DB를 설정하는과정에서 에러가나서 질문드려요여기서 하면 안되는거같은데 ... 도움부탁드릴려고 글 남깁니다!targetDb에서 select는 정상적으로 들어오는데 localDB save 할때 할당 문제인거 같은데 ...에로코드org.springframework.transaction.CannotCreateTransactionException: Could not open JPA EntityManager for transaction; nested exception is java.lang.IllegalStateException: Already value [org.springframework.jdbc.datasource.ConnectionHolder@4ff98dfc] for key [HikariDataSource (HikariPool-1)] bound to thread [scheduling-1] at org.springframework.orm.jpa.JpaTransactionManager.doBegin(JpaTransactionManager.java:467) ~[spring-orm-5.3.6.jar:5.3.6] at org.springframework.transaction.support.AbstractPlatformTransactionManager.startTransaction(AbstractPlatformTransactionManager.java:400) ~[spring-tx-5.3.6.jar:5.3.6] at org.springframework.transaction.support.AbstractPlatformTransactionManager.getTransaction(AbstractPlatformTransactionManager.java:373) ~[spring-tx-5.3.6.jar:5.3.6] at org.springframework.transaction.interceptor.TransactionAspectSupport.createTransactionIfNecessary(TransactionAspectSupport.java:595) ~[spring-tx-5.3.6.jar:5.3.6] at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:382) ~[spring-tx-5.3.6.jar:5.3.6] ------ at org.springframework.scheduling.support.ScheduledMethodRunnable.run(ScheduledMethodRunnable.java:84) [spring-context-5.3.6.jar:5.3.6] at org.springframework.scheduling.support.DelegatingErrorHandlingRunnable.run(DelegatingErrorHandlingRunnable.java:54) [spring-context-5.3.6.jar:5.3.6] at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511) [na:1.8.0_181] at java.util.concurrent.FutureTask.runAndReset$$$capture(FutureTask.java:308) [na:1.8.0_181] at java.util.concurrent.FutureTask.runAndReset(FutureTask.java) [na:1.8.0_181] at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$301(ScheduledThreadPoolExecutor.java:180) [na:1.8.0_181] at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:294) [na:1.8.0_181] at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) [na:1.8.0_181] at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) [na:1.8.0_181] at java.lang.Thread.run(Thread.java:748) [na:1.8.0_181] Caused by: java.lang.IllegalStateException: Already value [org.springframework.jdbc.datasource.ConnectionHolder@4ff98dfc] for key [HikariDataSource (HikariPool-1)] bound to thread [scheduling-1] at org.springframework.transaction.support.TransactionSynchronizationManager.bindResource(TransactionSynchronizationManager.java:193) ~[spring-tx-5.3.6.jar:5.3.6] at org.springframework.orm.jpa.JpaTransactionManager.doBegin(JpaTransactionManager.java:442) ~[spring-orm-5.3.6.jar:5.3.6] ... 93 common frames omitted 2024-02-26 12:16:27.150 INFO 23616 --- [ scheduling-1] o.s.batch.core.step.AbstractStep : Step: [step] executed in 737ms 2024-02-26 12:16:27.160 INFO 23616 --- [ scheduling-1] c.m.mj_agent.listener.JobLoggerListener : taragetJob Job is Done. (Status: FAILED) 2024-02-26 12:16:27.160 INFO 23616 --- [ scheduling-1] c.m.mj_agent.listener.JobLoggerListener : Job is Failed 2024-02-26 12:16:27.168 INFO 23616 --- [ scheduling-1] o.s.b.c.l.support.SimpleJobLauncher : Job: [SimpleJob: [name=taragetJob]] completed with the following parameters: [{time=1708917386263}] and the following status: [FAILED] in 797ms localDbConfigpackage com.munjaon.mj_agent.config; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.boot.jdbc.DataSourceBuilder; import org.springframework.boot.orm.jpa.EntityManagerFactoryBuilder; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Primary; import org.springframework.context.annotation.PropertySource; import org.springframework.core.env.Environment; import org.springframework.data.jpa.repository.config.EnableJpaRepositories; import org.springframework.orm.jpa.JpaTransactionManager; import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean; import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter; import org.springframework.transaction.PlatformTransactionManager; import javax.sql.DataSource; import java.util.HashMap; /** * */ @Configuration @PropertySource({ "classpath:application.yml" }) @EnableJpaRepositories( // basePackages = {"com.repia.collectweb.common", "com.repia.collectweb.schedule"}, // basePackages = {"com.munjaon.mj_agent.batch.local.repo"}, basePackages = {"com.munjaon.mj_agent.batch.local"}, entityManagerFactoryRef = "primaryEntityManager", transactionManagerRef = "primaryTransactionManager" ) public class LocalDbConfig { @Autowired private Environment env; @Bean @Primary @ConfigurationProperties(prefix = "spring.local-datasource.datasource.hikari") public DataSource primaryDataSource() { return DataSourceBuilder.create().build(); } @Bean @Primary public LocalContainerEntityManagerFactoryBean primaryEntityManager() { LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean(); em.setDataSource(primaryDataSource()); em.setPackagesToScan(new String[] { "com.munjaon.mj_agent.batch.local.repo.entity" }); HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter(); em.setJpaVendorAdapter(vendorAdapter); HashMap<String, Object> properties = new HashMap<>(); properties.put("hibernate.show_sql", env.getProperty("spring.jpa.show_sql")); properties.put("hibernate.format_sql", env.getProperty("spring.jpa.format_sql")); properties.put("hibernate.use_sql_comments", env.getProperty("spring.jpa.use_sql_comments")); properties.put("hibernate.hbm2ddl.auto", env.getProperty("spring.jpa.hibernate.hbm2ddl.auto")); properties.put("hibernate.dialect", env.getProperty("spring.jpa.database-platform")); // properties.put("hibernate.dialect", env.getProperty("spring.jpa.database")); em.setJpaPropertyMap(properties); return em; } @Bean @Primary public PlatformTransactionManager primaryTransactionManager() { JpaTransactionManager transactionManager = new JpaTransactionManager(); transactionManager.setEntityManagerFactory(primaryEntityManager().getObject()); return transactionManager; } }TargetDbConfigpackage com.munjaon.mj_agent.config; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.boot.jdbc.DataSourceBuilder; import org.springframework.boot.orm.jpa.EntityManagerFactoryBuilder; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.PropertySource; import org.springframework.core.env.Environment; import org.springframework.data.jpa.repository.config.EnableJpaRepositories; import org.springframework.orm.jpa.JpaTransactionManager; import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean; import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter; import org.springframework.transaction.PlatformTransactionManager; import org.springframework.transaction.annotation.EnableTransactionManagement; import javax.sql.DataSource; import java.util.HashMap; import java.util.Objects; /** * */ @Configuration @PropertySource({ "classpath:application.yml" }) @EnableTransactionManagement @EnableJpaRepositories( basePackages = {"com.munjaon.mj_agent.batch.target.repo"} , entityManagerFactoryRef = "targetDbEntityManager" , transactionManagerRef = "targetDbTransactionManager" ) public class TargetDbConfig { @Autowired private Environment env; @Bean // @Primary public LocalContainerEntityManagerFactoryBean targetDbEntityManager() { LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean(); em.setDataSource(targetDbDataSource()); em.setPackagesToScan(new String[] { "com.munjaon.mj_agent.batch.target.repo.entity" }); HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter(); em.setJpaVendorAdapter(vendorAdapter); HashMap<String, Object> properties = new HashMap<>(); properties.put("hibernate.show_sql", env.getProperty("spring.jpa.show_sql")); properties.put("hibernate.format_sql", env.getProperty("spring.jpa.format_sql")); properties.put("hibernate.use_sql_comments", env.getProperty("spring.jpa.use_sql_comments")); // properties.put("hibernate.hbm2ddl.auto", false); // properties.put("hibernate.dialect", false); properties.put("hibernate.hbm2ddl.auto", env.getProperty("spring.jpa.hibernate.hbm2ddl.auto")); properties.put("hibernate.dialect", env.getProperty("spring.jpa.database-platform")); em.setJpaPropertyMap(properties); return em; } @Bean // @Primary @ConfigurationProperties(prefix = "spring.target-datasource.datasource.hikari") public DataSource targetDbDataSource() { return DataSourceBuilder.create().build(); } // @Primary // @Bean @Bean(name = "targetDbTransactionManager") public PlatformTransactionManager targetDbTransactionManager(EntityManagerFactoryBuilder builder) { return new JpaTransactionManager(Objects.requireNonNull(targetDbEntityManager().getObject())); } } 감사합니다!
-
해결됨스프링 배치
분류가 필요한 상황이 있는데 방향에 대해 질문드립니다.
안녕하세요.구현하고자 하는 배치를 해보면서 강의를 부분부분 병행하며 듣고 있는데, 제가 원하는 배치는 어떻게 설계 해야 하는지 고민이 되어 조언을 얻고 싶어 질문드립니다.구현하려는 상황은 다음과 같습니다. db 컬럼 중 플래그 값이 있고 그걸로 reader 에서 readread 한 데이터들로 processor 에서 로직 진행 (로직 중간중간 db 조회나 업데이트하는 상황도 생김) writer 에서 write 해야 하는 테이블이 4개 인데 processor 로직 조건에 따라 어떤 경우는 2개, 어떤 경우는 4개 등 write 되는 테이블 개수가 달라짐마지막에 최종적으로 read 한 모든 데이터의 플래그 값을 업데이트 쳐서 다음 read 에서 조회되지 않게 함 처음 생각은 reader 와 processor 를 하나씩 만들고 writer 를 여러개 만드려고 했습니다.processor 에서 리턴되는 객체 하나로 여러 테이블에 write 해도 될만큼 필드가 겹치는게 많아서 이렇게 생각했습니다.그래서 찾아보니 writer 에도 composite 과 classifierComposite 구현체가 있더라구요.그런데 둘 다 사용해봤는데 제가 원하는 바를 실현시키지 못했습니다. 분류 후 여러개를 writer 해야 하는데 composite 는 분류가 안되고 classifierComposite 은 하나만 writer 되더라구요.그래서 writer 여러개로 설계하는게 안맞는 방법인가 싶어서요.같은 맥락으로 processor 여러개로 하는 방법도 뭔가 그림이 잘 안그려지고..결국 step 을 여러개 하는 방향을 생각 중인데 이때도 고민거리가 생깁니다.step 으로 했을 때는 같은 조건으로 테이블 개수만큼 read 를 여러번 하게 된다는 단점이 있는 것 같아서요.그리고 4번에서 read 하는 조건 플래그 값을 update 하는데 첫번째 스탭에서 해버리면 다음 스탭에서 read 를 못하게 되버립니다.그리고 2번 과정도 각 테이블마다 거의 똑같고 마지막에 조건에 따라 저장할 테이블만 분류하는 과정만 있는건데 그거를 스탭마다 중복되게 하는 것도 그렇습니다. 구현 상황을 보셨을 때 어떤 식으로 처리하는게 좋다고 생각하시는지 궁금합니다.
-
해결됨스프링 배치
setSortKeys 로 정한 값에서 오류가 나는데 원인을 모르겠습니다.
@Bean public JdbcPagingItemReader<RequestReportTargetDto> jdbcPagingItemReader() throws Exception { HashMap<String, Object> parameters = new HashMap<>(); parameters.put("reqReportYn", "N"); return new JdbcPagingItemReaderBuilder<RequestReportTargetDto>() .name("jdbcPagingItemReader") .dataSource(dataSource) .fetchSize(10) .rowMapper(new BeanPropertyRowMapper<>(RequestReportTargetDto.class)) .pageSize(10) .queryProvider(createQueryProvider()) .parameterValues(parameters) .build(); } @Bean public PagingQueryProvider createQueryProvider() throws Exception { SqlPagingQueryProviderFactoryBean qp = new SqlPagingQueryProviderFactoryBean(); qp.setDataSource(dataSource); qp.setSelectClause("M_ID mId, SERVICE_NO serviceNo, SERVICE_TYPE serviceType, PRODUCT_CODE productCode, REQ_REPORT_YN reqReportYn"); qp.setFromClause("from TARGET_TEST"); qp.setWhereClause("where reqReportYn = :reqReportYn"); Map<String, Order> sortKeys = new HashMap<>(); sortKeys.put("mId", Order.ASCENDING); qp.setSortKeys(sortKeys); return qp.getObject(); }@Getter @Setter public class RequestReportTargetDto { private String mId; private String serviceNo; private String serviceType; private String productCode; private String reqReportYn; }위와 같이 하고 실행하면 아래 오류가 납니다. org.springframework.dao.InvalidDataAccessApiUsageException: No value supplied for the SQL parameter '_mId': No value registered for key '_mId' at org.springframework.jdbc.core.namedparam.NamedParameterUtils.buildValueArray(NamedParameterUtils.java:379) ~[spring-jdbc-6.1.2.jar:6.1.2] at org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate.getPreparedStatementCreator(NamedParameterJdbcTemplate.java:472) ~[spring-jdbc-6.1.2.jar:6.1.2] at org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate.getPreparedStatementCreator(NamedParameterJdbcTemplate.java:446) ~[spring-jdbc-6.1.2.jar:6.1.2]..... sort key 로 정해준 값에서 계속 오류가 나는데 원인을 못찾고 있습니다. sort key 를 바꾸면 바꾸는데로 앞에 _ 가 붙어서 위와 같은 오류가 납니다. 강사님이 디버깅할 때 찍어주신 것처럼 where 절에 sort key 가 추가가 되는데 거기서 오류가 나는 것 같습니다.수정해봐야 하거나 더 확인할 수 있는 부분이 있을까요??
-
미해결스프링 배치
ChunkMonitor warning 확인
partition과 multiThread 를 이용한 테스트중 입니다.partition을 실행하는 단계에서chunkMonitor warning 이 계속 발생하는데 왜 발생하는지 이유를 잘 모르겠습니다.동작은 정상적으로 이루어지지만 문제가 있는 것은 아닌지 싶습니다.WARN [org.springframework.batch.core.step.item.ChunkMonitor] No ItemReader set (must be concurrent step), so ignoring offset data.그리고.. 쓰레드가 처음 실행할 때 아래의 warning 도 나오는데.. 왜 발생하는지 알 수 있을까여?ItemStream was opened in a different thread. Restart data could be compromised.조언 부탁드립니다.
-
미해결[스프링 배치 입문] 예제로 배우는 핵심 Spring Batch
조건별 분기 처리시 질문있습니다
.start(conditionalStartStep).on("FAILED").to(conditionalFailedStep).from(conditionalStartStep).on("COMPLETED").to(conditionalCompletedStep).from(conditionalStartStep).on("*").to(conditionalAllStep) 이때 오류 없이 성공하면 conditionalCompletedStep실패하게 되면 conditionalFailedStep 가게 되는데 마지막 줄의 "*" 표시는 어떨때 동작을 하게 만들 수 있을까요? 언뜻 보기에는 모든 상황에 대해서 발생하는거 처럼 보이는데 쉽사리 이해가 가지 않습니다
-
미해결스프링 배치
chunk에서 exception 처리 로직..
skipListener를 등록하여 테스트 중입니다.writer 에서 exception이 발생했는데 바로 skipListener로 넘어가지 않고 동일한 item에 대해 processor, writer를 한번 더 실행하고 skipListener로 넘어가는 현상을 발견했습니다.찾아보니 spring batch의 기본 동작 로직인 걸로 나오네요.보다 안정적인 수행을 위해 있는 기능 같은데 이렇게 재실행하지 않고 오류가 발생하면 바로(!!!) skipListener로 넘어가도록 할 수 있는 방법이 있을까요?
-
미해결스프링 배치
AsyncItemProcessor 트랜잭션 단위
- 학습 관련 질문을 남겨주세요. 상세히 작성하면 더 좋아요! - 먼저 유사한 질문이 있었는지 검색해보세요. - 서로 예의를 지키며 존중하는 문화를 만들어가요. - 잠깐! 인프런 서비스 운영 관련 문의는 1:1 문의하기를 이용해주세요. 선생님 안녕하세요!질문이 있습니다. 코드를 봐보니 AsyncItemProcessor를 사용할 때도 트랜잭션은 개별 아이템 단위가 아니라 Chunk 단위인 것 같은데 맞을까요?
-
미해결스프링 배치
잡 파라미터 관련 질문 있습니다.
안녕하세요. 잡파라미터 기본 설정 관련 질문이 있습니다.스프링 배치에서는 잡파라미터를 입력하지 않은 경우 이전 배치 실행 이력에서 (실행한 적이 있는 경우) 사용되었던 잡파라미터를 가져와 그값을 세팅해서 실행을 시키는대요.이렇게 처리하는 이유가 무엇인지 궁금합니다. 아무때나 그러는 건 아닌 것 같고 RunIdIncrementer 를 사용할 때만 이렇게 동작하는 것으로 보이는데 어떤 이유가 있을까요?
-
미해결스프링 배치
스프링 배치에서 트랜잭션 매니저 관련 질문이 있습니다.
안녕하세요 선생님. 질문이 있습니다.제가 알기로 배치에서는 청크 단위로 트랜잭션이 관리되는 것으로 알고 있습니다. 그렇다면 같은 트랜잭션 내에서는 같은 트랜잭션 매니저를 사용할 거라고 생각했는대요.한 step에서 txManagerA 라는 트랜잭션 매니저를 세팅 했는데 writer 로직에서 특정 repository 을 주입 받아 쿼리 수행을 했더니 txManagerB 라는 다른 트랜잭션 매니저를 사용하게 되어 의도와는 다르게 동작합니다. slave db 조회용 txManagerA, entityManagerFactoryA bean을 따로 만들었습니다. jpa 전체 설정은 @EnableJpaRepositories 어노테이션에 의해 마스터 DB용 txManagerB 로 등록되어있습니다.엔티티, 레파지토리 패키지 경로는 마스터, 슬레이브 둘 다 같습니다. 트랜잭션을 별도로 연것도 아닌데 (propagation=requires_new는 사용하지 않았습니다.) 어째서 부모 트랜잭션의 txManager 를 사용하지 않는건지 잘 이해가 되지 않습니다. 제가 뭔가 설정을 잘못한 걸까요? 아니면 스프링의 트랜잭션 정책일까요?
-
미해결스프링 배치
incrementer 관련 구현체 생성 시 질문
안녕하세요 강사님 강의 정말 잘 듣고 있습니다! 스프링부트에서 기본 제공하는 RunIdIncrementer에서 마지막 반환값 코드를 보면 return new JobParametersBuilder(params).addLong(this.key, id).toJobParameters(); 기존 paramers에 파라미터를 새롭게 add해주는 것으로 보이는데, 수업 10분쯤, 커스텀 클래스에서는 return new JobParametersBuilder().addString("run.id", id).toJobParameters();이렇게 JobParametersBuilder 안에 params를 넣어주지 않았는데 왜 잘 동작하는 지 궁금합니다! 제가 이해를 못 했거나, 빠트린 부분이 있을까요~?
-
미해결스프링 배치
spring batch 5
spring batch5에서 더이상 JobBuilderFactory와 StepBuilderFactory를 지원하지 않아 스프링 가이드를 참고해 JobBuilder와 StepBuilder로 해보고 있는데 아무래도 수업내용과는 코드차이가 있어 어려움이 있는데요, 혹시 spring batch5에 호환되는 버젼의 코드 업데이트 예정이 있으신지 여쭈어봅니다!
-
미해결스프링 배치
flowJob 의 next() 에 대해서 궁금한 부분이 있습니다.
주황색 박스의 next() 부분을@Bean public Job batchJob() { return this.jobBuilderFactory.get("batchJob") .start(step1()) .on("COMPLETED") .to(step2()) .on("*") .stop() .from(step1()).on("*") .to(step3()) .on("COMPLETED") .to(step4()) .on("FAILED") .end() .end() .build(); }이렇게 on("COMPLETED").to(step4()) 로 변경해도 동일하게 동작하는게 맞을까요?next() 로 결국 이전 작업이 성공해야 실행되는것으로 알고있어서요
-
미해결스프링 배치
ItemStream
안녕하세요, ItemStream 강의 부분 질문이 있어 글 남갑니다!CustomIteamStreamReader와 Writer는 Bean으로 생성하지 않아도 되는건가요?
-
미해결스프링 배치
동일한 Job파라미터으로 Job 실행
안녕하세요. 강의 잘 보고있습니다.다름이 아니고 동일한 Job파라미터로 실행했을때 전 강의에서 분명히 예외가 발생했던 것 같은데 어느순간부터 예외가 발생하지 않고 해당 데이터가 쌓입니다. 해당 테이블은 batch_job_execution 테이블입니다. 예외가 발생하게 할 순 없을까요?
-
미해결스프링 배치
JobRunner에 의존성 주입할 때 필드 주입을 사용하는 이유가 있을까요??
안녕하세요. 선생님.JobRunner 코드시에 필드 주입을 사용하는 것을 보고 질문을 드립니다.보통 다른 사람이 필드 주입을 사용하면 개인 스타일인가 하는 편인데요.Configuration 클래스 작성 시에는 롬복을 이용한 생성자 주입을 하셔서 혹시 차이를 두는 것에 특별한 이유가 있는지 궁금합니다.강의 잘 보고 있습니다. 감사합니다!
-
미해결스프링 배치
writer에서 다시 processor 호출 질문 드립니다.
질문 드립니다. processor의 return 형식이<A, B> 일 때 processor에서 A를 받아 B로 가공하여 return 하는데 이 때 B말고 다른 C도 함께 writer로 return이 가능한가요? step을 구성할 때 reader -> processor -> writer 순서인데 writer까지 진행된 이후 write 한 객체로 다시 processor 혹은 reader -> writer 등을 진행하고 싶을 땐 어떻게 해야 할까요? processor에서 조건을 사용하여 reader를 호출 하고 있는데 reader를 bean으로 생성하지 않고 reader.read(); 와 같은 방식으로 호출하는데 이 방식이 옳바른 방식인가요?
-
미해결스프링 배치
안녕하세요. 신규 강의 관련
해당 강의와 관련된 질문은 아니지만 동시성 관련 강의 오픈 메일에 링크가 이쪽으로 연결이 돼서요.11/21~28 오픈 예정이라고 하셨는데 혹시 오픈일정을 알 수 있을까요?
-
미해결스프링 배치
다음과 같은 부분에서 어떤 부분을 먼저 수강하는 게 좋을까요?
안녕하세요. 회사에서 저한테 매일 밤 12시에 20개 사이트에서 각각 1000 ~ 6000개의 데이터를 크롤링 후 해당 데이터 목록을 조회하는 웹 사이트 제작 업무를 맡겨서 진행중입니다. 업무를 시키실 때 스프링 배치를 활용해서 만들라고 하시고, 다른 곳에 출장가셔서 사무실에서 혼자 해당 업무를 완료해야하는 상황입니다ㅠㅠ. 다소 답답한 질문일 수도 있지만 다음과 같은 상황에서 제가 잘못 생각하고 있는 게 있는지, 또 이 상황을 해결하려면 어떤 부분의 강의를 들으면 되는지 여쭙고 싶습니다. 스프링 배치 개념이 익숙치 않기 때문에 스프링 MVC로 먼저 만들어봤습니다. 대신 Insert는 배치쪽에서 해야한다고 생각하여 service단에서 DB에 insert를 하는 dao 메소드를 실행시키지 않고 해당 데이터를 담은 List<VO>를 return 후 controller에서 DB insert하는 쪽으로 생각해봤습니다. 그대로 스프링 배치로 가져오려고 하니 step에서 service를 그냥 실행하고 List<VO>를 받아 DB insert를 하는 dao를 실행하면 되는지 아니면 service에 해당하던 내용을 ItemReader, processor, writer과 같이 스프링 배치에서 사용하는 클래스로 바꿔야 하는건지 잘 모르겠습니다. 또 20개의 서비스를 호출해야 하는데, 1개의 job에서 1개의 step에서 호출하는 게 좋을지, 1개의 job에서 20개의 step을 만드는 게 좋을지 각각 20개의 job을 만드는 게 좋을지 여쭤보고 싶습니다. 감사합니다
-
미해결스프링 배치
PagingQueryProvider에서 join 관련 질문 드립니다.
제 소스코드 공유 드립니다. 위 provider를 실행하면 select 절에 ot.tank_seq가 존재함에도 불구하고 order by 절에서 sortKeys로 설정한 ot.tank_seq를 인식하지 못하는 오류가 발생합니다.제가 검색해본 결과 join절을 사용해서 가져온 필드를 order by 하려면 alias를 붙여 사용하라고 하던데요. 그래서 위 코드처럼 alias를 붙여 실행하면 이와 같은 제가 설정한 적 없는 WHERE 절이 실행되게 되는데 혹시 왜 그럴까요?
-
미해결스프링 배치
Spring Batch Test 강의에서 clear()함수 질문드립니다.
Spring Batch Test 강의를 보면@Afterpublic void clear() 함수를 만들어서 insert한 데이터를 직접 삭제하는데 테스트코드에서 자동으로 트랜잭션 롤백이 안되는건가요?안된다면 할 수 있는 방법은 없나요?