Closed9

Spring Batch 開発メモ

ピン留めされたアイテム
Ryo IshizawaRyo Ishizawa

Spring Batchでバッチを書いていて、躓いた点などをメモしています。

Ryo IshizawaRyo Ishizawa

エラー

ライブラリのDependencyで NoSuchBeanDefinitionException エラーが発生する。

org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'scopedTarget.sampleReader': Unsatisfied dependency expressed through field 'sampleRepository'; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'com.example.library.sampleRepository' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}

解決策

@ComponentScan で読み込む

@SpringBootApplication
@ComponentScan({"com.example.library"})
public class SampleApplication {

	public static void main(String[] args) {
		SpringApplication.run(SampleApplication.class, args);
	}

}

他にもいくつかBeanを読み込む方法がある。上記の方法は、パッケージを一括で取り込む方法。

Ryo IshizawaRyo Ishizawa

エラー

BATCH_JOB_INSTANCE テーブルが存在しないのが原因でエラーになる

Caused by: org.springframework.jdbc.BadSqlGrammarException: PreparedStatementCallback; bad SQL grammar [SELECT JOB_INSTANCE_ID, JOB_NAME from BATCH_JOB_INSTANCE where JOB_NAME = ? and JOB_KEY = ?]; nested exception is java.sql.SQLSyntaxErrorException: (conn=266415) Table 'main.BATCH_JOB_INSTANCE' doesn't exist
	at org.springframework.jdbc.support.SQLErrorCodeSQLExceptionTranslator.doTranslate(SQLErrorCodeSQLExceptionTranslator.java:239) ~[spring-jdbc-5.3.18.jar:5.3.18]
	at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:70) ~[spring-jdbc-5.3.18.jar:5.3.18]
	at org.springframework.jdbc.core.JdbcTemplate.translateException(JdbcTemplate.java:1541) ~[spring-jdbc-5.3.18.jar:5.3.18]
...

解決策

  1. 接続しているデータベースにSchemaを追加する
    • Dependencyの中からorg.springframework.batch:spring-batch-core:4.x.xを探す
    • -> spring-batch-core-4.x.x.jar > org.springframework.batch.core > 中にschema定義のSQLがある(例:schema-mysql.sql)。これをデータベース上で実行させれば良い。
  2. spring.batch.jdbc.initialize-schema = ALWAYS を使う(動作未確認)

https://stackoverflow.com/questions/49443551/i-am-getting-error-table-test-batch-job-instance-doesnt-exist

Ryo IshizawaRyo Ishizawa

エラー

Spring BatchでJPAを利用していて、CannotCreateTransactionExceptionが発生する

org.springframework.transaction.CannotCreateTransactionException: Could not open JPA EntityManager for transaction; nested exception is java.lang.IllegalStateException: Already value [org.springframework.jdbc.datasource.ConnectionHolder@2ef63b6d] for key [HikariDataSource (HikariPool-1)] bound to thread
	at org.springframework.orm.jpa.JpaTransactionManager.doBegin(JpaTransactionManager.java:467) ~[spring-orm-5.3.18.jar:5.3.18]
	at org.springframework.transaction.support.AbstractPlatformTransactionManager.startTransaction(AbstractPlatformTransactionManager.java:400) ~[spring-tx-5.3.18.jar:5.3.18]
	at org.springframework.transaction.support.AbstractPlatformTransactionManager.getTransaction(AbstractPlatformTransactionManager.java:373) ~[spring-tx-5.3.18.jar:5.3.18]
...

解決策

(プロジェクトの既存設定によって解決方法が結構違うかも)

  1. JpaTransactionManagerのBeanを@Configurationが付いているConfigクラスに追加する
    @Bean
    public JpaTransactionManager jpaTransactionManager() {
        return new JpaTransactionManager();
    }
  1. (Chunkを利用する場合)Step の中にtransactionManagerを入れる
    @Bean
    public Step chunkStep() {
        return stepBuilderFactory.get("ChunkStep")
                .<String, String>chunk(CHUNK_COUNT)
                .reader(itemReader)
                .processor(itemProcessor)
                .writer(itemWriter)
                .transactionManager(jpaTransactionManager())
                .build();
    }

その他の解決方法:

https://stackoverflow.com/questions/50173477/spring-boot-jpa-batch-cannotcreatetransactionexception

Ryo IshizawaRyo Ishizawa

JPQL関連エラー

(Spring Batchには関連無いが…)

コード

    @Query("SELECT date, sum(amount) FROM my_table GROUP BY date")
    List<PartnerDaily> getPartnerSummary(LocalDate date);

エラー内容

...
Caused by: org.hibernate.hql.internal.ast.QuerySyntaxException: my_table is not mapped
	at org.hibernate.hql.internal.ast.util.SessionFactoryHelper.requireClassPersister(SessionFactoryHelper.java:170)
	at org.hibernate.hql.internal.ast.tree.FromElementFactory.addFromElement(FromElementFactory.java:91)
...

対応方法

  • 自分の場合はテーブルの指定方法が間違えていた。my_tableというテーブルだと、JPQLではMyTableと書く必要があった。

https://stackoverflow.com/questions/23018836/org-hibernate-hql-internal-ast-querysyntaxexception-table-is-not-mapped

Ryo IshizawaRyo Ishizawa

JPQL関連エラー その2

コード

Repository.java
    // 本当は複雑なクエリを書く予定だが、デバッグのために単純化
    @Query("SELECT path.to.package.Data(amount) FROM my_table")
    List<PartnerDaily> getData(LocalDate date);
path.to.package.Data.java
@Getter
@Setter
public class Data {
    private Integer amount;
}

エラー内容

  • 長いエラーだったが、最後に以下のようなエラーがある
.....()
Caused by: org.hibernate.QueryException: No data type for node: org.hibernate.hql.internal.ast.tree.MethodNode 
 \-[METHOD_CALL] MethodNode: '('
    +-[METHOD_NAME] IdentNode: 'path.to.package.Data' {originalText=path.to.package.MyTable}
    \-[EXPR_LIST] SqlNode: 'exprList'
       \-[DOT] DotNode:
.....()

解消方法

  • newがJPQL内から抜けていた。以下のコードに修正する。
Repository.java
    // 本当は複雑なクエリを書く予定だが、デバッグのために単純化
    @Query("SELECT new path.to.package.Data(amount) FROM my_table")
    List<PartnerDaily> getData(LocalDate date);
  • しかし、さらにエラーが発生する。
.....()
Caused by: org.hibernate.hql.internal.ast.QuerySyntaxException: Unable to locate appropriate constructor on class [.....()
  • Dataクラスにコンストラクターが不足しており、追加する必要があった
    • Lombokを利用している場合は@AllArgsConstructorを追加すれば良い。

参考

  • この記事を最初からきちんと読んでいれば、上記のエラーにハマる必要は無かった。。

https://stackoverflow.com/questions/36328063/how-to-return-a-custom-object-from-a-spring-data-jpa-group-by-query

このスクラップは2023/02/02にクローズされました