@Table(name="MBR")처럼 테이블 명을 바꾸는건 insert 쿼리나, update쿼리는 런타임에 영향을 주나, unique 제약 조건을 넣는건 실행 자체엔 영향 안주고, DDL 생성만 한다.
@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;
@Transient
private int temp;
public Member() {
}
}
@Column(name = "name") // db컬럼명은 name 이야.
private String username;
객체는 username이라고 쓰고싶은데, db에는 name이라고 적고 싶으면 이렇게 적어주면 됨.
db에는 enum 이 없음.
따라서 @Enumerated 어노테이션을 써주면 됨.
varchar를 넘어서는 큰 타입을 쓰고 싶으면 @Lob 해주면 됨.
@Lob 인데 String이면 clob으로 생성됨
이건 db랑 관계없이 메모리에만 계산하고 싶어 -> @Transient
@Column(name = "name",nullable = false,columnDefinition = "varchar(100) default 'EMPTY'")
private String username; 하면
반영이 되는것을 확인가능
Ordinal은 사용하면 안된다.
왜?
try {
Member member = new Member();
member.setId(1L);
member.setUsername("A");
member.setRoleType(RoleType.USER);
em.persist(member);
tx.commit();
}
이렇게 데이터를 넣었을 때,
public enum RoleType {
GUEST, USER, ADMIN;
}
게스트를 추가하면
순서가 바뀐다.
따라서 필수로 String으로 써야한다!!
@Enumerated(EnumType.STRING)
private RoleType roleType;
ROLETYPE이 GUEST로 들어간 것을 볼 수 있다.
최근은 Temporal 안씀.
private LocalDate testLocalDate;//연월
private LocalDateTime testLocalDateTime;//연월일
요렇게 쓴다
Auto는 데이터베이스 방언에 맞춰서 셋중 하나가 선택되는것.
Member.java
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private String id;
JpaMain.java
try {
Member member = new Member();
member.setUsername("C");
em.persist(member);
tx.commit();
}
id가 자동으로 생성됨.
Identity전략은 id에 값을 넣지 않고 db에 인서트 해야한다.
null로 insert쿼리가 날라오면 디비에서 그때 값을 세팅해준다.
Member.java
@Entity
public class Member {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
JpaMain.java
try {
Member member = new Member();
member.setUsername("C");
System.out.println("==================");
em.persist(member);
System.out.println("==================");
tx.commit();
}
persist하는 시점에 쿼리가 날라간다.
insert쿼리를 날려봐야 그때서야 pk값을 알 수 있다.
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE)
private Long id;
시퀀스 오브젝트를 만들어냄.
데이터베이스에 있는 시퀀스 오브젝트를 통해 시퀀스를 가져와서 값을 세팅하는 것.
숫자니까 Long으로 해주어야한다!(Integer는 10몇억 이상은 안된다)
@Entity
@SequenceGenerator(name = "member_seq_generator", sequenceName = "member_seq")
public class Member {
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "member_seq_generator")
private Long id;
meber_seq라는 시퀀스 오브젝트를 만들어냈다.
try {
Member member = new Member();
member.setUsername("C");
System.out.println("==================");
em.persist(member);
System.out.println("member.id = " + member.getId());
System.out.println("==================");
tx.commit();
}
em.persist를 할 때, 영속성 컨텍스트에 넣어야한다. 그럴려면 항상 pk가 있어야 한다.
그럴려면 먼저 시퀀스를 가지고 와야한다. 시퀀스에서 내 pk를 가지고 와야한다. @GeneratedValue(strategy = GenerationType.SEQUENCE,
generator = "MEMBER_SEQ_GENERATOR") 너 시퀀스 전략이네, 하고 jpa가 여기서 내가 값 가져올게 하는 방식으로 매커니즘이 동작한다.
그래서 call next value for MEMBER_SEQ (MEMBER_SEQ)의 다음 값 내놔 라는 쿼리를 날린다.
정리 : 영속성 컨텐스트 넣을려하는데 sequence 전략이네?
db한테 가서 얻어와야 겠네하고 db에서 값을 얻어와서
db에 이 id값을 넣어준다.
그 다음 영속성 컨텍스트에 저장함. 아직 db에 insert쿼리는 안날라감.
왜냐면 pk값만 딱 얻고 버퍼링도 해야하므로 영속성컨텍스트에 쌓여있다가
실제로 커밋하는 시점에 insert쿼리가 호출이 된다. 시퀀스 방식은 버퍼링(모아놨다가 한번에 보냄) 이 가능.
Member.java
@SequenceGenerator(
name = "MEMBER_SEQ_GENERATOR",
sequenceName = "MEMBER_SEQ", //매핑할 데이터베이스 시퀀스 이름
initialValue = 1, allocationSize = 50)
JpaMain.java
try {
Member member1 = new Member();
member1.setUsername("A");
Member member2 = new Member();
member2.setUsername("B");
Member member3 = new Member();
member3.setUsername("C");
System.out.println("==================");
em.persist(member1); //1,51
//em.persist(member2); //Memory에서 호출이됨
//em.persist(member3); // "
System.out.println("member.id = " + member1.getId());
System.out.println("member.id = " + member2.getId());
System.out.println("member.id = " + member3.getId());
System.out.println("==================");
tx.commit();
}
allocationSize:db에 50개를 db에 미리 올려두고 메모리에서 그 개수만큼 쓰는 방식.
51이면 1 부터 50개까지 쓸 수 있구나 한다.
101이면 51부터 100까지 쓸 수 있구나 함.
call next value for MEMBER_SEQ가 두번 호출 된다. 왜 두번 호출될까?
처음 호출하면 DB SEQ는 1이 되고, 두번째 호출하면 51이 된다
처음 호출해봤더니 1이 되어서 뭔가 문제가 있나보다 해서 한번더 호출된거다.
DB SEQ = 1 | 애플리케이션이 쓰는 것: 1
DB SEQ = 51 | 2
DB SEq = 51 | 3
start with 1 increment by 1: 1부터 시작해서 1씩 증가
시퀀스는 db가 관리하기 때문에
MEMBER_SEQ를 확인할 수 있다.
@Entity
@TableGenerator(
name = "MEMBER_SEQ_GENERATOR",
table = "MY_SEQUENCES",
pkColumnValue = "MEMBER_SEQ", allocationSize = 1)
public class Member {
@Id
@GeneratedValue(strategy = GenerationType.TABLE,
generator = "MEMBER_SEQ_GENERATOR")
private Long id;
자연키 : 비즈니스 적으로 의미있는 키 ex) 주민등록번호
대리키 : 비즈니스적으로 관계없는 키
비즈니스를 키로 끌고 오지 말자.
@Entity
public class Item {
@Id @GeneratedValue
@Column(name = "ITEM_ID")
private Long Id;
private String name;
private int Price;
private int stockQuality;
Member.java
package jpabook.jpashop.domain;
import javax.persistence.*;
@Entity
public class Member {
@Id @GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "MEMBER_ID")
private Long id;
private String name;
private String city;
private String street;
private String zipcode;
Order.java
@Entity
@Table(name = "ORDERS")
public class Order {
@Id
@GeneratedValue
@Column(name = "ORDER_ID")
private Long id;
@Column(name = "MEMBER_ID")
private Long memberId;
private LocalDateTime orderDate;
@Enumerated(EnumType.STRING)
private OrderStatus status;
OrderItem.java
@Entity
public class OrderItem {
@Id
@GeneratedValue
@Column(name = "ORDER_ITEM_ID")
private Long id;
@Column(name = "ORDER_ID")
private Long orderId;
@Column(name = "ITEM_ID")
private Long itemId;
private int orderPrice;
private int count;
OrderStatus.java
public enum OrderStatus {
ORDER, CANCLE;
}
Id를 db가 만들어주는 값을 쓴다고 가정하면 @GeneratedValue까지 해줘야한다.
getter,setter의 경우 다 만들어준 필요는 없지만 getter는 만들어주는게 좋다. setter는 좀 고민해봐야.
가급적이면 생성자에서 세팅하도록 해야한다.
Enum타입은 @Enumerated()를 해줘야한다.
localhost/~/test->localhost/~/jpashop
새로운 db쓰는것.
<property name="javax.persistence.jdbc.url" value="jdbc:h2:tcp://localhost/~/jpashop"/>
객체는 참조로 쭉쭉 이어져야 함.