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

Compare with Current View Page History

« Previous Version 9 Next »

JPA Repositori를 통해 일반적인 검색 기능은 앞장에서 여러가지 샘플을 통해 살펴보았습니다.

이번장에서는 저장관점에서의 Repository 기능을 활용해보겠습니다.


JPA저장소는 읽기/저장/삭제가 모두되고, 최종 DB저장소의 반영까지 책임(트랜잭션처리)을 지는

양방향 영속성 객체이다라고 간단하게 정의 가능합니다.


JPA Repository

JPA를 사용하면 데이터베이스 사용을위해 어플리케이션 레이아웃에 영속성을 위한 저장소(Repository)를 잘 다뤄야합니다.

위 다이어그램에서는 JPA의 Proxy속성과 트랜젝션처리에대한 설명은 제외되어 실제 작동방식은 다를수 있으나

최종 저장소를 직접적으로 제어하지 않는다는것에서 Git저장소와 유사한 형태라고 보면 이해가 쉬울듯 합니다. 

JPA 저장소는 SQL직접호출 방식과 비교해 아래와 같은 특징이 있습니다.

  • 기존 SQL/SP를 직접 호출하여 값을 얻어 처리하는 방식은, 로컬에 반환된 값을 사용하고 버리는 상태가 필요없는 방식이며 매번 호출이 필요합니다.
  • 기존에는 상태가 없기때문에 데이터중심적 설계방식이였다고하면, JPA에서는 중간상태가 있기때문에  메시지 중심 설계 방식도 고려해야합니다.
  • JPA에서는 저장소를 통해, 같은 값을 다시 읽는것을 시도할때 SQL중복호출을 막고 효율적인 읽기전략을 수행할수 있습니다.(Proxy전략,캐싱전략)
  • JPA에서 쓰기전략은 어플리케이션 예외까지 트랜잭션영역에 포함할수 있으며, Repository에 임시저장후 원하는 타이밍에 실제 Update(Push)를 할수가 있습니다.

어플리케이션 도메인(서비스)레벨에서 많은 중복적인 코드작성(예를 들면 SP/SQL작성)의 시간을 줄이지만

반대로 저장소가 관계형 DB로부터 어느시점 SQL문을 호출하고 데이터가 동기화가 되는지 파악하려면

JPA의 특성과 더불어 관계형 DB의 특성을 같이 잘알고 있어야 상호운영이 가능합니다. ( 난이도 업 )

검색및 집계 처리(복습)

검색 함수쿼리

public interface AddressRepo extends CrudRepository<Address, Long>{
	
	List<Address> findBySex(String sex);
	
	List<Address> findBySex(String sex, Sort sort);
	
	List<Address> findBySexOrderByAgeDesc(String sex);
	
	List<Address> findByAgeGreaterThan(int age);
	
	List<Address> findByAgeGreaterThanEqual(int age);
		
	List<Address> findByAgeLessThan(int age);
		
	List<Address> findByAgeBetween(int low,int high);
	
	List<Address> findByAgeGreaterThanAndSex(int age,String sex);
	
	List<Address> findByAgeGreaterThanOrSex(int age,String sex);
		
	List<Address> findByAgeIn(int age[]);
}

JPQL을 사용한 집계처리

	@Query("select new com.example.demo.data.AddressStatistics(t.address,AVG(t.age)) from Address t where t.age > :minage GROUP BY t.address HAVING AVG(t.age) > :filterage ")
	List<AddressStatistics> findRegionAvgage(
			@Param("minage") int minage,
			@Param("filterage") double filterage
			);


Native 쿼리

	@Query(value="SELECT address,age,name,phoneNbr,sex FROM address " + 
			"UNION " + 
			"SELECT address,age,name,phoneNbr,sex FROM address2 ",
			nativeQuery = true)
	List<?> makeUniOn();


SQL 윈도우함수를 대체하는 랭킹처리

	public void RankTest() {		
	     int[] score = {Integer.MIN_VALUE};
	     int[] no = {0};
	     int[] rank = {0};	
	     List<AddressAgeRank> ageRankList =  
				addressRepo.findByAgeBetween(10, 90).stream()
				.sorted((a,b) -> b.getAge() - a.getAge() )
				.map(p -> {
		             ++no[0];
		             if (score[0] != p.getAge()) rank[0] = no[0];
		             return new AddressAgeRank(p.getName(),score[0] = p.getAge(),  rank[0] );					
				})
				.collect(Collectors.toList());
	     
	     ageRankList.forEach(item ->{
	    	 System.out.println(item.toString());	    	 
	     });	    
	}


QueryDSL 지원이되는 저장소

//인터페이스 선언부
public interface AddressRepoDSL extends JpaRepository<Address, Long>,
QueryDslPredicateExecutor<Address>{
	
}


//사용부
	@Autowired
	private AddressRepoDSL addressRepoDSL;
	public void jpa_queryDslTest() {
		
		QAddress	userAddress = QAddress.address1;
		BooleanBuilder builder = new BooleanBuilder();
		
		builder.and(userAddress.name.eq("민수1") )
			   .and(userAddress.address.like("%" + "서" +"%"));		
				
		Iterable<Address> addressList =  addressRepoDSL.findAll(builder);
		addressList.forEach( item -> {
			String itemString = String.format("%d%s %s %s %s %s",item.getId(),item.getName(),
					item.getPhoneNbr(), item.getSex(),item.getAddress(),item.getAge());
			System.out.println(itemString);
		});
		
	}


참고 원본문서:


데이터 입력

스토어 프로시져 이용

CREATE OR REPLACE FUNCTION addaddress(
	address character varying,
	age integer,	
	name character varying,
	sex character varying,
	phonenbr character varying, 
	OUT res int)
 
RETURNS integer AS $BODY$
	
	DECLARE
		address_id int;
	BEGIN 
		-- insert address
		
		INSERT INTO address ( address, age, name,sex,phonenbr) VALUES( address, age, name,sex,phonenbr);

		SELECT nextval('address_id') INTO res;
		--set res = address_id;		
 
	END; 
$BODY$
LANGUAGE plpgsql VOLATILE









  • No labels