Versions Compared

Key

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

JPA의 컨셉은 Java Persistence API 의 약자로 두가지 큰 목적을 가지고 있습니다.있으며

  • 데이터 베이스에 존재하는 모델링을 자바객체로 맵핑을 시킴
  • SP/SQL방식을 최대한 억제하고, OOP중심적 Entity설계및 영속성 Repository를 통한 데이터 제어

JPA와 별개로 데이터베이스를 잘 활용하는 방법은 데이터베이스를 잘 이해하는것임으로

연관부분이 있을시 JPA의 특성과 같이 설명 진행 예정입니다.


설명을 위해, 축약된 코드로 진행되며, 풀소스는 아래에서 확인가능합니다위 특징은, 스프링의 웹요소와 연동할때도 유용하게 쓰입니다.


CodeLink : http://git.webnori.com/projects/WEBF/repos/spring_jpa/browseJPA 개념 추가설명

Expand
title목차펼치기

Table of Contents


접속 DB 설정

...


No Format
# application.properties
spring.jpa.hibernate.ddl-auto=update
spring.datasource.url=jdbc:mysql://localhost:3306/spring
spring.datasource.username=test
spring.datasource.password=test1234

...

Code Block
languagesql
themeEmacs
-- 사용자생성
INSERT INTO `spring`.`user`
(`id`,
`email`,
`name`)
VALUES
(<{id:}>,
<{email: >,
<{name:}>);

-- 사용자 조회
SELECT * FROM user



JPA

...

RelationShip

...


일반적으로 DB의 테이블은 하나의 테이블에 모든 정보를 포함하여 설계하지않고,

...

데이터베이스의 관계 형성과 유사한 효과를 내려고 합니다. 그 목적을 달성하기위해 테이블과 클래스의 몇가지 차이점을 알아야합니다.

Class VS Table

ClassTable

Class GroupInfo{

string name;

}


Class User{

GroupInfo groupInfo;

string name;

string email;

}


Class GroupInfoNew{

string name;

List<User> userList;

}

GroupInfo

Image Modified


User

Image Modified



select * from user u join groupinfo g on g.group_id=u.user_id


  • Class : 포함되는 객체는, 자신을 포함하는 객체 찾기가 어려우며,주인객체로 단방향접근이 일반적입니다. ( User → GroupInfo )
  • Table : 테이블은  자유로운 결합이 가능하며 연관관계 아이디를 통해 양방향접근이 가능합니다.  ( User ↔ GroupInfo )
  • Class : 클래스는 객체자체를 리스트화하여 가질수 있습니다.
  • Table : 테이블은 리스트형태의 데이터자체를 포함하는것은 불가능하며, 일대다 관계가 형성된 테이블을 통해 논리적 구성을 하여야합니다.

...

어떠한 관계가 형성이되고 인덱스를 설정하는지 파악하는것은 중요한 사안입니다.


Warning

클래스를 통한 어플리케이션에서 테이블 생성전략(DDL)은 일반적으로 개발단계까지 허용이되며, 지속적 빌드및 테스트로 한정지으면

단일지점이 아닌, 여러군대를 업데이트해야하는 SP방식보다 분명 유리합니다.

일반적으로 운영에서 어플리케이션이 테이블 구조를 변경하는것은 허용되지 않으며 DDL기능을 off시키고

데이터베이스의 운영및형상을 관리하는 관리자를 통해 하는것이 권장되며, 운영에 자동으로 변영이 되는것은

불안 요소로 측정되거나 금기시 되는 사항입니다.

하지만 이것이 모든경우 항상 옳다라고 할수없으며

해외 잘만들어진 엔터프라이즈급 서비스를 관리하는 어떠한 오픈 소스의 경우에도,

오픈소스 특성상 수많은 개선작업과 데이터구조변경이 여러사람에의해 이루어지며 버젼업이 되었을시,

DB구조를 안전하게 변경하면서 버젼업이되는 마이그레이션이되는 패키지를 많이 봐왔습니다.

물론 이것도 장단점이 있으며 분야마다 다른 상황이 존재하지만

현재 운영하는 DB구조를 , 어플리케이션(마이그레이션명령)이 안정적으로 변경하면서 버젼업을 할수 있느냐?

운영에서 어플리케이션이 테이블 구조를 변경하는것은 허용하지 않는 정책을 사용합니다.

DDL기능을 OFF시키거나, 어플리케이션 내에는 변경 코드 자체가 없을수도 있습니다.

어플리케이션 개발자에게 DBA에 준하는 권한을 줘야 개발/운영/배포가 가능한 구조에서

어플리케이션 에게 DDL을 무조건 금지하는 정책이 어떠한 의미를 가지는지 고민이 필요해보입니다애시당초 할수없는 구조이기때문에, 여러 관리자와 리소스를 투입해야한다? 기술적인 의미는 다릅니다.


식별관계 VS 비식별관계

  • 식별 관계는 부모 테이블의 기본 키를 자식 테이블로 전파하면서 자식 테이블의 기본 키 컬럼이 점점 늘어난다. 그러면 조인할 때 SQL이 복잡해지고 기본 키 인덱스가 불필요하게 커질 수 있다.
  • 식별 관계는 2개 이상의 컬럼을 합해서 복합 기본 키를 만들어야 하는 경우가 많다.
  • 식별 관계를 사용할 때 기본 키로 비지니스 의미가 있는 자연 키 컬럼을 조합하는 경우가 많다. 반면에 비식별관계의 기본 키는 비지니스와 전혀 관계없는 대리 키를 주로 사용한다. 
  • 언제든지 요구사항은 변한다. 식별 관계의 자연 키 컬럼들이 자식에 손자까지 전파되면 변경하기 힘들다.
  • 식별 관계는 부모 테이블의 기본 키를 자식 테이블의 기본 키로 사용하므로 비식별 관계보다 테이블 구조가 유연하지 못하다.

...

Code Block
languagejava
themeEmacs
		//Test를 위해 100개의 데이터 인입
		GroupInfo newGroupA = new GroupInfo("학생");
		Set usersA = new HashSet<User>() {{
			for(int i=0; i<100 ; i++) {
				String userName = String.format("minsu%d", i);
				String email = String.format("min%d@x.com", i);
				add(new User(userName,email,newGroupA));
			}					
		}};
		newGroupA.setUsers(usersA);
        groupRepository.save(new HashSet<GroupInfo>() {{
        	add(newGroupA);
        }});


		//원하는 페이지를 조회합니다.( 페이지번호 , 페이지당 처리수)
        PageRequest  pageRequest =  new PageRequest(1,10);                       
        Page<User> sPage = userPageRepo.findAll(pageRequest);
        System.out.println( String.format(" %d:Contents %d:Page", sPage.getNumberOfElements(),sPage.getNumber() ) );
        
        Page<User> sPagesPage2 = userPageRepo.findAllfindByGroupInfoName("학생", pageRequest);
        System.out.println( String.format(" %d:Contents %d:Page", sPagesPage2.getNumberOfElements(),sPagesPage2.getNumber() )) ) );


페이지와 소팅 동시처리
No Format
pageRequest =  new PageRequest(0,10, Sort.Direction.DESC , "a","b","c"  );
pageRequest =  new PageRequest(0,10, Sort.Direction.DESC ,  
        Page<User> sPage2 = userPageRepo.findByGroupInfoName("학생", pageRequest);
        System.out.println( String.format(" %d:Contents %d:Page", sPage2.getNumberOfElements(),sPage2.getNumber() "a",Sort.Direction.ASC,"b"  );
다중 소팅
No Format
Sort.Direction sortDir = Sort.Direction.DESC;
if( sortdir.equals("asc") ) sortDir = Sort.Direction.ASC;

Sort sortOpt = new Sort( sortDir, sort )
						.and( new Sort(Sort.Direction.DESC, "customervaluation") );

JPQL MODE

Code Block
languagejava
themeEmacs
public interface UserPageRepo extends Repository<User, Long>{

	// QueryMode
	@Query(value="select t from User t "			
			+ "where  t.name =:name  "
			+ "order by t.id " , nativeQuery=false )
	List<User> findBySomeName( @Param("name") String name, Pageable pageable);
	
}

...

nativeQuery , true/flase에따라 작동방식이 변경가능하며 , 특수한 경우가 아니면

JPQL사용이 권장됩니다.


다른 유용한 사이트:

JPA 개념 설명 : http://blog.woniper.net/255




Info

다른 진영(.net) 에서도 JPA와 유사한 스펙을 가지고 있습니다.

Entity Framework : https://docs.microsoft.com/en-us/ef/core/

NHibernate : https://en.wikipedia.org/wiki/NHibernate /


http://www.sqler.com/401779


서로의 어플리케이션진영에서 데이터베이스를 어떻게 다룰것인가?

에대한 고민이 비슷해 보이며 서로에게 영향을 주면서 계속 발전중인듯보입니다.

마치 웹에서 MVC패턴 적용이 진영간 표준화 된것처럼

데이터베이스를 다루는 기술도 표준화를 이끌어내기를 기대해봅니다.


진영간 유사한 스펙에 다른 기술적 차이


JAVA(JPA).NET(EntityFrame)
모델정의Entity-클래스클래스
Persitent 저장소명RepositoryDbContext
쿼리툴QueryDSLLinq