묻고 답해요
141만명의 커뮤니티!! 함께 토론해봐요.
인프런 TOP Writers
-
미해결자바 ORM 표준 JPA 프로그래밍 - 기본편
강의자료와 실제 생성 테이블이 다르고, Address가 값 객체일 수 없다고 생각합니다.
[질문 템플릿]1. 강의 내용과 관련된 질문인가요? 예2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? 예3. 질문 잘하기 메뉴얼을 읽어보셨나요? 예[질문 내용]안녕하세요. 김영한님의 강의를 잘 보고 있습니다. 강의를 보던도중, 문득 의문점이 들어서 여쭤보고자 질문을 작성하게 되었습니다. 질문의 테마는 값 타입 컬렉션과 기본키라고 할 수 있겠네요.기본 지식테이블은 기본키가 있을수도, 없을수도 있다.제가 배운대로는, 테이블은 기본키가 존재할 수도 있고 존재하지 않을 수도 있다고 배웠습니다. 그리고 기본키를 두는 이유는 기본키가 겹치지 않도록 해서, 데이터 중복을 막고, 조회 시 효율 증가를 위해서라고 생각했습니다. 김영한님의 강의에서 말하는 값타입은 주소가 다르더라도 안에 있는 값이 모두 같다고 하신걸로 이해했습니다.그래서 자바 객체가 값타입으로 들어가는 경우에는 equals를 통해서 같은지를 비교한다는 것도요!! 김영한님의 강의 중 예제로 들어주셨던 Member의 favoriteFoods, addressHistory는 값 타입을 데이터베이스 테이블로 변환한 예시로 이해했습니다.그리고 강의 내용에서 JPA를 이용해서 Table 구조를 생성하는 걸로 이해했습니다. 여기까지가 제가 이해한 내용입니다. 저는 그래서 해당 구조로 데이터베이스를 만들어준다고 인지했고, FAVORITE_FOOD, ADDRESS는 각각 중복값이 들어갈 수없다고 생각했습니다. 문제상황하지만 테이블의 생성 내용을 보면, 기본키 설정 부분이 빠져 있습니다.외래키 매핑만 되어 있고 실제로 기본키 부분이 빠져있습니다.제가 만든, ADDRESS 테이블을 예시로 들면,이는, FAVORITE_FOOD 도 동일합니다. 정말 중복값이 들어갈 수 없는지 테스트해보았습니다.테스트를 위한 코드는 다음과 같습니다.Address address = new Address("newCity", "street", "10000"); Member member1 = new Member(); member1.setName("member1"); member1.setHomeAddress(address); member1.getFavoriteFoods().add("치킨"); member1.getFavoriteFoods().add("치킨"); member1.getFavoriteFoods().add("치킨"); member1.getFavoriteFoods().add("피자"); member1.getFavoriteFoods().add("족발"); Address oldAddress = new Address("oldCity3", "street", "10000"); member1.getAddressList().add(new Address("oldCity", "street", "10000")); member1.getAddressList().add(new Address("oldCity2", "street", "10000")); member1.getAddressList().add(new Address("oldCity3", "street", "10000")); member1.getAddressList().add(new Address("oldCity3", "street", "10000")); member1.getAddressList().add(new Address("oldCity3", "street", "10000")); em.persist(member1); 결과값은 다음과 같습니다.값을 보게되면, FAVORITE_FOOD의 경우는 Set 자료구조 사용으로 중복값이 들어갈 수 없는 것이고, ADDRESS의 경우는 중복값이 들어갈 수 있었습니다. 만약 값의 변경이 일어나는 경우에는 어떻게 될까? 하는 고민이 생겨, 중복으로 들어있는 내용의 값을 변경해보았습니다.Address address = new Address("newCity", "street", "10000"); Member member1 = new Member(); member1.setName("member1"); member1.setHomeAddress(address); member1.getFavoriteFoods().add("치킨"); member1.getFavoriteFoods().add("치킨"); member1.getFavoriteFoods().add("치킨"); member1.getFavoriteFoods().add("피자"); member1.getFavoriteFoods().add("족발"); Address oldAddress = new Address("oldCity3", "street", "10000"); member1.getAddressList().add(new Address("oldCity", "street", "10000")); member1.getAddressList().add(new Address("oldCity2", "street", "10000")); member1.getAddressList().add(new Address("oldCity3", "street", "10000")); member1.getAddressList().add(new Address("oldCity3", "street", "10000")); member1.getAddressList().add(new Address("oldCity3", "street", "10000")); em.persist(member1); em.flush(); em.clear(); Member findMember = em.find(Member.class, member1.getId()); System.out.println("================== Start 2 =================="); findMember.getAddressList().remove(oldAddress); findMember.getAddressList().add(new Address("newCity1", "street", "10000")); tx.commit(); 결과값은 다음과 같습니다.중복값을 한번에 지워준다면, 그래도 결과적으로는 ADDRESS값을 중복이 없는 값객체로 쓸 수 있겠다고 생각했지만, 모두 지우지 않고 중복값을 하나만 지웠습니다.물론 List의 특성 상 중복 값 한개만 지우는게 당연하지만요. 가설목표하던 테이블 구조로 실제로 만들어지지 않았다고 생각했습니다. -> 기본키가 없다.왜냐하면 생성하고자 하는 테이블 구조와 생성된 테이블 구조가 다르기 때문입니다.음식에서 중복이 생기지 않는 이유는 Set의 특성 때문이지 테이블 때문이 아니라고 생각이 들었습니다. 값 객체의 특성 상 중복을 허용하는 경우는 없다.좋아하는 음식의 경우 같은 음식이 두번 있을 이유는 없지만, 이전의 주소의 경우는 같은 주소에 두번 이사갈 수 있다.그렇다면 음식과 다르게 주소의 경우는 중복이 가능하고, 값을 추적할 수 있어야 하므로 Entity로 사용하는게 맞지 않을까요?이 부분은 김영한님깨서 설명해주신 부분과 일치하지만, 결론까지 도달한게 맞는지 궁금합니다. 두서 없이 길게 적은 것 같은데, 제가 생각한 가설이 맞는지가 궁금합니다. 그리고 나아가 가설까지 도달하는 방식에 문제가 있거나 고칠점이 있다고 피드백도 부탁드립니다. 읽어주셔서 감사합니다.
-
미해결자바 ORM 표준 JPA 프로그래밍 - 기본편
기본키와 관련하여 질문드릴게요!.
@Entity@Getter@Setter@NoArgsConstructor(access = AccessLevel.PROTECTED)public class Bbs { @Id @GeneratedValue(strategy = GenerationType.SEQUENCE) @Column(name = "BBS_NO") private Long bbsNo; //bbs기본키 private String bbsTitle; private String bbsContent; private String bbsDate; @ColumnDefault("0") private Integer bbsHit; private String bbsNotice; private String bbsSecret; @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "MEMBER_ID") private Member member; @OneToMany(mappedBy = "bbs") List<Comment> comments = new ArrayList<>(); public void addMember(Member member){ this.member=member; member.getBbs().add(this); } public Bbs(String bbsTitle, String bbsContent, String bbsDate, Integer bbsHit, String bbsNotice, String bbsSecret, Member member) { this.bbsTitle = bbsTitle; this.bbsContent = bbsContent; this.bbsDate = bbsDate; this.bbsHit = bbsHit; this.bbsNotice = bbsNotice; this.bbsSecret = bbsSecret; this.member = member; } public void updateBbs(Long bbsNo,String bbsTitle, String bbsContent, String bbsDate, Integer bbsHit, String bbsNotice, String bbsSecret) { this.bbsTitle = bbsTitle; this.bbsContent = bbsContent; this.bbsDate = bbsDate; this.bbsNotice = bbsNotice; this.bbsSecret = bbsSecret; }} 위에 코드가 bbs기본키 전략이고. @Entity@Getterpublic class Comment { @Id @GeneratedValue(strategy = GenerationType.SEQUENCE) @Column(name = "COMMENT_NO") private Long commentId; //comment 기본키 private String content; @ColumnDefault("0") private int commentCnt; //대댓글시 정렬을 위해 사용 @ColumnDefault("0") private int commentGroup; private String Date; @ColumnDefault("0") private int commentSequence; @ColumnDefault("0") private int level; @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "BBS_NO") private Bbs bbs; @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "MEMBER_ID") private Member member; public Comment() { } public Comment(String content, int commentCnt, int commentGroup, String date) { this.content = content; this.commentCnt = commentCnt; this.commentGroup = commentGroup; this.Date = date; } public void addMember(Member member){ this.member=member; member.getComments().add(this); } public void addBbs(Bbs bbs){ this.bbs=bbs; bbs.getComments().add(this); }} 이게 코맨트(댓글) 기본키 전략입니다. 위에 사진을 보면 bbs_no이랑 commemt_no이랑 기본키가 같이 올라갑니다..... 제가 원하는건 bbs_no 도 1부터 증가하고 comment_no도 1부터 증가하게 하고싶은데 따로 기본키 설정을 해주었는데 왜 같이 올라가는지 잘 모르겠습니다. 강의나,JPA 기본키 전략을 다시 보아도 해결책을 찾이 못해 질문 드립니다.
-
미해결데이터베이스 중급(Modeling)
Primary Key 선정 기준
안녕하세요, 강의 잘 듣고 있습니다 Primary Key 지정할 때 Unique와 Not Null 두가지가 중요하다고 말씀해 주셨는데요 1. 레코드 최대 수가 int 형 범위 이내이면 굳이 Primary Key 선정에 대해 고민을 안하고 모든 테이블 Primary Key를 id (int형 자동증가)로 설정해도 되나요? 2. 실무에서 id(int 형 자동증가) 로 쓰는 경우가 많은 가요? 3. 수강신청시스템의 경우 학번으로 primary key 지정 vs id(int형 자동증가) 지정 어떤 장단점이 있는지 궁금합니다. 감사합니다!