본문 바로가기

프로그래밍/Web

JPA 쿼리 이것저것

엔티티 객체

JPA는 엔티티 객체가 곧 테이블이다. DB 테이블과 매핑되는 엔티티(도메인) 객체를 만들어 두고, 

저장소나 엔티티 매니저를 통해 실제 데이터를 처리한다.



@Entity

@Table(name="TABLE_NAME")

public class MyEntity {

@Id

@Column(name="userId", nullable=false)

@GeneratedValue(strategy=GenerationType.AUTO)

private Long userId;


// 다른 엔티티와 join

// OneToOne(optional=false)는 Inner Join 으로 처리된고, true 면 Outer join으로 동작한다.

@OneToOne(optional=false)

@JoinColumn(name="userId")

OtherEntity other;

}


@Entity

public class OtherEntity {

@Id

@GeneratedValue

private Long userId;

}



@Id : 주키(PK)

@Column : 컬럼명 - 없으면 변수명과 동일

@GeneratedValue : 값 지정 방식 - GenerationType.IDENTITY, GenerationType.AUTO 등







jpa 저장소를 사용하기 위해 config 클래스에 jpa 저장소를 활성화한다.


@Configuration

@EnableJpaRepositories

class MyConfig {


}


Repository

저장소는 별도의 구현은 필요없이 인터페이스 선언만으로 구성이 완료된다.

Repository, JpaRepository 등을 상속받은 인터페이스를 만들고 규칙에 의해 필요한 메쏘드를 선언해주면 jpa가 알아서 

데이터베이스와 연동해 객체를 전달해 주게 된다.


인터페이스 상속시 엔티티(도메인) 객체 정보와 ID 로 사용될 값의 타입을 전달해 준다.

interface MyRepository extends Repository<MyEntity, Long>

{

}


CrudRepository

ㄴPaginAndSortingRepository

ㄴ JpaRepository


기본적인 CRUD 메쏘드들이고, jpa 는 영속성 저장소(컨텍스트) 와 관련있는 플러시 관련 메쏘드들이 선언되어 있다.

CrudRepository

save

findOne

exists

findAll

count

delete

deleteAll


JpaRepository

flush

saveAndFlush

deleteInBatch

deleteAllInBatch

getOne



쿼리 메쏘드 추가하기

대충 아래와 같은 규칙으로 메쏘드를 선언해 주면 내부적으로 메쏘드를 정의해 쿼리를 만들어 주게 된다.



특정한 행위를 나타내는 접두어와 By 로 시작하는 조건으로 이루어지고, 필요에따라 열거해 주면 된다.


검색: find...By...And...

List<DataDTO> findByName(String name);

List<DataDTO> findDistinctUserByNameAndAge(String name, Long age);


조건에는 LessThan, GreaterThan, Like 등도 사용.

딱봐도 복잡한 쿼리는 적용이 힘들듯 싶다. 모호함을 피하기 위해  언더바가 예약어로 되어있긴 하다.

정렬이나 특정 갯수를 가져오는것도 된다.

findByNameAsc

findTop3ByName



기타 

read...By

get...By

count...By

delete...By



서비스 구현

jpa 는 트랜젝션 단위로 처리가 이루어지므로, 데이터 처리에 관련한 내용은 컨트롤러에서 서비스로 위임하게 된다.

컨트롤러에서 MyEntity에 해당 하는 객체를 생성하고, 데이터를 넣은 다음, 서비스의 save에 전달하면, 서비스는 리포지토리에

저장한다.

실제 db로의 저장은 트랜젝션이 마무리되어 컨트롤러로 돌아가면서 이루어지게 된다.


@Service

@Transactinal( readOnly = true)

public class MyService  {


@Autowired

MyRepository myRepository;


@Transactional

public void save( MyEntity data ) {

myRepository.save( data );

}

}



대충 흉내만 내 봤는데, 단일 테이블이나 복잡하지 않은 CRUD 구문들은 쉽게 처리할 수 있다. 하지만 쿼리해야할 데이터들이

점점 복잡해지면 JPA만으로는 한계가 있다.

이렇게 jpa 로 처리하기 힘든 복잡한 문장은 직접 쿼리로 처리하거나 JPQL 을 사용한다. 


저장소 메쏘드에 쿼리 지정

repository 메쏘드를 해당 규칙과 상관없이 별도 쿼리가 동작하도록 하려면 @Query 어노테이션을 사용한다.

쿼리 문자열 안의 파라미터는  ":name" 과 같이 사용.

@Repository

public interface MyRepository extends JpaRepository<MyEntity, Long> {

@Query("SELECT * FROM MyEntity a WHERE a.userId = :userId")

 public ArrayList<Object[]> getMyList(@Param("userId") Long userId );

}




Entity Manager 네이티브 쿼리 


@Service

@Transactional(readOnly = true)

public class MyService {


@PersistenceContext

private EntityManager entityManager;


public List<DataDTO> getList( Long id ) {

String query = " SELECT * FROM my_table WEHER user = :userId";


Query query = entityManager.createNativeQuery(query);

query.setParameter("userId", id );


List<Objectp[> result = query.getResultList();

List<DataDTO> list = new ArrayList<DataDTO>();

int i = 0;

for( Object[] object : result ) {

DataDTO data = new DataDTO();

data.setUserId(((BigInteger) object[0]).longValue());

list.add( i , data );

i++;

}


return list;

}


}


Entity Manage 객체 쿼리


Entity Manager를 사용하는 것은 동일한데, db 테이블이 아닌 엔티티 객체를 대상으로 쿼리한다. 

(어짜피 엔티티 객체에 DB 테이블 정보가 있느니...)


대부분 동일하고, 쿼리 생성 하는 부분만 메쏘드가 다르다.


public List<DataDTO> getList( Long id ) {

String query = " SELECT entity FROM MyEntity entity WEHER entity.user = :userId";


Query query = entityManager.createQuery(query);

query.setParameter("userId", id );


List<Objectp[> result = query.getResultList();

List<DataDTO> list = new ArrayList<DataDTO>();

int i = 0;

for( Object[] object : result ) {

DataDTO data = new DataDTO();

data.setUserId(((BigInteger) object[0]).longValue());

list.add( i , data );

i++;

}


return list;

}


'프로그래밍 > Web' 카테고리의 다른 글

VSCode 웹 디버깅  (0) 2018.07.19
openssl  (0) 2018.07.17
Windows 레드마인 설치(Bitnami)  (1) 2017.09.22
Gradle Wrapper  (0) 2017.03.06
스프링 요청/응답  (0) 2017.02.26
[spring] 프로퍼티 값 읽기  (0) 2017.02.21
[spring] 핸들러 인터셉터  (0) 2017.01.24
[spring] Spring boot 기본 설정  (0) 2017.01.24
[spring] batch 작업관련 요소들  (0) 2012.09.28
[spring] JAVA코드 테스트를 위한 Spring설정  (0) 2012.09.25