0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

[java] Spinrg Boot JPAでクエリ文を使用する方法

Posted at

はじめに

Spring BootでJPAを用いたとき、違和感を感じるほど簡単に条件を絞ることができる。
例えば特定のidを持つdataをtableから取得するためには
クエリ文なら、select * from table where id = 1 と表記するが、
JPAで、findById(1)
などと表記する。
しかし、こういったわかりやすい表記を用いることで、かえってより細かい条件まで絞ることに限界が生じてしまう。
よってそれを解決するために、クエリ文を用いて条件を絞ることを少しまとめる。

Code

Entity

Entity.Account
@Entity
@Data
@Table(name = "accounts")
public class Account {
	
	@Id
	@GeneratedValue(strategy = GenerationType.IDENTITY)
	private Integer id;
	
	private  String name;
	
	@Column(name = "login_id")
	private String loginId;
	
	@Column(name = "login_pw")
	private String loginPw;
	
	@Column(name = "is_admin")
	private Boolean isAdmin = false;
	
}

Repositry

AccountRepository
public interface AccountRepository extends JpaRepository<Account, Integer>  {
	
	@Query("select a from Account a")
	List<Account> findByidQuery();
	
	@Query("select a from Account a where a.id = ?1")
	Account findByidQueryOne(Integer id);
	
	@Query("select a from Account a where a.isAdmin = false ")
	List<Account> findByidQueryNotAdmin();
}

注意しないといけないのは、クエリ文だからSQLと全く同じようなTable名、Column名を使用してはいけない。
SQLでのColumn名はis_adminであるが、JPAで利用するためにはEntityと同じ名前であるisAdminとして表記しなければいけない。

Controller

AccountController
@Controller
@RequestMapping("/account")
public class AccountController {

	@Autowired
	AccountRepository accountRepository;

	@GetMapping("/query")
	public String queryTest() {
		
        List<Account>  accounts = accountRepository.findByidQuery();
		Account  account = accountRepository.findByidQueryOne(1);
		List<Account>  accountsNotAdmin = accountRepository.findByidQueryNotAdmin();
		// Repositoryからクエリ文によるaccountを取得した

		return "account/index";
	}
}

その他

public interface ReadingRecordRepository extends JpaRepository<ReadingRecord, Integer> {

    @Query("select new com.example.demo.model.Recommend(rr.itemId, count(rr.itemId)) "
            + "from ReadingRecord rr "
            + "where  rr.itemRelatedId = ?1 "
            + "group by rr.itemId order by count(rr.itemId) desc "
            + "limit 5")
    List<Recommend> findRecommends(Integer itemRelatedId);
}

より複雑な組み合わせであると、上のように書くことができる。
閲覧記録(ReadingRecord)から関連アイテムの記録をカウントして、上位5つのRecommendを取得するようにした。
Entityにないような型だと、modelを作成してnew ~ model.Model(id, name)などとして型を指定しなければならない。

おわりに

少し特殊な形、例えばCountSumなどの集計的な内容があるとき、クエリ文を使用することがほぼ必須であると思われる。Modelを作成して型指定をすることも必要である。
個人的にはJPAをそのまま利用するよりも、クエリ文で書いたほうがよりしっくりくるのでより好んで利用すると思った。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?