You are viewing an old version of this page. View the current version.

Compare with Current View Page History

« Previous Version 6 Next »

연관있는 두 테이블이 다른 복합키로 지정이 되어 있으며, 외래키 설정이 없을때

두가지 상황으로 볼수 있습니다.

  • 설계상의 문제 : 무결성을 지킬필요가 있어 외래키가 설정이 요구되나, 무시한경우
  • 의도된 상황 : 무결성을 지킬필요없는 로그성및 통계성

관련 영문 키워드:

mapping compositekey primary and non forign


샘플 DDL

유니크 : itemono + itemtype 은 테이블내에서 유일합니다.

ItemlInfo

CREATE TABLE `db_example2`.`iteminfo` (
  `itemtype` CHAR(1) NOT NULL,
  `itemno` INT NOT NULL,
  `itemname` VARCHAR(45) NULL,
  PRIMARY KEY (`itemtype`, `itemno`));


ItemStatics

CREATE TABLE `itemstatics` (
  `itemtype` char(1) NOT NULL,
  `itemno` int(11) NOT NULL,
  `viewcnt` int(11) DEFAULT NULL,
  `salecnt` int(11) DEFAULT NULL,
  `statictype` varchar(45) NOT NULL,
  PRIMARY KEY (`itemtype`,`itemno`,`statictype`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8

ItemStatic에서도 itemtype와 itemno둘만으로 유니크하기때문에 둘만 걸어도 되지만,3개가 걸려있습니다.

성능계에서는 클러스터인덱스의 효과를보기위해 실제 몇가지를 필드하나를 더 키로 거는경우도 있습니다.

하지만 대부분 데이터량과 선택도를 고려하지않고 무부분별하게 걸려있는 경우가 많으며

유용한 검색기능을 추가하는과정에서, 유니크한 키조건을 개선하는것은 이 주제에서 할수 없는것입니다.


JPA에서는 실제 유니크키한 값을, 엔티티를 구분하는 값으로 사용할것이며

ItemId(itemtype,itemno) 만을 정의하여, 조인 전략을 사용할것입니다.

동일한 엔티티를 판별하는 해시체크는 JPA에서도 중요하며

어플리케이션에서는 이러한 해시조건이 복잡해진다고 좋을것이 없기때문입니다.


Entity 설계

복합키정의

import javax.persistence.Column;
import javax.persistence.Embeddable;

@Embeddable
public class ItemId implements Serializable {
	
	@Column(columnDefinition="char(7)")
	private String	itemtype;
	private int		itemno;
	
    public ItemId() {

    }
	
    public ItemId(String itemtype, int itemno) {
        this.itemtype = itemtype;
        this.itemno = itemno;
    }
	
	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = itemtype.hashCode() + itemno;
		return result;
	}
 
	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		ItemId other = (ItemId) obj;
		if (itemtype == null) {
			if (other.itemtype != null)
				return false;
		} else if (!itemtype.equals(other.itemtype))
			return false;
		if (itemno != other.itemno)
			return false;
		return true;
	}
	
	public String getItemtype() {
		return itemtype;
	}
	public void setItemtype(String itemtype) {
		this.itemtype = itemtype;
	}
	public int getItemno() {
		return itemno;
	}
	public void setItemno(int itemno) {
		this.itemno = itemno;
	}

}


아이템통계

import javax.persistence.EmbeddedId;
import javax.persistence.Entity;

@Entity
public class ItemStatics {
	@EmbeddedId 
	ItemId staticid;
	
	int viewcnt;
}



아이템정보

import javax.persistence.Column;
import javax.persistence.EmbeddedId;
import javax.persistence.Entity;
import javax.persistence.JoinColumn;
import javax.persistence.JoinColumns;
import javax.persistence.ManyToOne;
import javax.persistence.MapsId;

@Entity
public class ItemInfo {
	
	@EmbeddedId 
	ItemId itemid;
	
	String itemname;
	
    @MapsId("staticid") //references EmbeddedId's property
    @JoinColumns({
        @JoinColumn( insertable = false, updatable = false,
            name = "itemtype",
            referencedColumnName = "itemtype"),
        @JoinColumn( insertable = false, updatable = false,
            name = "itemno",
            referencedColumnName = "itemno")
    })
    @ManyToOne
    private ItemStatics statics;

}


조회하기(조인기능 탑재)

	@Autowired
	ItemInfoRepository itemRepo;
	
	public void allTest() {
		itemRepo.findAll().forEach(item -> {
			String itemString = String.format("%s %d",item.getItemname() ,item.getStatics().getViewcnt() );			
			System.out.println(itemString);			
		});		
	}

조인문을 사용하지않고(실제는 조인문이 발생함), 각각의 다른테이블에 존재하는

아이템정보와 아이템통계의 참조를 얻어서 뷰카운트를 객체지향적 방법으로 조회를 하였습니다.

사용된 데이터>

ItemInfoItemStatics


결과>

T1 100
T2 200
T3 200




  • No labels