Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

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

위 다이어그램처럼 JPA Repository가 위와같이 작동하지 않지만, 옵션에따라 유사하게 작동이됩니다.

단지 마지막 JPA Repository 가 항상 이렇게 작동되는것은 아니나, DB객체를 직접 저장하지 않고 중간객체를 통해

DB를 효율적으로 이용한다는것입니다. 

 


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

...

  • 1차 캐시기능
  • 동일성보장
  • 트랜잭션을 지원하는 쓰기지연
  • 변경감지
  • 지연로딩


위와같은 장점이 있다고, SQL호출방식때 익힌 SQL 직접호출방에서 배운 데이터베이스의 개념을 알필요없다라고 결론을몰라도 될까요?

그것은 큰 착각입니다. 내리는것은 잘못되었습니다. 단지 JPA는 반복적인 SQL작성시간을 줄여줄뿐줄여주지만, 기존에 존재하지않던

중간 영속성 객체까지 잘 다뤄야하기 때문에 JPA의 특성과 더불어 관계형 DB의 특성을 같이 잘알고 있어야 상호운영이 가능합니다. ( 난이도 업 )합니다. 


단순한 검색및 집계처리에 대한 사용법을 다시한번 정리하였습니다.

Expand
title검색관련기능

검색및 집계 처리

...

검색 함수쿼리

장점: 바람직한 네이밍룰에의해 검색 기능을 작동시킬수있다.

단점: 아규멘트가 길어질수록,네이밍도 같이 길어진다.

Code Block
languagejava
themeEmacs
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을 사용한 집계처리

장점:SQL친화적으로 검색 인터페이스를 작성할수 있다.

단점:지원되지 않는 SQL문은 작동안한다.

No Format
	@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 쿼리

장점:네이티브 SQL문을 맘것 활용할수 있다.

단점:맵핑및 아규멘트전달에 어려움이 있으며, 다른 DB로의 호환성을 포기해야할수도 있다.

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


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

장점:특수한 기능구현이 가능하고 어플리케이션에게 연산부담을 시킬수있다.

단점:커스텀한 로직이 늘어나 관리가 안될수 있으니 , 효율적인 SQL문 작성법부터 알아보자

Code Block
languagejava
themeEmacs
	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 지원이되는 저장소

장점:여러가지 검색옵션을 조합을 할수 있으며, 대표적으로 null 인자값에대해 유연하게 대처할수 있다.

단점: 초기셋팅이 번거럽고, DSL사용을위하  QEntityObject가 메타빌드로 자동추가 생성이 된다. (어플리케이션이 엔티티증가에따라 무거워진다는것)

Code Block
languagejava
themeEmacs
//인터페이스 선언부
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);
		});
		
	}


참고 원본문서:


데이터 변경(Insert,Update,Delete)

스토어 프로시져 이용

장점: 전통적인 SP개발 방식을 이용할수 있다.

단점: 형상관리 분리로 인해, 서비스로직을 분리 관리해야하며, 상태가 없기때문에 JPA 중간저장소 기능을 100%활용못할수 있음  

예를 들면, 높은 TPS요구에대해 EntityManager의 커넥션풀 기능이 비활성화되어 커넥션 Max에러가 발생할수 있음(직접관리해야함)

Code Block
languagesql
themeEmacs
CREATE OR REPLACE FUNCTION addaddress(
	address character varying,
	age integer,	
	name character varying,
	sex character varying,
	phonenbr character varying )
 
RETURNS integer AS $BODY$	
	BEGIN 
		INSERT INTO address ( address, age, name,sex,phonenbr) VALUES( address, age, name,sex,phonenbr);
		return 0;
	END; 
$BODY$
LANGUAGE plpgsql VOLATILE
No Format
public interface AddressRepo extends CrudRepository<Address, Long>{
	@Procedure
	public Integer addaddress(String address,Integer age, String name, String sex, String phonenbr);	
}


//SP 호출방법 : 커넥션풀 관리가 안되어, Loop로 트랜잭션을 유발하는것은 위험합니다.
addressRepo.addaddress("독도", 45, "포켓몬", "남", "010-1233-3321");


//호출로그 : 실제 호출로그에는 아규멘트가 5개가아닌 6개입니다. 이것은 리턴처리가,OUT 파라메터로 자동연결되었기때문입니다. 
Hibernate: 
    {call addaddress(?,?,?,?,?,?)}


more info: http://roufid.com/3-ways-to-call-a-stored-procedure-with-hibernate-jpa-2-1/


CRUD

...

Repository


Insert

장점: 데이터 입력을 위해, 추가구현없이 CrudRepository만 사용하면되며 객체접근법 활용이 가능합니다.

...