JPA #4 ์ํฐํฐ ๋งคํ (๊ฐ์ฒด-ํ ์ด๋ธ ๋งคํ)
by JiwonDevJPA๋ ๋ฐ์ดํฐ๋ฒ ์ด์ค ํ ์ด๋ธ๊ณผ ๋งคํํ๊ธฐ๊ฐ ์ ๋ง ์ฝ๋ค. ์ ๋ ธํ ์ด์ ์ผ๋ก ๊ฐ๋จํ๊ฒ ๊ฐ๋ฅํ๋ค.
• ๊ฐ์ฒด์ ํ
์ด๋ธ ๋งคํ: @Entity, @Table
• ํ๋์ ์ปฌ๋ผ ๋งคํ: @Column
• ๊ธฐ๋ณธ ํค ๋งคํ: @Id
• ์ฐ๊ด๊ด๊ณ ๋งคํ: @ManyToOne,@JoinColumn
๐ @Entity
JPA์์ ์ฌ์ฉํ ์ํฐํฐ ํด๋์ค๋ฅผ ์ง์ ํ๋ค. ๋ฐ๋์ ๋ถ์ฌ์ค์ผํ๋ฉฐ ์๋ค๋ฉด ๊ฐ์ฒด๋ฅผ JPA๋ก ๋ค๋ฃฐ ์ ์๋ค.
@Entity(name = "์ด๋ฆ") ์ผ๋ก JPA์์ ์ธ ์ํฐํฐ ์ด๋ฆ์ ์ง์ ํด์ค ์ ์์ผ๋ฉฐ, ์๋ตํ๋ฉด ํด๋์ค๋ช ์ ์ด๋ฆ์ผ๋ก ์ฌ์ฉํ๋ค.
- ๋จ, ๋ฆฌํ๋ ์ ์ ์ด์ฉํ๊ธฐ ๋๋ฌธ์ [public ๋๋ protected ์ธ ๊ธฐ๋ณธ์์ฑ์]๊ฐ ํ์์ด๋ค.
- ๋ํ ์ฌ์ฉํ๋ ํ๋, ํด๋์ค์ final์ ์ฌ์ฉํ ์ ์๋ค. ํ๋ก์ ์์ฑ ๋ถ๊ฐ๋ฅ.
- enum, interface, inner ํด๋์ค ๋ํ ์ง์ํ์ง ์๋๋ค.
๋ด๋ถ์ ์ผ๋ก CGLIB๋ฑ์ ์ฌ์ฉํ์ง๋ง, ์ค๊ฐ์ ์ ๋ฐ์ดํธ๋๋ฉฐ ๋ฆฌํ๋ ์ ๊ธฐ์ ์ด ๋ฐ๋ ์๋ ์๊ธฐ์ ๊ฐ๋ตํ๊ฒ๋ง ์๊ณ ๋์ด๊ฐ์.
// JPA ์ด๋
ธํ
์ด์
์ ์๋ฐ ํ์ค persistence์ ํฌํจ๋์ด์๋ค.
import javax.persistence.Entity;
import javax.persistence.Id;
@Entity // ๋ณดํต ์๋ตํด์ ๋ง์ด ์ฌ์ฉํ๋ค. ํด๋์ค๋ช
์ ์ด๋ฆ์ผ๋ก ์ฌ์ฉ
public class Member {
@Id
private Long id;
@Column(name = "name")
private String username;
private Integer age;
@Enumerated(EnumType.STRING)
private RoleType roleType;
@Temporal(TemporalType.TIMESTAMP)
private Date createdDate;
@Temporal(TemporalType.TIMESTAMP)
private Date lastModifiedDate;
@Lob
private String description;
//Getter, Setter…
}
๐@Table
์ํฐํฐ์ ๋งคํํ ํ ์ด๋ธ์ ์ง์ ํ๋ ์ด๋ ธํ ์ด์ ์ด๋ค.
@Table(name= "ํ ์ด๋ธ๋ช " ) ์ผ๋ก ํ ์ด๋ธ์ ์ง์ ํด์ค ์ ์์ผ๋ฉฐ, ์๋ตํ๋ฉด Entity ์ด๋ฆ์ ํ ์ด๋ธ๋ช ์ผ๋ก ์ฌ์ฉํ๋ค.
@Index๋ก ์ธ๋ฑ์ค๋ฅผ ์ถ๊ฐํ๊ฑฐ๋ @UniqueConstraint๋ฅผ ์ด์ฉํด ํน์ ์นผ๋ผ์ ์ ์ฝ ์กฐ๊ฑด์ ์ถ๊ฐํด์ค ์ ์๋ค.
ํน์ ์นผ๋ผ ์ ์ฝ์กฐ๊ฑด์ @Column(unique= ... ) ๋ก๋ ๊ฑธ ์ ์์ง๋ง, ์ ์ฝ์กฐ๊ฑด ์ด๋ฆ์ค์ ์ด ๋ถ๊ฐ๋ฅํ๋ค๋ ๋จ์ ์ด ์๋ค.
@Entity
@Table(name="MEMBER", // ํ
์ด๋ธ๋ช
์ MEMBER๋ก ์ง์
uniqueConstraints = { // name, age ์นผ๋ผ์ unique ์ ์ฝ์กฐ๊ฑด ์ถ๊ฐ
@UniqueConstraint(name = "NAME_AGE_UNIQUE", columnNames = {"NAME", "AGE"} )
})
public class Member {
...
}
@Table(indexes = {@Index(columnList="mycol1"), @Index(columnList="mycol2")})
โ JPA์ ํ ์ด๋ธ ์๋ ์์ฑ ๊ธฐ๋ฅ (ddl.auto)
์ฐธ๊ณ ๋ก JPA๋ฅผ ์ฌ์ฉํ๋ฉด ๋ง๋ค์ด๋ ๊ฐ์ฒด๋ฅผ ์ด์ฉํ์ฌ ํ ์ด๋ธ์ ์๋ ์์ฑ(=DDL ์์ฑ)ํ ์ ์๋ค.
์ ํ๋ฆฌ์ผ์ด์ ์คํ ์์ ์ @Entity๋ฅผ ์ฝ์ด DB์ DDL์ ๋ ๋ ค์ ํ ์ด๋ธ์ ์์ฑํ๋ค. ์๋ ์ต์ ์ผ๋ก ์ค์ ํ ์ ์๋ค.
* ์ด์์๋ฒ์์๋ ์ ๋๋ก ์ฌ์ฉํด์๋ ์๋๋ ๊ธฐ๋ฅ์ด๋ค. ์๋ชปํ๋ค๊ฐ ์ด์์ค์ธ DB๊ฐ ์ญ์ ๋๊ณ ๋ค์ ์์ฑ๋ ์ ์๋ค.
๐ @Id
ํ ์ด๋ธ์ ํ์ ๊ฐ์ธ ๊ธฐ๋ณธํค๋ฅผ ์ง์ ํ๋ค. (์๋ค๋ฉด IntelliJ์์ ์น์ ํ๊ฒ ์ค๋ฅ๋ฅผ ๋์์ค๋ค.)
๊ธฐ๋ณธํ์ (int, String)์ด๋ ๊ธฐ๋ณธ ๋ํผํ์ (Interger)์ ๊ธฐ๋ณธํค๋ก ์ง์ ํด ์ค ์ ์๋ค.
๊ฐ์ฒด์๋ Null์ด ๋ค์ด๊ฐ ์ ์์ผ๋ฏ๋ก, ๊ธฐ๋ณธ ํ์ ๋ณด๋ค๋ ๋ํผํ์ (Long, Interger)๋ฅผ ์ฌ์ฉํ๋ ๊ฑธ ๊ถ์ฅํ๋ค.
๊ฐํน ๋ํผํ์ ์ ์ฌ์ฉํ๋ฉด boxing/ unboxing ๊ณผ์ ๋๋ฌธ์ ์ฑ๋ฅ์ด ๋๋น ์ง๋๊ฒ ์๋๊ฐ ๊ฑฑ์ ํ๋ ์ฌ๋๋ ์๋๋ฐ, ์ด๋ DB I/O์ ๋นํ๋ฉด ๋งค์ฐ ๋น ๋ฅด๊ธฐ ๋๋ฌธ์ ๋ณ๋ชฉ์ด ์๊ธฐ์ง ์๋๋ค. ์คํ๋ ค null์ ์ ๋๋ก ์ฒ๋ฆฌํ์ง ๋ชปํด ๋ฐ์ํ ์ ์๋ ๋ฌธ์ ๊ฐ ํจ์ฌ ํฌ๊ณ , ํด๊ฒฐํ๊ธฐ ์ด๋ ต๊ธฐ ๋๋ฌธ์ ๊ฐ๊ธ์ ๋ํผํ์ ์ ์ฐ๋ ๊ฑธ ๊ถ์ฅํ๋ค.
๊ทธ ์ธ Date, BingDecimal ๊ฐ์ ๊ฒ๋ ๊ธฐ๋ณธํค๋ก ์ฌ์ฉ ๊ฐ๋ฅํ์ง๋ง, ์ ์ฌ์ฉํ์ง๋ ์๋๋ค.
๊ธฐ๋ณธ ํค์ ์ ์ฝ์กฐ๊ฑด์ null์ด ๋๋ฉด ์๋๊ณ , ์ ์ผํด์ผํ๋ฉฐ, ๋ฏธ๋์๋ ๋ณํ ์ผ์ด ์์ด์ผ ํ๋ค.
์๋ฅผ ๋ค์ด ์ฃผ๋ฏผ๋ฑ๋ก๋ฒํธ, ํ๋ฒ ๊ฐ์ ๊ฒ๋ ๋จผ ๋ฏธ๋์๋ ๋ณํด๋ฒ๋ฆด ๊ฐ๋ฅ์ฑ์ด ์์ด ๊ธฐ๋ณธํค๋ก ์ ํฉํ์ง ์๋ค.
๋ณํ์ง ์๋๋ค๊ณ ํ๋๋ผ๋ [๋น์ฆ๋์ค์ ์๋ฏธ์๋ ๋ฐ์ดํฐ]๋ฅผ ํค๋ก ์ฌ์ฉํ๋ค๊ฐ๋, ์ถํ์ ๋ฒ์ ์ธ ๋ฌธ์ ๋ ๊ฐ์ธ์ ๋ณด ๋๋ฌธ์ ํค๋ฅผ ์ฌ์ฉํ์ง ๋ชปํ๊ฒ ๋ ๊ฒฝ์ฐ DB๋ฅผ ์ ๋ง ํฌ๊ฒ ์๋ด์ผํ ์๋ ์๋ค.
๊ทธ๋์ ๋ณดํต [ํค ์์ฑ์ ๋ต์ ์ฌ์ฉํ Long ํค] ์ [๋น์ฆ๋์ค์ ์๊ด์๋ ๋์ฒดํค] ๋ฑ์ id๋ก ์ฌ์ฉํ๋ ๊ฑธ ๊ถ์ฅํ๋ค.
โ ๊ธฐ๋ณธํค ์์ฑ ์ ๋ต @GeneratedValue
๊ธฐ๋ณธํค๋ ์ง์ ๋ง๋ค์ง ์๊ณ , DB ์๋ ์์ฑ์ ์ด์ฉํ ์ ์๋ค. ์ด๋ ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ๊ธฐ๋ณธํค ์์ฑ์ ์์กดํ๋ ๋ฐฉ๋ฒ์ด๋ค.
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY) // ๊ธฐ๋ณธ๊ฐ์ AUTO
private Long id;
์ต์ ์ ์ด 4๊ฐ์ง๊ฐ ์๋ค.
- AUTO(๊ธฐ๋ณธ๊ฐ) : ์๋ 3๊ฐ์ง์ค DB ๋ฐฉ์ธ(dialect)์ ๋ฐ๋ผ ์๋ ์ง์ .
- IDENTITY : ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ํค ์์ฑ์ ์์. DB๊ฐ ์์์ ์ฒ๋ฆฌํด๋ผ (MySQL, PostgreSQL, SQL Server, DB2)
โก JPA ์ฟผ๋ฆฌ : id varchar(255) generated by default as identity
โก MySQL ์ฟผ๋ฆฌ : id varchar(255) not null auto_increment
* insert๋ฅผ ํ์ง ์์ผ๋ฉด id ๊ฐ์ด ๋ฌด์์ธ์ง ์ ์ ์๊ธฐ ๋๋ฌธ์ ์ฐ๊ธฐ ์ง์ฐ์ด ๋ถ๊ฐ๋ฅํ๋ค. ๋ฐ๋ก DB์ flush ๋๋ค.
๋ค๋ง ํค ์์ฑ์ ๋ฐ์ํ๋ ์ฐ๊ธฐ์ง์ฐ์ ์ค์ ์๋น์ค์๋ ์ฑ๋ฅ ์ฐจ์ด๊ฐ ๊ฑฐ์ ์์ด์ ๋ฌด์ํ๊ณ ์ฌ์ฉํด๋ ํฐ ์๊ด์ ์๋ค.
* JDBC3๋ถํฐ ์ถ๊ฐ๋ getGeneratedKeys๋ฅผ ์ฌ์ฉํ๊ธฐ ๋๋ฌธ์ [insert SQL+ select key] ๋ ์ฟผ๋ฆฌ๋ฅผ ํ ๋ฒ์ ์ฒ๋ฆฌํ๋ค. - SEQUENCE : ๋ฐ์ดํฐ๋ฒ ์ด์ค ์ํ์ค ์ค๋ธ์ ํธ ์ฌ์ฉ (Oracle, ๋จ @SequenceGenerator ๋ก DB ์ํธ์ค์ ์ฐ๋ ํ์)
โก id๋ฅผ ์ํธ์ค์์ ์กฐํํด ์์์ฑ ์ปจํ ์คํธ์ ์ ์ฅํ๋ค.
โก ์ํ์ค ์ค๋ธ์ ํธ๋ ๋ณดํต 1๋ถํฐ ์์ํ๊ณ , +1 ๋ก ์ฆ๊ฐ๋๊ธดํ์ง๋ง ๊ฐ๋ฐ์๊ฐ ์ํ๋ค๋ฉด ์ด ๊ฐ์ ๋ณ๊ฒฝํ ์๋ ์๋ค.
* ์ํ์ค๋ง DB์์ ๊ฐ์ ธ์ค๋ฉด ๋๊ธฐ์ ์ฟผ๋ฆฌ๋ ์ฐ๊ธฐ์ง์ฐ์ด ๊ฐ๋ฅํ๋ค.
@Entity
@SequenceGenerator(
name = "BOARD_SEQ_GENERATOR", // ์ฌ์ฉํ sequence ์ด๋ฆ
sequenceName = "BOARD_SEQ", // ์ค์ ๋ฐ์ดํฐ๋ฒ ์ด์ค sequence ์ด๋ฆ
initialValue = 1, allocationSize = 1
)
public class Board{
@Id
@GeneratedValue(
strategy = GenerationType.SEQUENCE,
generator = "BOARD_SEQ_GENERATOR" // ์์ sequence ์ด๋ฆ
)
private Long id;
}
โก ์๋ฌด๋ฆฌ ์ํ์ค๋ฅผ ๊ฐ์ ธ์จ๋ค๊ณ ํด๋, DB์ ๋งค๋ฒ ์ํ์ค ๊ฐ์ ์์ฒญ์ ํ๋๊ฒ ๋คํธ์ํฌ ๋น์ฉ์ด ๋ถ๋ด์ค๋ฌ์ธ ์ ์๋ค.
๊ทธ๋์ allocationSize๋ผ๋ ์ต์
์ ์ด์ฉํด์ DB์ ๋ฏธ๋ฆฌ ์ํ์ค ๊ฐ์ 50๊ฐ๋ฅผ ๋ง๋ค์ด๋๊ณ ํ๋ฒ์ ๋ฐ์์์ ์ฌ์ฉํ๋ค.
์ฌ๋ฌ ์ค๋ ๋์์ ๋์์ ์ฌ์ฉํ๋ค ํ๋๋ผ๋, ํ ๋น๋ฐ์ ์ํธ์ค๊ฐ ๋ค๋ฅด๊ธฐ ๋๋ฌธ์ (1~51, 52~100) ๋์์ฑ ๋ฌธ์ ๋ ์๋ค.
๋ค๋ง ์๋ฒ๊ฐ ์ค๊ฐ์ ์ฃฝ์ด๋ฒ๋ฆฌ๋ฉด ํ ๋น๋ฐ์๋ค๊ฐ ๋จ์ ์ํธ์ค๋ ์์ํ ์ฌ์ฉํ์ง ๋ชปํ๋ค. Size๋ฅผ ์ ๋นํ ์ค์ ํ์.
- TABLE : ํค ์์ฑ์ฉ ํ
์ด๋ธ ์ฌ์ฉ ( @TableGenerator ํ์)
DB์์ ์ํธ์ค ์ค๋ธ์ ํธ๋ฅผ ์ง์ํ์ง ์๋ ๊ฒฝ์ฐ, ์ง์ ํ ์ด๋ธ์ ๋ง๋ค์ด์ ์ํธ์ค์ฒ๋ผ ์ฌ์ฉํ๋ ๋ฐฉ๋ฒ์ด๋ค.
Table์ ์์ฑํ๋ ๊ฒ์ผ๋ฟ, DB ์ํธ์ค ์ค๋ธ์ ํธ์ ์ฌ์ฉ๋ฒ์ ๋์ผํ๋ค. ๋ค๋ง ์ฑ๋ฅ์ด ํจ์ฌ ๊ตฌ๋ ค์ ์ ์ฌ์ฉํ์ง ์๋๋ค.
/* ์ฑ๋ฅ์ด ๊ตฌ๋ฆฐ ๋์ , ๊ทธ๋ฅ ํ
์ด๋ธ์ ๋ง๋๋๊ฑฐ๋ผ ๋ชจ๋ DB์ ์ ์ฉ๊ฐ๋ฅ */
@Entity
@TableGenerator(
name = "MY_BOARD_SEQ_GENERATOR", // ์ฌ์ฉํ table sequence ์ด๋ฆ
table = "MY_BOARD_SEQ", // ์ค์ ๋ฐ์ดํฐ๋ฒ ์ด์ค table ์ด๋ฆ
pkColumnValue = "BOARD_SEQ", allocationSize = 1
)
public class Board{
@Id
@GeneratedValue(
strategy = GenerationType.TABLE,
generator = "MY_BOARD_SEQ_GENERATOR" // ์์ sequence ์ด๋ฆ
)
private Long id;
}
๐ @Column
ํ๋์ ์นผ๋ผ์ ๋งค์นญํ ๋ ์ฌ์ฉํ๋ค. @Column์ ์ด์ฉํด์ ์ ์ฝ์กฐ๊ฑด์ ์ถ๊ฐํ ์ ์๋ค.
๋น์ฐํ JPA ์คํ ๋ก์ง์ ์ํฅ์ ์ฃผ์ง๋ ์๋๋ค. ํ ์ด๋ธ์ ์์ฑํ ๋ (=์๋ DDL ์์ฑ์ ์ฌ์ฉํ ๋) ์ฌ์ฉ๋๋ค.
์ฌ๋ด์ด์ง๋ง @Table์ ์ธ๋ฑ์ค๋ @Column์ ์ ์ด๋๋ฉด DB๋ฅผ ํ์ธํ์ง ์์๋ ๊ฐ๋ฐ์๊ฐ ์ฝ๊ฒ ์ ๋ณด๋ฅผ ํ์ธํ ์ ์๋ค.
โ ๊ฐ์ฒด - ํ ์ด๋ธ ์ด๋ฆ๋ณ๊ฒฝ ์ ๋ต (naming_strategy)
๋ฌผ๋ก @Column์ ์๋ตํด๋ ๋๋ค. ์์์ ํน์ ๊ท์น์ ๋ฐ๋ผ ํ ์ด๋ธ๊ณผ ๊ฐ์ฒด๋ฅผ ๋งคํ๋๋๋ก ๋์ํ๋ค.
๋ณดํต ๊ฐ์ฒด๋ ์นด๋ฉ์ผ์ด์ค(myHomeTown)์ ์ฌ์ฉํ๊ณ , DB๋ ์ธ๋์ค์ฝ์ด(MY_HOME_TOWN)์ ์ฐ๋๊ฒ ์ผ๋ฐ์ ์ธ๋ฐ. ๋ง์ฝ ๋ค๋ฅด๊ฒ ๋ณํํ๊ณ ์ถ๋ค๋ฉด naming_strategy ์ต์ ์ ํตํด ์ ์ ํ๊ฒ ๋ณํ ๊ฐ๋ฅํ๋ค.
- ImprovedNamingStrategy : camelCase๋ฅผ CAMEL_CASE๋ก ๋ณ๊ฒฝ
- SpringPhysicalNamingStrategy (์คํ๋ง์ฉ ์ต์ , ๊ธฐ๋ณธ๊ฐ) : camelCase๋ฅผ CAMEL_CASE๋ก ๋ณ๊ฒฝ. (์์๊ฑธ ์์ํด์๋ง๋ฆ)
- PhysicalNamingStrategyStandardImpl (์คํ๋ง์ฉ ์ต์ ) : ๋ณ๊ฒฝ์์ด ๋ณ์์ด๋ฆ์ ๊ทธ๋๋ก ์ฌ์ฉ
- ๊ฑฐ์ ์ฌ์ฉํ ์ผ์ ์์ง๋ง ์ด๋ฆ ์ ๋ต ํด๋์ค๋ฅผ ์ปค์คํ ํด์ ์ฌ์ฉํ ์๋ ์๋ค. ๊ถ๊ธํ๋ฉด ๊ฒ์ํด๋ณด๋๋ก ํ์.
// resource/META-INFO/persistence.xml
<property name="hibernate.ejb.naming_strategy" value="org.hibernate.cfg.ImprovedNamingStrategy"></property>
// resource/application.yml
jpa:
hibernate:
naming:
physical-strategy: org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl
public class Member {
// ๊ธฐ๋ณธํค ๋งคํ
@Id
@Column(name = "ID")
private String id;
// not null, varchar(10)
@Column(name = "NAME", nullable = false, length = 10)
private String username;
}
๐ [DB ์นผ๋ผ]๊ณผ [๊ฐ์ฒด ํ๋] ๋งคํํ๊ธฐ
@Column ๋ง๊ณ ๋ค์ํ ๋งคํ ์ด๋ ธํ ์ด์ ์ ์ ๊ณตํด์ค๋ค.
public enum RoleType {
ADMIN, USER
}
@Entity
public class Member {
@Id
private Long id;
@Column(name = "name") // @Column์ ์ด์ฉํ์ฌ ์ ์ฝ์กฐ๊ฑด์ ์ถ๊ฐํ๊ฑฐ๋ ํ
์ด๋ธ๊ณผ ๋งคํํ๋ค.
private String username;
private Integer age; // DB์ ์๋ ํ์
์ ๋ณ๋ค๋ฅธ ์ต์
์ด ์์ด๋ ์์์ ์ฒ๋ฆฌ.
// DB์๋ Enum ํ์
์ด๋๊ฒ ์์ผ๋ฏ๋ก, ๋ฐ๋ก ์ง์ ํด์ฃผ์ด์ฌํ๋ค.
@Enumerated(EnumType.STRING)
private RoleType roleType;
// DB๋ TIME, DATE, TIMESTAMP(์๊ฐ+๋ ์ง)๋ก ๊ตฌ๋ถ์ง์ด ์ฌ์ฉํ๋ค.
@Temporal(TemporalType.TIMESTAMP)
private Date createdDate;
@Temporal(TemporalType.TIMESTAMP)
private Date lastModifiedDate;
@Lob
private String description;
//Getter, Setter…
}
โ @Basic
DB ์นผ๋ผ์ ๋งคํ์ ํ ๋์๋ @Column์ด๋ @Table (* ์ด๋ฆ์ง์ ๊ฐ๋ฅ)์ ์ฌ์ฉํ๋ฉด ๋๋ค.
๋ง์ฝ JPA Entity์ ํน์ ์ต์ ์ ์ฃผ๊ณ ์ถ์ ๊ฒฝ์ฐ @Basic์ ์ฌ์ฉํ๋ค.
@Lob @Basic(fetch = FetchType.EAGER) // optional = false ๋ฑ์ผ๋ก nullable ์ค์ ๋ ๊ฐ๋ฅ
private String profileImage;
์ด๋ ๋ฐ์ดํฐ๋ฒ ์ด์ค ์นผ๋ผ๊ณผ๋ ์๊ด์์ด, ๊ทธ๋ฅ JPA ์์ ์ถ๊ฐ์ ์ธ ์ต์ ์ ์ค ๋ ์ฌ์ฉํ๋ ๊ธฐ๋ฅ์ด๋ค.
- @Column ์ฌ์ฉ์, ๋ฐ์ดํฐ๋ฒ ์ด์ค์์ null์ ํ์ฉํ๋ฉด ๋ฌด์กฐ๊ฑด null ํ์ฉ์ด๋ค. ์ ํ๊ถ์ด ์๋ค.
- @Basic์ ๋ฐ์ดํฐ๋ฒ ์ด์ค null ์ฌ๋ถ์ ์๊ด์์ด, JPA Entity ์์ฒด์ ์ ์ฝ์กฐ๊ฑด์ ์ค ์ ์๋ค.
โ ์ฃผ์์ฌํญ
๋ง์ฝ DB์ ์ ์ฅํ์ง ์๊ณ ์ถ๋ค๋ฉด, ๋ฉ๋ชจ๋ฆฌ์๋ง ๋จ๊ฒจ๋๋ @Transient๋ฅผ ์ฌ์ฉํ๋ฉด ๋๋ค. (์ฟผ๋ฆฌ๊ฐ ๋ฐ์ํ์ง ์๋๋ค.)
@Transient
private MyCacheMemory Temp
* ์ฐธ๊ณ ๋ก Enumeratd๋ ๋ฐ๋์ STRING์ผ๋ก ์ฌ์ฉํด์ผํ๋ค.
์์(1,2,3)์ ์ฌ์ฉํ๋ ORDINAL๋, Enum ๊ฐ์ฒด๋ฅผ ์์ ํ ๋๋ง๋ค DB์ ์๋ ์๋ณ์์ ์๋ฏธ๊ฐ ๋ฐ๋๊ธฐ์ ํฐ์ผ ๋ ์์๋ค.
@Enumerated(EnumType.STRING) // ORDINAL โ
private RoleType roleType;
@Temporal์ Java8 ์ดํ ๋ฒ์ ์๋ ์ฌ์ฉํ ์ผ์ด ๊ฑฐ์ ์๋ค.
๊ทธ๋ฅ LocalDate, LocalDateTime ํด๋์ค๋ฅผ ์ฌ์ฉํ๋ฉด ์์์ ์ฒ๋ฆฌ๋๊ธฐ ๋๋ฌธ์ด๋ค
@Lob์ ๋ฐ๋ก ์ง์ ํ๋ ์ต์ ์ด ์๊ณ , ํ์ ์ด ๋ฌธ์๋ฉด CLOB, ๊ทธ ์ธ๋ BLOB ( ๋ฐ์ด๋๋ฆฌ )๋ก ์๋ ๋งคํ๋๋ค.
๐ @Embedded (์ปดํฌ๋ํธ)
๋ญ ์ฐจ๊ทผ์ฐจ๊ทผ ๋ฐฐ์๋๊ฐ๊ฑฐ์ง๋ง, ์ด๋ฒ ๊ธ์์ ๋ฐฐ์ด ๊ฑธ ์ฌ์ฉํ ์ต์ข ์ ์ธ ์ฝ๋๋ ์๋์ ๋น์ทํ๊ฒ ๋ง๋ค์ด ์ง๊ฒ๋๋ค.
// ์๋ฒ ๋๋ ํ์
์ฌ์ฉํ์ง ์์์ ๋
@Entity
public class Member {
@Id @GeneratedValue
private Long id;
private String name;
// ๊ทผ๋ฌด ๊ธฐ๊ฐ
LocalDate startDate;
LocalDate endDate;
// ์ง ์ฃผ์ ํํ
private String city;
private String street;
private String zipcode;
// ...
}
ํ์์ด ์์ ๊ฐ์ ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ง ์ด์ ๋ ์๋์ ๊ฐ์ด ์ค๊ณํ๊ณ ์ ํ๊ธฐ ๋๋ฌธ์ ๋๋ค.
"ํ์ ์ํฐํฐ๋ ์ด๋ฆ, [ ๊ทผ๋ฌด ๊ธฐ๊ฐ ], [ ์ง ์ฃผ์ ]๋ฅผ ๊ฐ์ง๋ค."
์ค์ ๋ฐ์ดํฐ๋ '๊ทผ๋ฌด๊ธฐ๊ฐ', '์ง ์ฃผ์'๋ผ๋ ํ๋์ ๊ฐ์ผ๋ก ๋ค๋ฃจ๊ธฐ์๋ ๊น๋ค๋กญ์ต๋๋ค. ๊ทธ๋์ ์ด๋ฐ Entity๊ฐ ๋ง๋ค์ด์ง๊ฑฐ์ฃ .
"ํ์ ์ํฐํฐ๋ ์ด๋ฆ, [๊ทผ๋ฌด ์์์ผ, ๊ทผ๋ฌด ์ข
๋ฃ์ผ], [์ฃผ์ ๋์, ์ฃผ์ ๋ํธ์, ์ฐํธ ๋ฒํธ]๋ฅผ ๊ฐ์ง๋ค."
๋ฌด์ธ๊ฐ ์ด์ํ์ง ์์ผ์ ๊ฐ์? ํ์์ด '์ง ์ฃผ์'๊ฐ ํ์ํ ๊ฒฝ์ฐ๋ ์์ง๋ง, '์์ธ', '906ํธ' ์ด๋ฐ ๋ฐ์ดํฐ๊ฐ ๋จ๋ ์ผ๋ก ํ์ํ ๊ฒฝ์ฐ๊ฐ ์์๊น์?
์๋ ์ ์ด์, [ ์ง ์ฃผ์ ] ๋ ํ๋์ ๋ฐ์ดํฐ๋ก ๋ด์ผํ ๊ฑฐ ๊ฐ์๋ฐ, ์ฌ๊ธฐ์ ํฌํจ๋ ์ธ๋ถ ๋ฐ์ดํฐ๋ฅผ ํ์์ด ๊ฐ์ง๊ณ ์๋๊ฒ ๊ฐ์ฒด์งํฅ์ ์ผ๋ก ์ข์ ์ค๊ณ์ธ์ง ๊ณ ๋ฏผํด๋ณผ ํ์๊ฐ ์์ต๋๋ค. ์ด๋ ์์ง๋ ฅ์ ๋จ์ด๋จ๋ฆฌ๊ณ , ์ฌ์ฉ๊ณผ ์ ์ง๋ณด์๋ฅผ ์ด๋ ต๊ฒ ๋ง๋ญ๋๋ค.
โจ ์ด๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํด JPA์์๋ @Embedded ํ์ (์ปดํฌ๋ํธ)๋ฅผ ์ ๊ณตํด์ค๋๋ค.
์ฐธ๊ณ ๋ก ์๋ฒ ๋๋ ํ์ ์ ์ฌ์ฉํ๋ค๊ณ ํด์ DB ํ ์ด๋ธ์ด ๋ ์์ฑ๋์ง๋ ์์ต๋๋ค. ๊ธฐ์กด๊ณผ ๋์ผํ๊ฒ ๋งคํํด์ ์ฌ์ฉํฉ๋๋ค.
// ์๋ฒ ๋๋ ํ์
์ฌ์ฉ
@Entity
public class Member {
@Id @GeneratedVAlue
private Long id;
private String name;
@Embedded
private Period workPeriod; // ๊ทผ๋ฌด ๊ธฐ๊ฐ
@Embedded
private Address homeAddress; // ์ง ์ฃผ์
}
์๋ฒ ๋๋ ํ์ ์ ์๋์ ๊ฐ์ด ์ ์ ๊ฐ๋ฅํฉ๋๋ค.
@Embeddable
public class Address {
@Column(name="city") // ๋งคํํ ์ปฌ๋ผ ์ ์ ๊ฐ๋ฅ
private String city;
private String street;
private String zipcode;
public boolean isMetropolitanCity (City city) {
// .. ๊ฐ ํ์
์ ์ํ ๋ฉ์๋๋ฅผ ์ ์ํ ์ ์๋ค
}
}
๋น์ฐํ ์๋ฒ ๋๋ ํ์ ์์์ ๋ค๋ฅธ ์๋ฒ ๋๋ ํ์ ์ ์ฌ์ฉํ ์ ์์ต๋๋ค.
๊ทธ๋์ ์ ์ค๊ณ๋ JPA Entity๋ ๋ณดํต DB ํ ์ด๋ธ๋ณด๋ค ๋ ๋ง์ ์์ ๊ฐ์ฒด๋ฅผ ๊ฐ์ง๋๊ฒ ์ผ๋ฐ์ ์ ๋๋ค.
'๐ฑBackend > JDBC & JPA' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
JPA #6 ๋ค์ํ ์ฐ๊ด๊ด๊ณ ๋งคํ (1:N, N:1, N:N) (0) | 2021.11.09 |
---|---|
JPA #5 ๋ฐ์ดํฐ ์ค์ฌ ์ค๊ณ์ ๋ฌธ์ ์ , ์ฐ๊ด ๊ด๊ณ ๋งคํ (0) | 2021.11.09 |
JPA #3 ๊ธฐ๋ณธ ์ฌ์ฉ๋ฒ, ์์์ฑ ์ปจํ ์คํธ (0) | 2021.11.07 |
JPA #2 ๋ณธ๊ฒฉ์ ์ผ๋ก ์์๋ณด์. (0) | 2021.11.07 |
JPA #1 ๊ฐ์ฒด๋ฅผ ๋ฐ์ดํฐ๋ก ์ ์ฅํ๋ ๋ฐฉ๋ฒ (0) | 2021.11.07 |
๋ธ๋ก๊ทธ์ ์ ๋ณด
JiwonDev
JiwonDev