(Lock ์ ๋ํด์๋ ์ ๊ฐ ์์ง ๊ณต๋ถ๋ฅผ ์ ๋ชปํ์ฌ์, ์ดํ ์ ๋ฆฌํ๋๋ก ํ๊ฒ ์ต๋๋ค) Data JPA์์์ Lock ์ค์ @Lock์ ํตํด ๊ฐํธํ๊ฒ ์ค์ ํ ์ ์์ต๋๋ค. ์์ interface MemberRepository : JpaRepository { @Lock(LockModeType.PESSIMISTIC_WRITE) fun findByUsername(username: String): Member? } ์ง์ํ๋ Lock์ ์ข
๋ฅ ํด๋น LockModeType์ ํจํค์ง๋ฅผ ์ดํด๋ณด๋ฉด ๋ค์๊ณผ ๊ฐ์ต๋๋ค. ์ฆ Lock์ ์ค์ ํ๋ ๊ฒ์ JPA์ ํ์ค ์คํ์
๋๋ค. ๊ทธ๋ฌ๋ @Lock์ ํตํด ํด๋น ์ค์ ์ ํธํ๊ฒ ๋ง๋ค์ด ์ฃผ๋ ๊ฒ์ Data JPA์์ ์ ๊ณตํ๋ ๊ธฐ๋ฅ์
๋๋ค. Reference ์ค์ ! ์คํ๋ง ๋ฐ์ดํฐ JPA - ์ธํ..
๐๏ธ Spring
JPA Hint JPA ์ธํฐํ์ด์ค์ ๊ธฐ๋ฅ์ด ์๋ ์ด๋ ํ ๊ตฌํ์ฒด๊ฐ ์ถ๊ฐ์ ์ผ๋ก ์ ๊ณตํ๋ ๊ธฐ๋ฅ์ ์ฌ์ฉํ๊ณ ์ถ์ ๊ฒฝ์ฐ์ ์ฌ์ฉํฉ๋๋ค. ์ด๋ฒ ์์๋ JPA์ ๊ตฌํ์ฒด์ธ ํ์ด๋ฒ๋ค์ดํธ์ ๊ธฐ๋ฅ์ ํตํด ์ฝ๊ธฐ ์ ์ฉ ์ฟผ๋ฆฌ๋ฅผ ๋ง๋ค์ด๋ณด๋๋ก ํ๊ฒ ์ต๋๋ค. ์กฐํํ์ฌ ๊ฐ์ ๋ณ๊ฒฝํ ์ ์๋ ์ฝ๊ธฐ ์ ์ฉ ์ฟผ๋ฆฌ ๋ง๋ค๊ธฐ public interface MemberRepository extends JpaRepository { @QueryHints ( value=@QueryHint(name = "org.hibernate.readOnly", value = "true") ) Member findReadOnlyByUsername(String username); } Reference ์ค์ ! ์คํ๋ง ๋ฐ์ดํฐ JPA - ์ธํ๋ฐ | ๊ฐ์ ์คํ๋ง ๋ฐ์ดํฐ JPA๋ ๊ธฐ์กด..
@EntityGraph JPQL์ ํ์น ์กฐ์ธ์ ์กฐ๊ธ ๋ ํธํ๊ฒ ์ธ ์ ์๊ฒ DATA JPA์์ ์ ๊ณตํด์ฃผ๋ ๊ธฐ๋ฅ์
๋๋ค. @EntityGraph(attributePaths = {"ํ์น์กฐ์ธํ ์ํฐํฐ ํ๋๋ช
1", "ํ๋๋ช
2", ...}) ์์ @Entity @Getter @Table(name = "member") class Member { @Id @Column(name = "member_id") @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; private String username; @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "team_id") private Team team;..
๋ฒํฌ ์ฐ์ฐ ํ๋์ ๋ฐ์ดํฐ๊ฐ ์๋ ์ฌ๋ฌ ๋ฐ์ดํฐ๋ฅผ ํ๋ฒ์ ์์ ํ๊ฑฐ๋ ์ญ์ ํ๋ ์ฐ์ฐ์ ์๋ฏธํฉ๋๋ค. ์์ JPA๋ฅผ ์ฌ์ฉํ ๊ฒฝ์ฐ executeUpdate()๋ฅผ ํตํด ๋ฒํฌ ์ฐ์ฐ์ ์ํํ ์ ์์์ต๋๋ค. ์๋ฅผ ๋ค์ด ๋ชจ๋ ํ์์ ๋์ด๋ฅผ 1์ฉ ์ฆ๊ฐ์ํค๋ ์ฟผ๋ฆฌ๋ฅผ ์์ JPA๋ก ์์ฑํ๋ฉด ๋ค์๊ณผ ๊ฐ์ต๋๋ค. int resultCount = em.createQuery("update Member m set m.age = m.age").executeUpdate() Spring Data JPA์์์ ๋ฒํฌ ์ฐ์ฐ @Modifying์ ์ฌ์ฉํฉ๋๋ค. public interface MemberRepository extends JpaRepository { @Modifying @Query("update Member m set m.age = m.a..
ํด๋ฆญ ์ ์ด๋ํฉ๋๋ค. ์์ํ JPA DATA JPA QueryDSL ์์ JPA ์์์ ํ์ด์ง ๋ค์ ๋ ๋ฉ์๋๋ฅผ ํตํด ํ์ด์ง์ ์งํํฉ๋๋ค setFirstResult(int startPosition) : ์กฐํ ์์ ์์น, 0๋ถํฐ ์์ํฉ๋๋ค. setMaxResult(int maxResult) : ์กฐํํ ๋ฐ์ดํฐ ์ setFirstResult๋ ํ์ด์ง์ ๋ฒํธ๊ฐ ์๋ ์กฐํ๋ฅผ ์์ํ row์ ์์น๋ฅผ ์ค์ ํ๋ ๊ฒ์
๋๋ค. ์์ ์ฝ๋ em.createQuery("select m from Member m where m.age = :age order by m.username desc", Member.class) .setParameter("age", age) .setFirstResult(0) //์์ ์์น ์ง์ .setMax..
JPA์ ๋ฐํ ํ์
์ ์ข
๋ฅ Data JPA์์ ๋ฐํ ํ์
์ ์ง์ ํ ๋, ๋ค์๊ณผ ๊ฐ์ ๋ฐํ ํ์
๋ค์ ์ง์ ํ ์ ์์ต๋๋ค. List : ์ปฌ๋ ์
, ๊ฒฐ๊ณผ๊ฐ ์์ผ๋ฉด ๋น ์ปฌ๋ ์
์ ๋ฐํํฉ๋๋ค. Member : ๋จ๊ฑด(๊ฒฐ๊ณผ๊ฐ ์์ผ๋ฉด ๊ฒฐ๊ณผ๊ฐ null, ๊ฒฐ๊ณผ๊ฐ 2๊ฐ์ด๋ฉด ์๋ฌ๊ฐ ๋ฐ์ํฉ๋๋ค.) Optional : ๋จ๊ฑด optional(๊ฒฐ๊ณผ๊ฐ 2๊ฐ์ด๋ฉด ์๋ฌ๊ฐ ๋ฐ์ํฉ๋๋ค) ... https://docs.spring.io/spring-data/jpa/docs/2.3.0.RELEASE/reference/html/#repository-query-return-types Spring Data JPA - Reference Documentation Example 108. Using @Transactional at query methods @T..
์ฟผ๋ฆฌ ๋ฉ์๋ ์คํ๋ง ๋ฐ์ดํฐ JPA๊ฐ ์ ๊ณตํ๋ ์ฟผ๋ฆฌ ๋ฉ์๋ ๊ธฐ๋ฅ์ ๋ํ์ ์ผ๋ก ๋ค์๊ณผ ๊ฐ์ต๋๋ค. ๋ฉ์๋์ ์ด๋ฆ์ผ๋ก ์ฟผ๋ฆฌ ์์ฑ @Query๋ฅผ ์ฌ์ฉํด์ ๋ฆฌํ์งํ ๋ฆฌ ์ธํฐํ์ด์ค์ ์ฟผ๋ฆฌ๋ฅผ ์ง์ ์ ์ ๋ฉ์๋ ์ด๋ฆ์ผ๋ก ์ฟผ๋ฆฌ ์์ฑ Optional findByUsername(String username); ์์ ์์์ฒ๋ผ ๋ฉ์๋์ ์ด๋ฆ๋ง ์ค์ ํจ์ผ๋ก์จ ์ฟผ๋ฆฌ๋ฅผ ์๋์ผ๋ก ์์ฑํ ์ ์์ต๋๋ค. ์ค์ํ ๊ฒ์ ํด๋น ํ๋๊ฐ ์ํฐํฐ์ ์กด์ฌํด์ผ ํ๋ฉฐ, ํ๋๋ช
๊ณผ ๋ฉ์๋ ์ด๋ฆ์ด ๋ฐ๋์ ์ผ์นํด์ผ ํ๋ค๋ ๊ฒ์
๋๋ค. ๊ทธ๋ ์ง ์๋๋ค๋ฉด ์ ํ๋ฆฌ์ผ์ด์
๋ก๋ฉ ์์ ์ ์์ธ๊ฐ ๋ฐ์ํฉ๋๋ค. ์ ์ด https://docs.spring.io/spring-data/jpa/docs/current/reference/html/#appendix.query.method.subje..
์คํ๋ง ๋ฐ์ดํฐ JPA์์ ์ถ์ํ์ ์ค์ฌ์ด ๋๋ ์ธํฐํ์ด์ค๋ Repository ์
๋๋ค. Repository๋ ๊ด๋ฆฌํ ๋๋ฉ์ธ ํด๋์ค์, ๋๋ฉ์ธ ํด๋์ค์ ID(์๋ณ์)๋ฅผ ํ์
์ธ์๋ก ์ฌ์ฉํฉ๋๋ค. ์ค์ ๊ตฌํ์ ๋ค์๊ณผ ๊ฐ์ต๋๋ค. @NoRepositoryBean public interface CrudRepository extends Repository { S save(S entity); Iterable saveAll(Iterable entities); Optional findById(ID id); boolean existsById(ID id); Iterable findAll(); Iterable findAllById(Iterable ids); long count(); void deleteById(ID id); v..