====== Spring Data JDBC ====== * [[https://projects.spring.io/spring-data-jdbc/|Spring Data JDBC]] * https://github.com/spring-projects/spring-data-jdbc * [[https://spring.io/blog/2018/09/17/introducing-spring-data-jdbc|Introducing Spring Data JDBC]] * [[springframework:spring_data_jdbc:querydsl|Spring Data JDBC & QueryDSL]] ===== 가장 큰 특징 ===== * Entity 가 proxy 객체가 아닌 POJO 이기 때문에, proxy 일 때 발생하는 숨은 동작들이 발생하지 않는다. * 이 특징을 잘 활용하면 side effect 없이 다양한 시도를 할 수 있다. ===== JdbcAggregateTemplate ===== * [[https://docs.spring.io/spring-data/jdbc/docs/current/api/org/springframework/data/jdbc/core/JdbcAggregateTemplate.html|JdbcAggregateTemplate]] * SpringDataJdbc 가 내부적으로 사용하는 DB 제어 template * 직접 주입 받아서 사용가능하다. ===== EntityCallback ===== * [[https://docs.spring.io/spring-data/commons/docs/current/api/org/springframework/data/mapping/callback/EntityCallback.html?is-external=true|EntityCallback]] - Spring Data의 EntityCallback * [[https://docs.spring.io/spring-data/jdbc/docs/current/api/org/springframework/data/relational/core/mapping/event/BeforeSaveCallback.html|BeforeSaveCallback]] : Entity 저장전 Callback. * 각종 ''Before*Callback'' ===== AbstractJdbcConfiguration ===== * [[https://docs.spring.io/spring-data/jdbc/docs/current/api/org/springframework/data/jdbc/repository/config/AbstractJdbcConfiguration.html|AbstractJdbcConfiguration]] 설정 확장. * [[https://docs.spring.io/spring-data/jdbc/docs/current/api/org/springframework/data/jdbc/core/convert/JdbcCustomConversions.html|JdbcCustomConversions]] : Custom 객체 -> DB 저장데이터 변환 * [[https://docs.spring.io/spring-data/commons/docs/current/api/org/springframework/data/convert/WritingConverter.html|@WritingConverter]] : 데이터를 컬럼으로 쓰기할 때 변환 * [[https://docs.spring.io/spring-data/commons/docs/current/api/org/springframework/data/convert/ReadingConverter.html|@ReadingConverter]] : 데이터를 컬럼에서 객체로 읽을 때 변환 ===== Bidirectional Relationship ===== ==== internal ==== * [[https://docs.spring.io/spring-data/commons/docs/current/api/org/springframework/data/annotation/Transient.html|@Transient]] : 해당 피드를 Repository에서 다루지 않는다는 표시. * [[https://docs.spring.io/spring-data/commons/docs/current/api/org/springframework/data/annotation/PersistenceConstructor.html|@PersistenceConstructor]] 로 지정된 생성자는 DB에서 데이터 읽어서 객체화 할 때 호출된다. * DB 데이터를 읽을 때 생성자에서 ''@Transient'' 필드에 값 주입해서 양방향 관계 흉내가 가능함. ==== external ==== * 이런 방법 보다는 그냥 [[https://docs.spring.io/spring-data/jdbc/docs/2.2.3/api/org/springframework/data/jdbc/core/mapping/AggregateReference.html|AggregateReference]] 를 사용해 ID 값만 저장하고 ID로 일괄 조회하는 것이 나을 듯. 이것이 SpringDataJDBC의 기본 방침. ===== Caching ===== * Spring Data JDBC는 Cache를 지원하지 않는다. * 필요하다면 [[springframework:cacheabstraction|Spring Cacheh Abstraction]]을 사용한다. ===== Eager Loading ===== * [[https://docs.spring.io/spring-data/jdbc/docs/2.2.3/api/org/springframework/data/jdbc/core/mapping/AggregateReference.html|AggregateReference]] 로 매핑된 필드를 [[https://docs.spring.io/spring-data/jdbc/docs/2.2.3/api/org/springframework/data/relational/core/mapping/Embedded.html|@Embedded]]로 매핑한 View 객체를 생성하고 일반 SQL 쿼리로 join 을 통해 값을 채우면 된다. * [[https://github.com/schauder/talk-beyond/blob/master/src/main/java/de/schauderhaft/beyond/join/MinionView.java|MinionView]] ''Minion''이라는 Entity에 대해 join 데이터를 ''Embed''한 view 클래스. * 어차피 조회한 엔티티가 proxy가 아니라서 별다른 side effect 없이 View 객체 사용가능. class MinionView extends Minion { MinionView(String name, AggregateReference evilMaster) { super(name, evilMaster); } @Embedded(onEmpty = Embedded.OnEmpty.USE_EMPTY, prefix = "master_") Person master; } // join 해서 MinionView에 값을 넣는 Repository 쿼리 @Query("select m.id as id, m.name name, m.number_of_eyes as number_of_eyes, " + "p.name as master_name, p.id as master_evil_master " + "from minion m join person p on p.id = m.evil_master") List allMinionViews(); ===== 참조 ===== * [[https://springone.io/2021/sessions/spring-data-jdbc-beyond-the-obvious|Spring Data JDBC: Beyond the Obvious | SpringOne | Sep 1–2, 2021]] * [[https://spring.io/blog/2020/05/20/migrating-to-spring-data-jdbc-2-0|Migrating to Spring Data JDBC 2.0]] * [[https://www.baeldung.com/spring-data-jdbc-intro|Introduction to Spring Data JDBC | Baeldung]] * [[https://www.infoq.com/presentations/spring-data-jdbc/|The New Kid on the Block: Spring Data JDBC]] * [[https://evgeniy-khist.github.io/spring-data-examples/#75e0f07fedd63771fc35ec852a9c937f|Spring Data JPA pitfalls and modern alternatives: Spring Data JDBC and Spring Data R2DBC]] * [[https://spring.io/blog/2018/09/24/spring-data-jdbc-references-and-aggregates|Spring Data JDBC, References, and Aggregates]] * [[https://spring.io/blog/2021/09/09/spring-data-jdbc-how-to-use-custom-id-generation|Spring Data JDBC - How to use custom ID generation]] * [[https://spring.io/blog/2021/09/22/spring-data-jdbc-how-do-i-make-bidirectional-relationships|Spring Data JDBC - How do I make Bidirectional Relationships?]] * [[https://spring.io/blog/2021/10/18/spring-data-jdbc-how-do-i-implement-caching|Spring Data JDBC - How do I implement caching?]] * [[https://www.youtube.com/watch?v=GOSW911Ox6s|Domain-Driven Design with Relational Databases Using Spring Data JDBC - YouTube]] : Spring Data JDBC에서 내부적으로 자동적으로 처리되는 부분들을 드러내 보여줌. * https://github.com/schauder/talk-beyond : 관련 소스 * [[https://www.youtube.com/watch?v=SJlKBkZ2yAU|Spring Data JDBC: Beyond the Obvious - YouTube]] * [[https://luvstudy.tistory.com/174|Spring Data JDBC는 현재 쓸 만할까?]] * 2022현재 multiple datasource 지정 안됨 * [[https://github.com/spring-projects/spring-data-relational/issues/544|Multiple datasources support [DATAJDBC-321] · Issue #544 · spring-projects/spring-data-relational]] * [[https://github.com/spring-projects/spring-data-relational/pull/1005|Add jdbcConverterRef to @EnableJdbcRepositories by kota65535 · Pull Request #1005 · spring-projects/spring-data-relational]] * [[https://youtube.com/playlist?list=PLbuI9mmWSoUFGL6B_NxB9IoGqyDq-vEen&si=aaNTrHZx_9fswpn6|Spring Dataa JDBC - SpringBoot 3]]