No property {Column} found for type {Entity}エラーが出て、@Queryを使ってみた

<br>
以下のコードでは、Person EntityにPersonを保存して誕生日の月データが"8月"の人を検索しています。

```java:PersonRepositoryTest.java
    @Test
    void findByBirthdayBetween() {
        givenPerson("martin",10,"A",LocalDate.of(1991,8,15));
        givenPerson("david",9,"B",LocalDate.of(1992,7,1));
        givenPerson("dennis",8,"O",LocalDate.of(1993,1,5));
        givenPerson("sophia",7,"AB",LocalDate.of(1994,6,30));
        givenPerson("benny",6,"A",LocalDate.of(1995,8,30));

        List<Person> result = personRepository.findByMonthOfBirthday(8);

        result.forEach(System.out::println);
    }
```
Person Entityクラス、birthday Columnをオブジェクトとして保持したいので@Embedded annotationを定義しています。
```java:Person.java
package com.informanaging.project.demo.domain;

import com.informanaging.project.demo.domain.dto.Birthday;
import lombok.*;
import javax.persistence.*;
import java.time.LocalDate;

@Entity
@NoArgsConstructor
@AllArgsConstructor
@RequiredArgsConstructor
@Data
public class Person {
    //　省略
    @Embedded 
    private Birthday birthday;
    //　省略
}

```
Birthday DTO クラス、@Embeddable annotationが定義されています。(Person Entityのbirthdayと紐付け)
```java:Birthday.java
package com.informanaging.project.demo.domain.dto;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import javax.persistence.Embeddable;

@Embeddable // Entityに所属されている
@AllArgsConstructor
@NoArgsConstructor
@Data
public class Birthday {
    private int yearOfBirthday;
    private int monthOfBirthday;
    private int dayOfBirthday;
}
```

Repository クラスです。月データを受けて Personをselectします。
```java:PersonRepository.java
package com.informanaging.project.demo.repository;

import com.informanaging.project.demo.domain.Person;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import java.time.LocalDate;
import java.util.List;

// JpaRepository<Entity, Id>
public interface PersonRepository extends JpaRepository<Person, Long> {    
    List<Person> findByMonthOfBirthday(int monthOfBirthday);
}
```

それで、テストを実行すると以下のエラーが出てしまいます。
詳細を見ると、monthOfBirthdayはBirthdayクラスには定義されていますが、Person Entityには定義されていないためエラーが発生しています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3097775/6cd8ed26-3544-3b70-6bb9-5a104eba2ed1.png)

エラーを解消するために、Repository クラスにQuery annotationを定義してあげれば対応できます。
そうすると、Person EntityにmonthOfBirthday Columnを別途定義しなくていいです。
```java:修正後_PersonRepository.java
public interface PersonRepository extends JpaRepository<Person, Long> {
    @Query(value = "select person from Person person where person.birthday.monthOfBirthday =?1")
    List<Person> findByMonthOfBirthday(int monthOfBirthday);
}
```
Query annotaionを定義し、その中に実行したいSQLを作成します。作成するのはただのSQLではなくJPQLを作成しなければなりません。
<b>普通のSQLだとTableを指定しますが、JPQLはEntityを指定します。?1はパラメータのmonthOfBirthdayです。</b>
上記を見ると、Person Entityをfrom句に指定し、where句は「person Entityで定義しているbirthda dtoのmonthOfBirthdayをゲット！」ということで「person.birthday.monthOfBirthday」を指定します。

テストの結果も正常に検索されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3097775/67cd6043-a8dc-b51a-d221-ea3b222200f5.png)

JPQLでパラメータとして"?1"を使いたくない場合は、@Param("A")を定義し、"?1"代わりに"A"を使えばいいです。
```java:修正後_PersonRepository.java
public interface PersonRepository extends JpaRepository<Person, Long> {
    @Query(value = "select person from Person person where person.birthday.monthOfBirthday = :monthOfBirthday")
    List<Person> findByMonthOfBirthday(@Param("monthOfBirthday")int monthOfBirthday);
}
```