Spring-DataにDAOを実装しています:
public interface TestDataRepository extends CrudRepository<DpConfigData, Long> {
@Query(value = "select distinct(oid) from unit", nativeQuery = true)
List<Long> testMethod();
}
そして、言及されたDAOをテストするためのユニットテスト:
@Test
public void test(){
List<Long> testData = dpConfigDataEntityDataRepository.testMethod();
for (Long oid:testData){
System.out.print(oid);
}
}
テストを実行すると奇妙な結果が得られます-List<Long> testData
実行時に、LongではなくBigIntegerインスタンスが入力されます。その結果、次のようになりますClassCastException:Java.math.BigIntegerをJava.lang.Longにキャストできません
JPAの実装-休止状態。 DBとして私はPostgreSQLを使用しています、unit.oid
フィールドはDBレイヤーでBigIntタイプです。ユニット全体をフェッチする場合はLongにマップされますが、「selectdistinct ...」としてカスタムクエリを使用すると、問題が発生し、BigIntegerにマップされます。
だから、私の質問:そのような奇妙な行動の原因は何ですか?エレガントな方法でそれを解決/回避する方法は?
最後に、「サービス」レイヤーに手動でマッピングすることで、この問題を回避しました。例(擬似コード):
public interface TestDataRepository extends CrudRepository<DpConfigData, Long> {
@Query(value = "select distinct(oid) from unit", nativeQuery = true)
List<Object> testMethod();
}
}
次に、サービスレイヤーで手動マッピングを行います。
public class TestServiceImpl extends TestService {
pulic List<Object> testMethod(){
List<Object> rawList = testDataRepository.testMethod();
List<Object> resultList = new ArrayList(rawList.size());
for(Object rw:rawList){
resultList.add(Long.valueOf(String.valueOf(rw)));
}
return resultList;
}
}
これはSpringデータJPAの問題です。 DBでデータ型がBigIntegerとして定義されており、JPAクエリでLongとしてフェッチしようとすると、エラーは発生しませんが、Longデータ型ではBigIntegerとして値が設定されます。
解決策:
BigIntegerを戻り値の型として使用します
@Query(value = "select distinct(oid) from unit", nativeQuery = true) List<BigInteger> testMethod();
次に、変数を次のように設定します。Long variable = bigIntegerValue.longValue();
Stringを戻り値の型として使用し、Longに変換します
@Query(value = "select distinct(oid) from unit", nativeQuery = true) List<String> testMethod();
次に、値を次のように設定します
Long variable = Long.valueOf(stringValue);
DB列タイプを変更を整数/数値に変更します。
エンティティオブジェクトから値を取得します。
Long variable = dpConfigData.getOid();
ここで、dpConfigData
はEntity(DpConfigData.class)のオブジェクトです。
PostgresqlのBigIntは、署名されていないため、BigIntegerにマップされます
JPAオブジェクトでoidをLongからBigIntegerに変更するのが最善の選択肢だと思います
以下のようにJPQLを使用してこれを試すことができます。
public interface TestDataRepository extends
JpaRepository<DpConfigData, Long> {
@Query(value = "select distinct(u.oid) from unit u")
List<Long> testMethod();
}
エンティティオブジェクトも、指定された属性に対して同じデータ型Longを持っている必要があることを確認してください。