Spring Data JPA のクエリメソッド名を使用した検索を行うと、検索結果が0件になる
チュートリアルを基に、Springを学習中です。
チュートリアルではPostgreSQLを使用していましたが、手持ちの環境の都合上、Oracle 18c XEを使用しました。
「メソッド名からクエリを生成する方法」の所で、意図した検索結果にならず、つまづいています。
具体的には、生成されたクエリを実行すると、SQL Plusだと検索されますが、プログラムからは検索結果が0件になってしまいます。
発生している問題・エラーメッセージ
ログから、以下のクエリが生成されていることを確認しました。
バインドされた値も確認しました。
log
12022-01-07 10:50:52.422 DEBUG 16596 --- [nio-8080-exec-1] org.hibernate.SQL : 2 select 3 reservable0_.reserved_date as reserved_date1_1_, 4 reservable0_.room_id as room_id2_1_ 5 from 6 reservable_room reservable0_ 7 where 8 reservable0_.reserved_date=? 9 order by 10 reservable0_.room_id asc 11Hibernate: 12 select 13 reservable0_.reserved_date as reserved_date1_1_, 14 reservable0_.room_id as room_id2_1_ 15 from 16 reservable_room reservable0_ 17 where 18 reservable0_.reserved_date=? 19 order by 20 reservable0_.room_id asc 212022-01-07 10:50:52.423 TRACE 16596 --- [nio-8080-exec-1] o.h.type.descriptor.sql.BasicBinder : binding parameter [1] as [VARCHAR] - [2022-01-07]
SQL Plusの実行結果は以下の通りです(一部省略)。
sql
1SQL> select 2 2 reservable0_.reserved_date as reserved_date1_1_, 3 3 reservable0_.room_id as room_id2_1_ 4 4 from 5 5 reservable_room reservable0_ 6 6 where 7 7 reservable0_.reserved_date='2022-01-07' 8 8 order by 9 9 reservable0_.room_id asc; 10 11RESERVED_DATE1_1_ 12-------------------- 13ROOM_ID2_1_ 14----------- 152022-01-07 16 1 17 182022-01-07 19 2 20 212022-01-07 22 3 23(以降省略) 24 257行が選択されました。
これが、プログラムの実行結果を確認すると、検索結果が0件になります。
該当のソースコード
検索の実行個所は以下の通りです(一部抜粋)。
java
1 @RequestMapping(method = RequestMethod.GET) 2 String listRooms(Model model) { 3 String date = LocalDate.now().toString(); 4 5 List<ReservableRoom> rooms = roomService.findReservableRooms(date); 6 // デバッグ用 7 System.out.println("rooms count:" + rooms.size()); //ここが0件になる 8 9 model.addAttribute("date", date); 10 model.addAttribute("rooms", rooms); 11 return "room/listRooms"; 12 }
検索メソッドのソースは以下の通りです(エンティティのゲッター/セッターは省略しています)。
java
1@Service 2@Transactional 3public class RoomService { 4 5 @Autowired 6 ReservableRoomRepository reservableRoomRepository; 7 8 public List<ReservableRoom> findReservableRooms(String date) { 9 return reservableRoomRepository.findByReservableRoomId_reservedDateOrderByReservableRoomId_roomIdAsc(date); 10 } 11}
java
1public interface ReservableRoomRepository extends JpaRepository<ReservableRoom, ReservableRoomId> { 2 List<ReservableRoom> findByReservableRoomId_reservedDateOrderByReservableRoomId_roomIdAsc(String reservedDate); 3}
java
1@Entity 2public class ReservableRoom implements Serializable { 3 @EmbeddedId 4 private ReservableRoomId reservableRoomId; 5 6 @ManyToOne 7 @JoinColumn(name = "room_id", insertable = false, updatable = false) 8 @MapsId("roomId") 9 private MeetingRoom meetingRoom; 10 11 public ReservableRoom(ReservableRoomId reservableRoomId) { 12 this.reservableRoomId = reservableRoomId; 13 } 14 15 public ReservableRoom() { 16 } 17 //getter/setterは省略 18}
java
1@Embeddable 2public class ReservableRoomId implements Serializable { 3 private Integer roomId; 4 private String reservedDate; 5 6 public ReservableRoomId(Integer roomId, String reservedDate) { 7 this.roomId = roomId; 8 this.reservedDate = reservedDate; 9 } 10 11 public ReservableRoomId() { 12 } 13 14 @Override 15 public int hashCode() { 16 final int prime = 31; 17 int result = 1; 18 result = prime * result + ((reservedDate == null) ? 0 : reservedDate.hashCode()); 19 result = prime * result + ((roomId == null) ? 0 : roomId.hashCode()); 20 return result; 21 } 22 23 @Override 24 public boolean equals(Object obj) { 25 if(this == obj) return true; 26 if(obj == null) return false; 27 if(getClass() != obj.getClass()) return false; 28 ReservableRoomId other = (ReservableRoomId) obj; 29 if(reservedDate == null) { 30 if(other.reservedDate != null) return false; 31 }else if(!reservedDate.equals(other.reservedDate)) 32 return false; 33 if(roomId == null) { 34 if(other.roomId != null) return false; 35 }else if(!roomId.equals(other.roomId)) 36 return false; 37 return true; 38 } 39 //getter/setterは省略 40}
試したこと
- ログの確認
- SQL Plusでの動作検証
- デバッグ出力の追加
- PostgreSQLとOracleの非互換調査
- チュートリアルとのソースの突合せ
- Spring Data JPA リファレンスの確認
- Googleで類似事例の確認
補足情報(FW/ツールのバージョンなど)
- Spring Boot 2.6.2
- Java 11
- Oracle 18c XE
2022/01/10追記
「SQL Plusとプログラムで、見ているデータベースが異なるのではないか」とのご指摘をいただきました。
同じデータベースを参照している認識です。
以下に、SQL Plusのログインとapplication.propertiesを掲載します。
sql
1connect xxxx/xxxx@//localhost:1521/XEPDB1
properties
1spring.datasource.driver-class-name=oracle.jdbc.driver.OracleDriver 2spring.datasource.url=jdbc:oracle:thin:@//localhost:1521/XEPDB1 3spring.datasource.username=xxxx 4spring.datasource.password=xxxx 5spring.jpa.database-platform=org.hibernate.dialect.Oracle10gDialect 6spring.jpa.show-sql=true 7spring.jpa.hibernate.ddl-auto=validate 8spring.jpa.properties.hibernate.format_sql=true 9spring.sql.init.encoding=UTF-8 10logging.level.org.hibernate.SQL=DEBUG 11logging.level.org.hibernate.type.descriptor.sql.BasicBinder=TRACE
2022/01/13追記
application.propertiesに以下を追記し、schema.sqlとdata.sqlからデータベースを作成してみたところ、正常に動作しました。
properties
1spring.sql.init.mode=always 2spring.sql.init.schema-locations=classpath:schema.sql
「SQL Plusとプログラムで、見ているデータベースが異なるのではないか」とのご指摘の通りのようですが、理屈があまり理解できていません。
SQL Plusのconnectの書式か、spring.datasource.urlの書式のどちらかが誤っているのでしょうか?
2022/01/16追記
SQL PlusでテーブルをDROPして、アプリ側で「テーブル無し」のエラーとなることを確認しました。
SQL Plusでテーブルを作成する際に、わざとカラム属性を誤った属性にしたところ、エンティティの生成でエラーとなることを確認しました。
以上のことから、SQL Plusとプログラムで見ているデータベースは同じであると考えられます。
しかし、レコードのINSERTだけ、SQL Plusとプログラムで振る舞いが異なることを確認しています。
回答2件
あなたの回答
tips
プレビュー