JPA - kdevkr/mambo-box GitHub Wiki

์˜ค๋žซ๋™์•ˆ ์‚ฌ์šฉํ•˜์ง€ ์•Š์•˜๋˜ JPA ์‚ฌ์šฉํ•ด๋ณด๊ธฐ!

JPA ๊ด€๋ จ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์†์„ฑ ์„ค์ •

spring:
  jpa:
    show-sql: true
    hibernate:
      ddl-auto: none
    properties:
      hibernate:
        boot.allow_jdbc_metadata_access: false
    open-in-view: false
    database-platform: org.hibernate.dialect.PostgreSQLDialect
  datasource:
    url: jdbc:postgresql://[hostname]:5432/[database]
    hikari:
      jdbc-url: ${spring.datasource.url}
    username: [user]
    password: [password]

Hibernate Entity Manager ์ง์ ‘ ํ˜ธ์ถœํ•˜๊ธฐ

ํ…Œ์ด๋ธ”์„ ๋งŒ๋“ค์ง€ ์•Š๊ณ  ๊ฐ„๋‹จํ•œ ์ฟผ๋ฆฌ๋ฅผ ํ˜ธ์ถœํ•˜๊ณ  ์‹ถ์„๋•Œ (์˜ˆ, ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ๋ฒ„์ „ ์กฐํšŒ)

@PersistenceContext
EntityManager entityManager;

String version = entityManager.createQuery("SELECT version()", String.class).getSingleResult();

๋‹จ์ผ ์ปฌ๋Ÿผ์„ ๋งคํ•‘ํ•ด์„œ ๊ฐ€์ ธ์˜ฌ ๋ฐฉ๋ฒ•์€ ์—†๋‹ค!

์‚ฌ์šฉ์ž์— ๋Œ€ํ•œ ํ…Œ๋„ŒํŠธ ์•„์ด๋””(u_grp_id)๋ฅผ ํ•จ๊ป˜ ๊ฐ€์ ธ์˜ค๊ณ  ์‹ถ์„ ๋•Œ ์ฐธ์กฐ ํ…Œ์ด๋ธ”์— ๋Œ€ํ•œ ์กฐ์ธ ํŒจ์น˜๋ฅผ ์œ„ํ•ด์„œ๋Š” ์—”ํ„ฐํ‹ฐ๋กœ ๊ด€๋ฆฌ๋˜์–ด์•ผํ•จ

@Data
@Entity
@Table(name = "\"user\"")
public class UserEntity {
    @Id
    @Column(name = "u_id")
    private String uId;
    private String id;
    private String name;
    private String language;
    private String timeZone;
    private String type;
    private boolean del;

    @JsonIgnore
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "u_id", referencedColumnName = "u_id", insertable = false, updatable = false)
    private UserRel userRel;

    public String getUGrpId() {
        return userRel == null ? null : userRel.getUGrpId();
    }
}

@Data
@IdClass(UserRel.ID.class)
@Entity
@Table(name = "user_rel")
public class UserRel {

    @Id
    @Column(name = "u_id")
    private String uId;

    @Id
    @Column(name = "u_grp_id")
    private String uGrpId;

    @Data
    public static class ID implements Serializable {
        private String uGrpId;
        private String uId;
    }
}

Enum ๊ณผ Field ๊ฐ„ ๋ณ€ํ™˜

org.springframework.dao.DataIntegrityViolationException: Could not extract column [7] from JDBC ResultSet [Bad value for type byte : SYSTEM] [n/a]; SQL [n/a]
...
Caused by: org.hibernate.exception.DataException: Could not extract column [7] from JDBC ResultSet [Bad value for type byte : SYSTEM] [n/a]
...
Caused by: org.postgresql.util.PSQLException: Bad value for type byte : SYSTEM

@Enumerated(EnumType.STRING) ๋˜๋Š” JPA Attribute Converter ๋กœ ์ž๋ฐ” Enum ์„ DB ์ปฌ๋Ÿผ๊ณผ ๋งคํ•‘ํ•  ์ˆ˜ ์žˆ๋‹ค.

  • @Enumerated(EnumType.STRING): Enum ๊ณผ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— ์ €์žฅ๋˜๋Š” ๊ฒฐ๊ณผ๊ฐ€ ๋™์ผํ•  ๋•Œ
  • Attribue Converter: Enum ๊ณผ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— ์ €์žฅ๋˜๋Š” ๊ฐ’์ด ์ผ์น˜ํ•˜์ง€ ์•Š๋Š” ๊ฒฝ์šฐ
@Enumerated(EnumType.STRING)
@JdbcType(PostgreSQLEnumJdbcType.class)
private UserType type;

JSON ๋ฐ์ดํ„ฐ ์ฒ˜๋ฆฌ๋Š”?...

public class UserEntity {
    @JdbcTypeCode(SqlTypes.JSON)
    private Metadata metadata;

    @Data
    public static class Metadata {
        private String status;
        @JsonAlias({"alarm_interval"})
        private String alarmInterval;
    }
}

PostgreSQL์˜ PL/pgSQL ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ๋ฐฉ๋ฒ•

EntityManager ๋˜๋Š” JdbcTemplate ๋กœ ํ”„๋กœ์‹œ์ € ์ฝœ ํ˜ธ์ถœํ•˜๊ธฐ...

N+1 ๋ฌธ์ œ

์‹ ์ž… ๊ฐœ๋ฐœ์ž ์ด๋ ฅ์„œ์—์„œ ์‰ฝ๊ฒŒ ๋ณผ ์ˆ˜ ์žˆ๋˜... JOIN ์„ ์ˆ˜ํ–‰ํ•˜์ง€ ์•Š๊ณ  ์กฐํšŒ ๋ชฉ๋ก์— ๋Œ€ํ•œ ๊ฐœ์ˆ˜ ๋งŒํผ ๊ฐœ๋ณ„ ์กฐํšŒ๋ฅผ ์ˆ˜ํ–‰ํ•˜๋Š” ๊ณผ์ •, JPQL ๋กœ Fetch Join์„ ์ˆ˜ํ–‰ํ•ด์•ผ ํ•œ๋‹ค?

Hibernate: select ue1_0.u_id,ue1_0.created,ue1_0.del,ue1_0.id,ue1_0.language,ue1_0.last_login_time,ue1_0.name,ue1_0.time_zone,ue1_0.type from "user" ue1_0 offset ? rows fetch first ? rows only
Hibernate: select ur1_0.u_grp_id,ur1_0.u_id from user_rel ur1_0 where ur1_0.u_id=?
Hibernate: select ur1_0.u_grp_id,ur1_0.u_id from user_rel ur1_0 where ur1_0.u_id=?
Hibernate: select ur1_0.u_grp_id,ur1_0.u_id from user_rel ur1_0 where ur1_0.u_id=?
Hibernate: select ur1_0.u_grp_id,ur1_0.u_id from user_rel ur1_0 where ur1_0.u_id=?
Hibernate: select ur1_0.u_grp_id,ur1_0.u_id from user_rel ur1_0 where ur1_0.u_id=?
Hibernate: select ur1_0.u_grp_id,ur1_0.u_id from user_rel ur1_0 where ur1_0.u_id=?
Hibernate: select ur1_0.u_grp_id,ur1_0.u_id from user_rel ur1_0 where ur1_0.u_id=?
Hibernate: select ur1_0.u_grp_id,ur1_0.u_id from user_rel ur1_0 where ur1_0.u_id=?
Hibernate: select ur1_0.u_grp_id,ur1_0.u_id from user_rel ur1_0 where ur1_0.u_id=?
Hibernate: select ur1_0.u_grp_id,ur1_0.u_id from user_rel ur1_0 where ur1_0.u_id=?
Hibernate: select count(ue1_0.u_id) from "user" ue1_0
@Transactional(readOnly = true)
public interface UserEntityRepository extends JpaRepository<UserEntity, String> {
    @Query("SELECT u FROM UserEntity u join fetch u.userRel")
    Page<UserEntity> findAll(Pageable pageable);
}
Hibernate: select ue1_0.u_id,ue1_0.created,ue1_0.del,ue1_0.id,ue1_0.language,ue1_0.last_login_time,ue1_0.name,ue1_0.time_zone,ue1_0.type,ur1_0.u_grp_id,ur1_0.u_id from "user" ue1_0 join user_rel ur1_0 on ur1_0.u_id=ue1_0.u_id fetch first ? rows only
Hibernate: select count(ue1_0.u_id) from "user" ue1_0 join user_rel ur1_0 on ur1_0.u_id=ue1_0.u_id

Instant and OffsetDateTime

@JdbcType(OffsetDateTimeJdbcType.class)
private OffsetDateTime createdAt;

@JdbcType(InstantJdbcType.class)
private Instant lastLoginTime;
  • Timestamp with timezone ์œผ๋กœ ๋งŒ๋“ค์–ด์ง€๋ฉฐ long ์€ Timestamp ์ปฌ๋Ÿผ์ด ๋œ๋‹ค.
โš ๏ธ **GitHub.com Fallback** โš ๏ธ