✔️ Member.java
@Entity
@Getter @Setter
public class Member {   
	@Id @GeneratedValue
	@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")	
@Getter @Setter
public class Order {
	
	@Id @GeneratedValue
	@Column(name = "ORDER_ID")
	private Long id;
	
	@Column(name = "MEMBER_ID")		// Member.java에 MEMBER_ID와 FK관계
	private Long memberId;
	
	private LocalDateTime orderDate;
	private String status;
	
}
✔️ OrderItem.java
@Entity
@Getter @Setter
public class OrderItem {	
	
	@Id @GeneratedValue
	@Column(name = "ORDER_ITEM_ID")
	private Long id;
	
	@Column(name = "ORDER_ID")		// Order.java에 ORDER_ID와 FK관계
	private Long orderId;	
	
	@Column(name = "ITEM_ID")		// Item.java에 ITEM_ID와 FK관계
	private Long itemId;
	
	private int orderPrice;
	private int count;
	
}
✔️ Item.java
@Entity
@Getter @Setter
public class Item {
	
	@Id @GeneratedValue
	@Column(name = "ITEM_ID")
	private Long id;
    
	private String name;
	private int price;
	private int stockQuantity;
}
✔️ JpaMain.java <- JPA 실행을 위한 main클래스
public class JpaMain {
	public static void main(String[] args) {
		EntityManagerFactory emf = Persistence.createEntityManagerFactory("hello");
		EntityManager em = emf.createEntityManager();
		EntityTransaction tx = em.getTransaction();
		tx.begin();
		
		try {
        	tx.commit();
		} catch (Exception e) {
			tx.rollback();
		}finally {
			em.close();
			emf.close();
		}
	}
    
✔️ 클래스에서 화면 우클릭 > Run As > Java Application으로 실행하기


✔️ Member.java
@Entity
@Getter @Setter
public class Member {
	@Id @GeneratedValue
	@Column(name = "MEMBER_ID")
	private Long id;
	
	@Column(name = "USERNAME")
	private String name;
    
// 	FK 키 설정 전
//	@Column(name = "TEAM_ID")
//	private Long teamid;	
	
//  FK 키 설정
	@ManyToOne
	@JoinColumn(name = "TEAM_ID")  //  <- Team.java에 TEAM_ID와 연결된다
	private Team team;
}
✔️ Team.java
@Entity
@Getter @Setter
public class Team {
	@Id @GeneratedValue
	@Column(name = "TEAM_ID")	
	private Long id;
	private String name;
}
✔️ JpaMain.java
public class JpaMain {
	public static void main(String[] args) {
		EntityManagerFactory emf = Persistence.createEntityManagerFactory("hello");
		EntityManager em = emf.createEntityManager();
		EntityTransaction tx = em.getTransaction();
		tx.begin();
        
		try {
			Team team = new Team();
			team.setName("TeamA");
			
			// -> persist하면 영속상태가 된다.
			// 영속상태가 될 때, PK의 값이 세팅이 된 후에 영속상태가 된다.
			// Team을 먼저 생성해서 PK를 생성해야 FK를 생성할 수 있다.
			em.persist(team); 
			
			Member member = new Member();
			member.setName("member1");
			// FK인 Member 에서 PK 객체인 Team을 통째로 가져온다. 
			member.setTeam(team);
	        em.persist(member);
	        
	        
	        //강제 db 쿼리를 보고 싶을 때
	        em.flush();
	        em.clear();
	        
	        //select
	        // find시에 1차캐시에서 가지고 와서 select문이 없다.
	        Member findmember = em.find(Member.class, member.getId());
	        // Member에서 Team 객체를 통째로 가져온다.
	        Team findTeam = findmember.getTeam();
	        
	                
			tx.commit(); 	// 영속성 컨텍스트에 들어가 테이블 생성
			} catch (Exception e) {
				tx.rollback();
			}finally {
				em.close();
				emf.close();
			}
		}
✔️ DB - Table 생성

- 테이블 연관관계
 
- 관계 1개
- Member 테이블 입장에서 Team 테이블 조인 가능
- Team 테이블 입장에서 Member 테이블 조인 가능
- 객체 연관관계
 
- 관계 2개
- Member 객체에서 Team 객체로 연관관계 1개(단방향)
- Team 객체에서 Member 객체로 연관관계 1개(단방향)
- 사실은 단방향 연관관계가 2개 있는 것이다.
- 관리의 딜레마
 
- 둘 중 하나로 외래키를 관리해야 한다.
- Member에서 Team으로 가는 team 참조 값과, Team에서 Member로 가는 members 참조 값이 있다.
- Member에서 Team값이 수정 되었을 때 Member table의 TEAM_ID가 수정되야 하는지, Team에 있는 members를 수정했을 때 Member table의 TEAM_ID가 수정되야 하는지?
- DB입장에서는 Member table에 있는 TEAM_ID만 update되면 된다. ->룰(주인)이 생긴다.
- 연관관계의 주인(Owner) - 양방향 매핑 규칙
 
- 객체의 두 관계중 하나를 연관관계의 주인으로 지정
- 연관관계의 주인만이 외래 키를 관리(등록, 수정)
- 주인이 아닌쪽은 읽기만 가능
- 주인은 mappedBy 속성을 사용X
->mappedBy: 내가 누군가에 의해서 mapping되었다 라는 뜻
- 주인이 아니면 mappedBy 속성으로 주인 지정
✔️ Team.java
@Entity
@Getter @Setter
public class Team {
	@Id @GeneratedValue
	@Column(name = "TEAM_ID")
	private Long id;
	private String name;
	
	/* team에 의해서 관리가 된다.
	mappedBy가 적힌 곳은 읽기만 가능하다.
	값을 넣어봐야 아무일도 벌어지지 않는다.
	대신 조회는 가능
	*/
	@OneToMany(mappedBy = "team")	//**
	private List<Member> member = new ArrayList<Member>();
	
	public void addMember(Member member) {
		member.setTeam(this);
		this.member.add(member);
	}
}

✔️ JpaMain.java
public class JpaMain {
	public static void main(String[] args) {
		EntityManagerFactory emf = Persistence.createEntityManagerFactory("hello");
		EntityManager em = emf.createEntityManager();
		EntityTransaction tx = em.getTransaction();
		tx.begin();
		
		try {
  			Team team = new Team();
			team.setName("TeamA");
			
			// -> persist하면 영속상태가 된다.
			// 영속상태가 될 때, PK의 값이 세팅이 된 후에 영속상태가 된다.
			// Team을 먼저 생성해서 PK를 생성해야 FK를 생성할 수 있다.
			em.persist(team); 
			
			Member member = new Member();
			member.setName("member1");
			// FK인 Member 에서 PK 객체인 Team을 통째로 가져온다. 
			//member.setTeam(team);
	        em.persist(member);
	        	        
	        //강제 db 쿼리를 보고 싶을 때
	       
	        em.flush();	 // DB에 넣어준다.
	        em.clear();  // 영속성 컨텍스트에 가지고 있던 crud구문을 비워준다.
            
			//============================================================
			// 양방향 매핑
	        Member findSideMember = em.find(Member.class, member.getId());
	        List<Member> members = findmember.getTeam().getMember();
	        
	        for(Member m : members) {
	        	System.out.println("result1 = " + m.getName());
	        }
	        //============================================================
	        
			tx.commit(); // commit하면 영속성 컨텍스트에 들어가기때문에 여기서 테이블 생성
		} catch (Exception e) {
			tx.rollback();
		}finally {
			em.close();
			emf.close();
		}
	}
}
- 양방향 연관관계 주의
 
- 순수 객체 상태를 고려해서 항상 양쪽에 값을 설정하자
- 연관관계 편의 메소드를 생성하자
- 양방향 매핑시에 무한 루프 조심하자
-> toString(), lombok lib 조심할 것
- 양방향 매핑 정리
 
- 단방향 매핑만으로도 이미 연관관계 매핑은 완료
- 양방향 매핑은 반대 방향으로 조회기능이 추가 된 것 뿐.
- 양방향 사용 이유 : JPQL에서 역방향으로 탐색할 일이 많음
- 단방향 매핑을 잘 하고 양방향은 필요할 때 추가해도 됨(테이블에 영향을 주지 않음)
- 결론 : 객체입장에서 양방향 매핑은 필수는 아님, 필요 시에 그때 생성해도 늦지 않는다.
- 연관관계의 주인을 정하는 기준
 
- 비지니스 로직을 기준으로 연관관계의 주인을 선택하면 안됨
- 연관관계의 주인은 외래 키의 위치를 기준으로 정해야함
✔️ Item.java
@Entity
@Getter @Setter
public class Item {
	
	@Id @GeneratedValue
	@Column(name = "ITEM_ID")
	private Long id;
	
	@OneToMany(mappedBy = "item")
	private List<OrderItem> orderItem = new ArrayList<OrderItem>();
	
	public void addOrderItem(OrderItem orderItem) {
		orderItem.setItem(this);
		this.orderItem.add(orderItem);
	}
	
	private String name;
	private int price;
	private int stockQuantity;
}
✔️ Member.java
@Entity
@Getter @Setter
public class Member {
	@Id @GeneratedValue
	@Column(name = "MEMBER_ID")
	private Long id;
	
	private String name;
	private String city;
	private String street;
	private String zipcode;
	
	
	@OneToMany(mappedBy = "member")
	private List<Order> order = new ArrayList<Order>();
	
	public void addMember(Order order) {
		order.setMember(this);
		this.order.add(order);
	}
}
✔️ Order.java
@Entity
@Table(name = "ORDERS")
@Getter @Setter
public class Order {
	@Id @GeneratedValue
	@Column(name = "ORDER_ID")
	private Long id;
	
	@OneToMany(mappedBy = "order")
	private List<OrderItem> orderItem = new ArrayList<OrderItem>();
	
	public void addOrderItem(OrderItem orderItem) {
		orderItem.setOrder(this);
		this.orderItem.add(orderItem);
	}
	
//	@Column(name = "MEMBER_ID")
//	private Long memberId;
	
	@ManyToOne
	@JoinColumn(name = "MEMBER_ID")
	private Member member;
	
	
	private LocalDateTime orderDate;
	private String status;
}
✔️ OrderItem.java
@Entity
@Setter @Getter
public class OrderItem {
	@Id @GeneratedValue
	@Column(name = "ORDER_ITEM_ID")
	private Long id;
	
	
	@ManyToOne
	@JoinColumn(name = "ORDER_ID")
	private Order order;
	
	
//	@Column(name = "ORDER_ID")
//	private Long orderId;
	
//	@Column(name = "ITEM_ID")
//	private Long itemId;
	
	@ManyToOne
	@JoinColumn(name ="ITEM_ID")
	private Item item;
	
	private int orderprice;
	private int count;
}