Spring Data JPA 진급 Specification 동적 조회

21959 단어 Spring
1 사양 동적 조회
때때로 우 리 는 특정한 실 체 를 조회 할 때 주어진 조건 이 고정 되 지 않 을 때 해당 하 는 조회 문 구 를 동적 으로 구축 해 야 한다. Spring Data JPA 에서 Jpa SpecificationExecutor 인 터 페 이 스 를 통 해 조회 할 수 있다.JPQL 보 다 는 타 입 이 안전 하고 대상 지향 적 이라는 장점 이 있다.
import java.util.List;

import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;

/**
 *	JpaSpecificationExecutor      
 **/
 public interface JpaSpecificationExecutor {
   	//          
 	T findOne(Specification spec);	
   	//        
 	List findAll(Specification spec);
   	//        
 	Page findAll(Specification spec, Pageable pageable);
   	//      
 	List findAll(Specification spec, Sort sort);
   	//    
 	long count(Specification spec);
}

Jpa SpecificationExecutor 에 대해 이 인 터 페 이 스 는 기본적으로 Specification 인 터 페 이 스 를 중심 으로 정 의 됩 니 다.Specification 구 조 는 검색 조건 이 라 고 간단하게 이해 할 수 있 습 니 다.
Specification 인터페이스 에 서 는 다음 과 같은 방법 만 정의 합 니 다.
    //      
    /**
    *	root	:Root  ,        ,    root        
    *	query	:          ,       
    *	cb		:      ,           
    **/
    public Predicate toPredicate(Root root, CriteriaQuery> query, CriteriaBuilder cb);

1.1 Specifications 를 사용 하여 조건 조회 완료
//    customerDao
@Autowired
private CustomerDao customerDao;	
@Test
public void testSpecifications() {
  	//          ,    Specification    ,   toPredicate  
	Specification  spec = new Specification() {
		public Predicate toPredicate(Root root, CriteriaQuery> query, CriteriaBuilder cb) {
			//cb:    ,         like:    
			//root:   Customer     custName      
			return cb.like(root.get("custName").as(String.class), "  %");
		}
	};
	Customer customer = customerDao.findOne(spec);
	System.out.println(customer);
}

1.2 Specifications 기반 페이지 조회
@Test
public void testPage() {
	//      
	Specification spec = new Specification() {
		public Predicate toPredicate(Root root, CriteriaQuery> query, CriteriaBuilder cb) {
			return cb.like(root.get("custName").as(String.class), "  %");
		}
	};
	
	/**
	 *       
	 * 		Pageable :   
	 * 			PageRequest   Pageable  ,           
	 * 				     :  ( 0  )
	 * 				     :      
	 */
	Pageable pageable = new PageRequest(0, 5);
	
	/**
	 *     ,   Spring Data Jpa    page bean
	 * 		    findAll             
	 * 			     :    Specification
	 * 			     :    
	 */
	Page page = customerDao.findAll(spec,pageable);
	
}

Spring Data JPA 의 페이지 별 조 회 는 내부 에서 자동 으로 이 루어 지 는 패 키 징 과정 으로 Spring Data JPA 가 제공 하 는 pageBean 대상 을 되 돌려 줍 니 다.그 중의 방법 은 다음 과 같다.
	 //     
	int getTotalPages();
	 //      	
	long getTotalElements();
	//      
	List getContent();

1.3 방법 대응 관계 방법 명칭 Sql 대응 관계
equle	filed = value
gt(greaterThan)	filed > value
lt(lessThan)	filed < value
ge(greaterThanOrEqualTo)	filed >= value
le(lessThanOrEqualTo)	filed <= value
notEqule	filed != value
like	filed like value
notLike	filed not like value

제2 장 다 표 디자인
2.1 표 간 의 관계 구분
데이터베이스 에 여러 표 사이 에 세 가지 관계 가 존재 한다. 다 대 다, 한 쌍 다 와 한 쌍 의 관계 이다.주의: 한 쌍 의 다 관 계 는 두 가지 로 볼 수 있 습 니 다. 즉, 한 쌍 이 많 고 한 쌍 이 많 습 니 다.그 러 니까 네 가지 가 더 정확 해.
명확: 우 리 는 오늘 실제 개발 에서 자주 사용 하 는 관련 관계, 한 쌍 이 많 고 여러 쌍 이 많다.1 대 1 의 경우, 실제 개발 에 서 는 거의 사용 되 지 않 는 다.
2.2 JPA 프레임 워 크 에서 표 관계 에 대한 분석 절차
실제 개발 에서 우리 데이터 뱅 크 의 표 는 서로 관련 관계 가 있 을 수 밖 에 없고 조작 표를 할 때 여러 장의 표 조작 과 관련 될 수 있다.이러한 ORM 사상 을 실현 하 는 구조 에서 (예 를 들 어 JPA) 우 리 는 실체 류 를 조작 함으로써 데이터 베이스 시트 에 대한 조작 을 실현 할 수 있다.그래서 오늘 우리 의 학습 중점 은 배치 실체 간 의 관련 관 계 를 파악 하 는 것 이다.
STEP 1: 먼저 두 장의 표 간 의 관 계 를 확인한다.
만약 관계 가 틀 렸 다 면, 뒤에서 하 는 모든 조작 은 정확 할 수 없 을 것 이다.
두 번 째 단계: 데이터베이스 에서 두 장의 표 의 관 계 를 실현 합 니 다.
세 번 째 단계: 실체 류 에서 두 실체의 관 계 를 묘사 합 니 다.
네 번 째 단계: 실체 클래스 와 데이터베이스 시트 의 관계 맵 설정 (중점)
3 JPA 중 에 한 쌍 이 많아 요.
3.1 예시 분석
우리 가 채택 한 예 는 고객 과 연락처 이다.
고객: 한 회 사 를 말 합 니 다. 우 리 는 A 로 기록 합 니 다.
연락처: A 회사 의 직원 을 말 합 니 다.
아르 바 이 트 를 고려 하지 않 고 회사 와 직원 의 관 계 는 한 쌍 이 많다.
3.2 표 관계 구축
한 쌍 의 다 중 관계 에서 우 리 는 한 쪽 을 위주 표 라 고 부 르 고 많은 쪽 을 종 표 라 고 부 르 는 습관 이 있다.데이터베이스 에 한 쌍 이상 의 관 계 를 맺 으 려 면 데이터베이스 의 외부 키 로 제약 을 받 아야 한다.
무엇이 외 키 입 니까?표 에 열 이 있 는 것 을 말 합 니 다. 값 은 메 인 표 의 메 인 키 를 참조 하고 이 열 은 바로 외 키 입 니 다.
다음 그림 과 같이 다 중 데이터베이스 관계 의 구축
3.3 실체 류 관계 구축 및 맵 설정
실체 류 에서 고객 이 적은 쪽 이기 때문에 여러 개의 연락 처 를 포함해 야 하기 때문에 실체 류 는 고객 중 여러 개의 연락 처 를 나타 내야 한다. 코드 는 다음 과 같다.
/**
 *       
 *          JPA   
 *         javax.persistence   
 */
@Entity//           
@Table(name="cst_customer")//                
public class Customer implements Serializable {
	
	@Id//           
	@GeneratedValue(strategy=GenerationType.IDENTITY)//         
	@Column(name="cust_id")//         cust_id   
	private Long custId;
	@Column(name="cust_name")//         cust_name   
	private String custName;
	@Column(name="cust_source")//         cust_source   
	private String custSource;
	@Column(name="cust_industry")//         cust_industry   
	private String custIndustry;
	@Column(name="cust_level")//         cust_level   
	private String custLevel;
	@Column(name="cust_address")//         cust_address   
	private String custAddress;
	@Column(name="cust_phone")//         cust_phone   
	private String custPhone;
	
    //              
  	@OneToMany(targetEntity=LinkMan.class)
	@JoinColumn(name="lkm_cust_id",referencedColumnName="cust_id")
	private Set linkmans = new HashSet(0);
	
	public Long getCustId() {
		return custId;
	}
	public void setCustId(Long custId) {
		this.custId = custId;
	}
	public String getCustName() {
		return custName;
	}
	public void setCustName(String custName) {
		this.custName = custName;
	}
	public String getCustSource() {
		return custSource;
	}
	public void setCustSource(String custSource) {
		this.custSource = custSource;
	}
	public String getCustIndustry() {
		return custIndustry;
	}
	public void setCustIndustry(String custIndustry) {
		this.custIndustry = custIndustry;
	}
	public String getCustLevel() {
		return custLevel;
	}
	public void setCustLevel(String custLevel) {
		this.custLevel = custLevel;
	}
	public String getCustAddress() {
		return custAddress;
	}
	public void setCustAddress(String custAddress) {
		this.custAddress = custAddress;
	}
	public String getCustPhone() {
		return custPhone;
	}
	public void setCustPhone(String custPhone) {
		this.custPhone = custPhone;
	}
	public Set getLinkmans() {
		return linkmans;
	}
	public void setLinkmans(Set linkmans) {
		this.linkmans = linkmans;
	}
	@Override
	public String toString() {
		return "Customer [custId=" + custId + ", custName=" + custName + ", custSource=" + custSource
				+ ", custIndustry=" + custIndustry + ", custLevel=" + custLevel + ", custAddress=" + custAddress
				+ ", custPhone=" + custPhone + "]";
	}
}

연락 처 는 많은 측 이기 때문에 실체 류 에서 나타 나 려 면 모든 연락 처 는 한 명의 고객 만 대응 할 수 있 고 코드 는 다음 과 같다.
/**
 *        (    )
 */
@Entity
@Table(name="cst_linkman")
public class LinkMan implements Serializable {
	@Id
	@GeneratedValue(strategy=GenerationType.IDENTITY)
	@Column(name="lkm_id")
	private Long lkmId;
	@Column(name="lkm_name")
	private String lkmName;
	@Column(name="lkm_gender")
	private String lkmGender;
	@Column(name="lkm_phone")
	private String lkmPhone;
	@Column(name="lkm_mobile")
	private String lkmMobile;
	@Column(name="lkm_email")
	private String lkmEmail;
	@Column(name="lkm_position")
	private String lkmPosition;
	@Column(name="lkm_memo")
	private String lkmMemo;

	//       :         
	@ManyToOne(targetEntity=Customer.class)
	@JoinColumn(name="lkm_cust_id",referencedColumnName="cust_id")
	private Customer customer;//     ,          
	
	public Long getLkmId() {
		return lkmId;
	}
	public void setLkmId(Long lkmId) {
		this.lkmId = lkmId;
	}
	public String getLkmName() {
		return lkmName;
	}
	public void setLkmName(String lkmName) {
		this.lkmName = lkmName;
	}
	public String getLkmGender() {
		return lkmGender;
	}
	public void setLkmGender(String lkmGender) {
		this.lkmGender = lkmGender;
	}
	public String getLkmPhone() {
		return lkmPhone;
	}
	public void setLkmPhone(String lkmPhone) {
		this.lkmPhone = lkmPhone;
	}
	public String getLkmMobile() {
		return lkmMobile;
	}
	public void setLkmMobile(String lkmMobile) {
		this.lkmMobile = lkmMobile;
	}
	public String getLkmEmail() {
		return lkmEmail;
	}
	public void setLkmEmail(String lkmEmail) {
		this.lkmEmail = lkmEmail;
	}
	public String getLkmPosition() {
		return lkmPosition;
	}
	public void setLkmPosition(String lkmPosition) {
		this.lkmPosition = lkmPosition;
	}
	public String getLkmMemo() {
		return lkmMemo;
	}
	public void setLkmMemo(String lkmMemo) {
		this.lkmMemo = lkmMemo;
	}	
	public Customer getCustomer() {
		return customer;
	}
	public void setCustomer(Customer customer) {
		this.customer = customer;
	}
	@Override
	public String toString() {
		return "LinkMan [lkmId=" + lkmId + ", lkmName=" + lkmName + ", lkmGender=" + lkmGender + ", lkmPhone="
				+ lkmPhone + ", lkmMobile=" + lkmMobile + ", lkmEmail=" + lkmEmail + ", lkmPosition=" + lkmPosition
				+ ", lkmMemo=" + lkmMemo + "]";
	}
}

3.4 매 핑 의 주해 설명
@OneToMany:
   	  :          
      :
    	targetEntityClass:            
    	mappedBy:                 。
    	cascade:          
    	fetch:          
    	orphanRemoval:        

@ManyToOne
      :        
      :
    	targetEntityClass:            
    	cascade:          
    	fetch:          
    	optional:      。     false,           。

@JoinColumn
       :                  。
       :
    	name:         
    	referencedColumnName:             
    	unique:    。      
    	nullable:      。     。
    	insertable:      。     。
    	updatable:      。     。
    	columnDefinition:      。

3.5 한 쌍 이상 의 조작
3.5.1 추가
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations="classpath:applicationContext.xml")
public class OneToManyTest {

	@Autowired
	private CustomerDao customerDao;
	
	@Autowired
	private LinkManDao linkManDao;
	
	
	/**
	 *     
	 *   :
	 * 	            
	 *   :
	 * 	                
	 *                (          )
	 *       ,      
	 *   :
	 *		               ,     ,      :
	 *		   2 insert 1 update.
	 * 		           2 insert。
	 *  
	 */
	@Test
	@Transactional  //    
	@Rollback(false)//      
	public void testAdd() {
		Customer c = new Customer();
		c.setCustName("TBD    ");
		c.setCustLevel("VIP  ");
		c.setCustSource("  ");
		c.setCustIndustry("    ");
		c.setCustAddress("       ");
		c.setCustPhone("010-84389340");
		
		LinkMan l = new LinkMan();
		l.setLkmName("TBD   ");
		l.setLkmGender("male");
		l.setLkmMobile("13811111111");
		l.setLkmPhone("010-34785348");
		l.setLkmEmail("[email protected]");
		l.setLkmPosition("  ");
		l.setLkmMemo("   ");

		c.getLinkMans().add(l);
		l.setCustomer(c);
		customerDao.save(c);
		linkManDao.save(l);
	}
}

저 장 된 사례 를 통 해 우 리 는 양 방향 관 계 를 설정 한 후에 두 개의 insert 문 구 를 보 내 고 불필요 한 update 문 구 를 보 내 는 것 을 알 수 있 습 니 다. 그러면 우리 의 해결 은 생각 이 매우 간단 하고 한 측 이 유지 권 을 포기 하 는 것 입 니 다.
	/**
	 *                 
	 */
    //@OneToMany(targetEntity=LinkMan.class)
//@JoinColumn(name="lkm_cust_id",referencedColumnName="cust_id")	
//               
	@OneToMany(mappedBy="customer")

3.5.2 삭제
	@Autowired
	private CustomerDao customerDao;
	
	@Test
	@Transactional
	@Rollback(false)//      
	public void testDelete() {
		customerDao.delete(1l);
	}

삭제 작업 에 대한 설명 은 다음 과 같 습 니 다.
표 데이터 삭제: 언제든지 임의로 삭제 할 수 있 습 니 다.
메 인 테이블 데이터 삭제:
* 61557 은 표 데이터 1 에서 기본 적 인 상황 에서 외부 키 필드 를 null 로 설정 한 다음 에 메 인 표 데 이 터 를 삭제 합 니 다.데이터베이스 의 표 구조 에 있어 서 외부 키 필드 에 빈 제약 이 있 으 면 기본 적 인 상황 이 잘못 보 고 됩 니 다.2. 관련 관 계 를 유지 할 권 리 를 포기 하면 삭제 할 수 없습니다. (외부 키 필드 가 null 로 허용 되 는 지 여부 와 관계 가 없습니다) 삭제 할 때 표 의 외부 키 필드 를 업데이트 하지 않 기 때 문 입 니 다.3. 삭제 하려 면 직렬 연결 을 사용 하여 참조 삭제
 표 데이터 참조 없 음: 마음대로 삭제
실제 개발 중, 등급 삭제 신중하게 사용 하 세 요!(한 쌍 이 많은 상황 에서)
3.5.3 레벨 연결 조작
연결 작업: 대상 을 조작 하 는 동시에 관련 대상 을 조작 하 는 것 을 말한다.
사용 방법: 작업 주체 의 주해 에 캐 스 케 이 드 만 설정 하면 됩 니 다.
/**
 * cascade:      
 * 		CascadeType.MERGE	    
 * 		CascadeType.PERSIST	    :
 * 		CascadeType.REFRESH     :
 * 		CascadeType.REMOVE	    :
 * 		CascadeType.ALL		    
 */
@OneToMany(mappedBy="customer",cascade=CascadeType.ALL)

4 JPA 중 에 다 대 다.
4.1 예시 분석
우리 가 채택 한 예 는 사용자 와 역할 이다.
사용자: 우리 반 의 모든 학우 들 을 말 합 니 다.
역할: 우리 반 친구 들 의 신분 정 보 를 말 합 니 다.
예 를 들 어 A 학생 은 제 학생 입 니 다. 그 중 에 한 신분 이 학생 입 니까? 아니면 집안 의 아이 입 니까? 그러면 그 는 자녀 입 니 다.
이 동시에 B 학생 은 학생 과 자녀의 신분 도 가진다.
그러면 어떤 학우 도 여러 가지 신분 을 가 질 수 있다.동시에 학생 이라는 신분 은 여러 학우 에 의 해 가 질 수 있다.
그래서 우 리 는 사용자 와 캐릭터 간 의 관계 가 많 고 많다 고 말한다.
4.2 표 관계 구축
여러 쌍 의 표 관 계 를 구축 하 는 것 은 중간 표 이다. 그 중에서 사용자 표 와 중간 표 의 관 계 는 한 쌍 이 많 고 캐릭터 표 와 중간 표 의 관계 도 한 쌍 이 많다. 다음 그림 과 같다.
4.3 실체 류 관계 구축 및 맵 설정
한 사용자 가 여러 개의 역할 을 가 질 수 있 기 때문에 사용자 실체 류 에 여러 개의 역할 의 정 보 를 포함해 야 한다. 코드 는 다음 과 같다.
/**
 *        
 */
@Entity
@Table(name="sys_user")
public class SysUser implements Serializable {
	
	@Id
	@GeneratedValue(strategy=GenerationType.IDENTITY)
	@Column(name="user_id")
	private Long userId;
	@Column(name="user_code")
	private String userCode;
	@Column(name="user_name")
	private String userName;
	@Column(name="user_password")
	private String userPassword;
	@Column(name="user_state")
	private String userState;
	
	//       
	@ManyToMany(mappedBy="users")
	private Set roles = new HashSet(0);
	
	public Long getUserId() {
		return userId;
	}
	public void setUserId(Long userId) {
		this.userId = userId;
	}
	public String getUserCode() {
		return userCode;
	}
	public void setUserCode(String userCode) {
		this.userCode = userCode;
	}
	public String getUserName() {
		return userName;
	}
	public void setUserName(String userName) {
		this.userName = userName;
	}
	public String getUserPassword() {
		return userPassword;
	}
	public void setUserPassword(String userPassword) {
		this.userPassword = userPassword;
	}
	public String getUserState() {
		return userState;
	}
	public void setUserState(String userState) {
		this.userState = userState;
	}
	public Set getRoles() {
		return roles;
	}
	public void setRoles(Set roles) {
		this.roles = roles;
	}
	@Override
	public String toString() {
		return "SysUser [userId=" + userId + ", userCode=" + userCode + ", userName=" + userName + ", userPassword="
				+ userPassword + ", userState=" + userState + "]";
	}
}

한 캐릭터 가 여러 사용자 에 게 부여 할 수 있 기 때문에 캐릭터 실체 류 에 여러 사용자 의 정 보 를 포함해 야 한다. 코드 는 다음 과 같다.
/**
 *        
 */
@Entity
@Table(name="sys_role")
public class SysRole implements Serializable {
	
	@Id
	@GeneratedValue(strategy=GenerationType.IDENTITY)
	@Column(name="role_id")
	private Long roleId;
	@Column(name="role_name")
	private String roleName;
	@Column(name="role_memo")
	private String roleMemo;
	
	//       
	@ManyToMany
	@JoinTable(name="user_role_rel",//      
			  //   user_role_rel    sys_role      role_id
			  joinColumns={@JoinColumn(name="role_id",referencedColumnName="role_id")},
			  //   user_role_rel     sys_user    user_id
			  inverseJoinColumns={@JoinColumn(name="user_id",referencedColumnName="user_id")}
	)
	private Set users = new HashSet(0);
	
	
	public Long getRoleId() {
		return roleId;
	}
	public void setRoleId(Long roleId) {
		this.roleId = roleId;
	}
	public String getRoleName() {
		return roleName;
	}
	public void setRoleName(String roleName) {
		this.roleName = roleName;
	}
	public String getRoleMemo() {
		return roleMemo;
	}
	public void setRoleMemo(String roleMemo) {
		this.roleMemo = roleMemo;
	}
	public Set getUsers() {
		return users;
	}
	public void setUsers(Set users) {
		this.users = users;
	}
	@Override
	public String toString() {
		return "SysRole [roleId=" + roleId + ", roleName=" + roleName + ", roleMemo=" + roleMemo + "]";
	}
}

4.4 매 핑 의 주해 설명
@ManyToMany
	  :         
	  :
		cascade:      。
		fetch:          。
    	targetEntity:        。           。

@JoinTable
      :        
      :
    	nam:        
    	joinColumns:                        			  			
    	inverseJoinColumn:                  
    	
@JoinColumn
      :                  。
      :
    	name:         
    	referencedColumnName:             
    	unique:    。      
    	nullable:      。     。
    	insertable:      。     。
    	updatable:      。     。
    	columnDefinition:      。

4.5 여러 쌍 의 조작
4.5.1 저장
    @Autowired
	private UserDao userDao;
	
	@Autowired
	private RoleDao roleDao;
	/**
	 *   :
	 * 	       
	 *   :
	 * 	  2    3   
	 * 	 1     1  2   (   )
	 * 	 2     2  3   (   )
	 *         
	 *   :
	 *      ,          ,                 。
	 *     :
	 * 	                
	 */
	@Test
	@Transactional  //    
	@Rollback(false)//      
	public void test1(){
		//    
		SysUser u1 = new SysUser();
		u1.setUserName("  1");
		SysRole r1 = new SysRole();
		r1.setRoleName("  1");
		//      
		u1.getRoles().add(r1);
		r1.getUsers().add(u1);
		//  
		roleDao.save(r1);
		userDao.save(u1);
	}

다 중 (저장) 에서 쌍방 이 관 계 를 설정 하면 쌍방 이 모두 중간 표를 유지 하고 중간 표 에 데 이 터 를 삽입 하 는 것 을 의미 합 니 다. 중간 표 의 2 개의 필드 는 연합 메 인 키 이기 때문에 오 류 를 보고 하고 메 인 키 가 중복 되 며 저장 실패 문 제 를 해결 합 니 다. 어느 한 측 에서 중간 표 에 대한 유지 권 을 포기 하면 됩 니 다. 수 동적 인 측 에서 포기 하 는 것 을 추천 합 니 다. 설정 은 다음 과 같 습 니 다.
//          ,            
@ManyToMany(mappedBy="roles")
private Set users = new HashSet(0);

4.5.2 삭제
	@Autowired
	private UserDao userDao;
	/**
	 *     
	 * 	        ,            
	 *   
	 *	      ,             ,         
	 */
	@Test
	@Transactional
	@Rollback(false)//      
	public void testDelete() {
		userDao.delete(1l);
	}

5 Spring Data JPA 의 다 중 표 조회
5.1 대상 탐색 조회
대상 도 내 비게 이 션 검색 방식 은 이미 불 러 온 대상 에 따라 그의 관련 대상 으로 내 비게 이 션 하 는 것 이다.그것 은 클래스 와 클래스 간 의 관 계 를 이용 하여 대상 을 검색 한다.예 를 들 어 저 희 는 ID 조회 방식 을 통 해 고객 을 찾 을 수 있 습 니 다. Customer 류 의 getLinkmans () 방법 으로 이 고객 의 모든 연락 처 를 얻 을 수 있 습 니 다.대상 내 비게 이 션 조회 의 사용 요 구 는 두 대상 사이 에 반드시 관련 관계 가 있어 야 한 다 는 것 이다.
고객 을 조회 하여 이 고객 의 모든 연락 처 를 가 져 옵 니 다.
@Autowired
private CustomerDao customerDao;

@Test
//    java     ,    no session  ,            
@Transactional 
public void testFind() {
	Customer customer = customerDao.findOne(5l);
	Set linkMans = customer.getLinkMans();//      
	for(LinkMan linkMan : linkMans) {
		System.out.println(linkMan);
	}
}

연락 처 를 조회 하여 이 연락처 의 모든 고객 을 가 져 옵 니 다.
@Autowired
private LinkManDao linkManDao;


@Test
public void testFind() {
	LinkMan linkMan = linkManDao.findOne(4l);
	Customer customer = linkMan.getCustomer(); //      
	System.out.println(customer);
}

대상 내 비게 이 션 조회 의 문제점 분석
문제 1: 우리 가 고객 을 조회 할 때 연락 처 를 조회 해 볼 까요?
분석: 만약 우리 가 조사 하지 않 는 다 면 사용 할 때 스스로 코드 를 쓰 고 방법 을 호출 하여 조회 해 야 한다.만약 우리 가 알 아 낸다 면, 사용 하지 않 을 때 또 서버 메모 리 를 헛되이 낭비 할 것 이다.
해결: 로드 지연 사상 을 사용 합 니 다.설정 을 통 해 우리 가 사용 해 야 할 때 진정한 조 회 를 시작 하도록 설정 합 니 다.
설정 방법:
/**
 *       @OneToMany     fetch  
 * 		FetchType.EAGER	:    
 * 		FetchType.LAZY	:    
 */
@OneToMany(mappedBy="customer",fetch=FetchType.EAGER)
private Set linkMans = new HashSet<>(0);

문제 2: 우리 가 연락 처 를 조회 할 때 고객 을 조회 해 낼 까요?
분석: 예 를 들 어 연락처 의 상세 한 정 보 를 조회 할 때 반드시 해당 연락처 의 소속 고객 을 볼 것 이다.만약 우리 가 조사 하지 않 는 다 면, 사용 할 때 는 스스로 코드 를 써 서 방법 을 호출 하여 조회 해 야 한다.만약 우리 가 알 아 낸다 면, 한 대상 은 너무 많은 메모 리 를 소모 하지 않 을 것 이다.그리고 대부분의 경우 우 리 는 사용 해 야 한다.
해결: 즉시 로드 하 는 사상 을 사용 합 니 다.설정 방식 을 통 해 표 의 실 체 를 조회 하면 메 인 표 의 실체 대상 을 동시에 찾 을 수 있 습 니 다.
구성 방식
/**
 *        @ManyToOne     fetch  
 * 		FetchType.EAGER	:    
 * 		FetchType.LAZY	:    
 */
@ManyToOne(targetEntity=Customer.class,fetch=FetchType.EAGER)
@JoinColumn(name="cst_lkm_id",referencedColumnName="cust_id")
private Customer customer;

5.2 Specification 조회 사용
/**
 * Specification     
 */
@Test
public void testFind() {
	Specification spec = new Specification() {
		public Predicate toPredicate(Root root, CriteriaQuery> query, CriteriaBuilder cb) {
			//Join      ,  root    
			//      ,               ,             (left,inner,right)
			//JoinType.LEFT :     ,JoinType.INNER:   ,JoinType.RIGHT:    
			Join join = root.join("customer",JoinType.INNER);
			return cb.like(join.get("custName").as(String.class),"  1");
		}
	};
	List list = linkManDao.findAll(spec);
	for (LinkMan linkMan : list) {
		System.out.println(linkMan);
	}
}

좋은 웹페이지 즐겨찾기