Versions Compared

Key

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

...

Expand

JPA의 영속성기능은 오라클 DBMS의 핵심기능중 축소된 Buffer Cache 처리기능과 유사해 보입니다.

필수적이지는 않으나 두가지 개념을 함께 익히면 JPA의 영속성개념을 익히는데 도움이 될듯합니다.

순서상 JPA와 별개로 관계형DB를 잘 이용하기위해서 DBMS 아키텍쳐를 익혀야하는것을 추천하며

오라클에서 관련자료를 많이 찾을수 있습니다.



JPA 제공 Repository

JPA Repository는 목적에따라 3가지로 구분이됩니다. 역활이 지정이 되지않았다고 하면

JpaRepository를 사용하면 모든 기능 활용이 가능합니다.

  • PaginAndSortingRepository : 페이징과 소팅이되는 조회용 저장소
  • CrudRepository : 데이터 업데이트에 관련된 저장소
  • JpaRepository : 위 두가지 기능 모두 활용가능하며 추가로 일부 영속성관련 제어가능

CRUD Repository

JPA에서는 기본적인 데이터 삽입/수정/조회를 위해 추가적인 구현없이 기본적인 기능을 제공하는

인터페이스를 제공해줍니다. 트랜젝션관리 영속성관리등을 직접할필요가 없기때문에 이용이 간단합니다.

단순한 데이터 변경 서비스에서는 CrudRepository만으로도 충분합니다.


인터페이스 준비

아래와 같이 조작할 엔티티(테이블)을 지정하는 인터페이스를 준비하면,

사용자테이블을 제어하기위한 기본 기능을 추가 구현없이 사용가능합니다.

No Format
/선언
public interface GroupRepositoryUserRepository extends CrudRepository<GroupInfoCrudRepository<User, Long> {
}
public interface UserRepository extends CrudRepository<User, Long> {
}

Insert


서비스 로직정의

데이터 제어는, 제공되는 일괄적이고 단순한 save,delete,find 3가지만 이용하여

우리가 원하는 데이터제어의 서비스 코드를 작성할수가 있습니다. 

No Format
public class UserUpdateService{
....
  @Autowired
  private UserRepository userRepository;
 
  public User jpatest1C(String groupname,String name) {
		
No Format
// 그룹생성
GroupInfo newGroup = new GroupInfo();
		newGroup.setName("학생"groupname);
		groupRepository.save(newGroup);

				
		// 사용자 생성
        User addUser = new User();
        addUser.setName("minsu"name);
        addUser.setEmail("test@x.com");
        addUser.setGroupInfo(newGroup);                        

//SQL문에서는 외래키인 그룹ID를 지정하지만,객체모델에서는 이미 알고있는 참조지정을 합니다.
//이것이 OOP의 특성을 잃지않으면서,관계형DB의 특성까지 확장이된 한가지 케이스입니다. 
addUser.setGroupInfo(newGroup);
userRepository.save(addUser); 

...

        return userRepository.save(addUser);
	}
		
	public void jpatest1U(User user) {
		user.setName(user.getName() + "_mody");
		userRepository.save(user);
	}	
	
	public void jpatest1D(User user) {
		userRepository.delete(user);
	}	
	
	public void japtestList() {
        // 사용자 조회
        Iterable<User> userList = userRepository.findAll();      
        userList.forEach(item->System.out.println( String.format("V1 Name:%s  GroupName:%s", item.getName(),item.getGroupInfo().getName() )  ));	
	}	

사용예

OOP(객체) 접근방식을 통하여, 실제 데이터베이스의 저장소 변경을 할수가 있습니다.

샘플은, 사용자추가/업데이트/삭제/조회를 순차적으로 실행하였습니다.

트랜잭션은 Transactional 어노테이션을 사용하여, 트랜잭션 범위를 지정하여 활용할수 있습니다.

하지만 CRUDRepository에서는 각각의 최소단위가 이미 트랜잭션 단위이기때문에 CRUD저장소의

인터페이스를 순차적으로 사용하는곳에서 트랜잭션을 거는것은 의미가 없습니다.

CrudRepository는 트랜잭션 처리를 상당수 은닉화 하였기때문에, 복잡한 트랜잭션 처리가 요구되는곳에서는

JpaRepository 혹은 사용자정의 Repository에서 트랜잭션에 관련된 커밋,롤백등 직접반영하는것이 권장됩니다.

명령어를 통해 직접하는방식, 인터페이스에 트랜잭션 어노테이션을 지정하는방식 크게 두가지가 있으며

이 부분은 별도의 주제로 다시 살펴보겠습니다.


No Format
@Transactional	
public void jpa_test1() {		
		User userA = jpatest1C("학생A","minsu");
		User userB = jpatest1C("학생B","minsu");
		jpatest1U(userA);
		jpatest1D(userB);
		japtestList();
	}
Expand
title실행결과

실제로 아래와같은 SQL문이 차례로 수행됩니다.(SQL약식표현)

insert com.example.demo.data2.User – minsu,학생A 추가

insert com.example.demo.data2.User – minsu,학생B 추가

update com.example.demo.data2.User –첫번째 추가된 minsu의 이름변경

delete com.example.demo.data2.User –두번째 추가된 minsu data 삭제


japtestList() ==> 결과( 첫번째 추가된 이름이 변경된 minsu만 조회됨

V1 Name:minsu_mody  GroupName:학생A


Custom Repository

조회및 트랜잭션에 관련된 비지니스 로직이 복잡할시 CrudRepository의 인터페이스로는 

구현하기가 힘들어질수도 있습니다. ( 상당수 추상화되어 간단한 기능만 제공하기 떄문에 )

이경우 복잡한 비지니스 로직에대해 영속성을 고려한 디테일한 트랜잭션 전략을 구성할수가 있습니다. 

여기서 앞장에서 설명하지 못한 JPA의 중요요소인 영속성에대한 기능도 함께 설명하여 살펴보도록하겠습니다.


Delete

Custom Repository

비지니스 로직이 복잡해서 CrudRepository의 인터페이스만으로는 부족하여

트랜잭션처리및 영속성상태변경을 직접 관여하고 싶을때 사용자가 직접 영속성을관리하는

EntityManage를 구현레벨에 활용할수가 있습니다.

인터페이스 준비

Code Block
languagejava
themeEmacs
public interface MyAddressRepository  {
	void someTest(Address2 address2);
}


public class AddressRepositoryImpl implements MyAddressRepository { 
	@PersistenceContext
	private EntityManager em;
	  
	@Override
	@Transactional
	public void someTest(Address2 address2) {
		em.refresh(address2);		
		em.detach(address2);
		em.persist(address2);
		em.lock(address2, null);
		em.flush();
	}	  
}
public interface AddressRepository extends CrudRepository<Address2, Long>,MyAddressRepository {

}

...

네이밍설명
MyAddressRepository

인터페이스이며, 커스텀함 함수규격을 미리 설명을 해놓아야합니다.

네이밍 특성 : 특성+테이블명+저장소

My + Address + Repository

AddressRepositoryImpl

커스텀한 구현체를 정의합니다.

네이밍 특성: 테이블명+저장소+구현

MyAddressRepositoryImpx ( X )

AddressRepository

최종 사용가능해진 저장소이름입니다. JPA의 기본 저장소 특성과함께

사용자 정의 기능을 함께 사용가능합니다.

네이밍특성: 테이블명+저장소

Insert

Update

...