public List<Order> findAll(OrderSearch orderSearch) {
return em.createQuery("select o from Order o join o.member m" +
"where o.status :=status " +
"and m.name like :name", Order.class)
.setParameter("status", orderSearch.getOrderStatus())
.setParameter("name", orderSearch.getMemeberName())
.setMaxResults(1000) // 최대 1000건
.getResultList();
}
- 동적쿼리
1) JPQL로 처리
코드도 길고 유지보수하기 힘들다. 실무에서 안씀!
public List<Order> findAllByString(OrderSearch orderSearch) {
String jpql = "select o from Order o join o.member m";
boolean isFirstCondition = true;
//주문 상태 검색
if (orderSearch.getOrderStatus() != null) {
if (isFirstCondition) {
jpql += " where";
isFirstCondition = false;
} else {
jpql += " and";
}
jpql += " o.status = :status";
}
//회원 이름 검색
if (StringUtils.hasText(orderSearch.getMemberName())) {
if (isFirstCondition) {
jpql += " where";
isFirstCondition = false;
} else {
jpql += " and";
}
jpql += " m.name like :name";
}
TypedQuery<Order> query = em.createQuery(jpql, Order.class)
.setMaxResults(1000);
if (orderSearch.getOrderStatus() != null) {
query = query.setParameter("status", orderSearch.getOrderStatus());
}
if (StringUtils.hasText(orderSearch.getMemberName())) {
query = query.setParameter("name", orderSearch.getMemberName());
}
return query.getResultList();
}
2) JPA Criteria로 처리
JPA 표준 제공(JPA 스펙에 있어서 실습 진행한 것이 실무에 사용되는 것은 아니다.)
1번보다 짧아졌지만 이 코드만 봐서 무슨 쿼리가 생성되는지 모르겠음 > 유지보수가 힘들다.
public List<Order> findAllByCriteria(OrderSearch orderSearch){
//jpa 표준 제공
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<Order> cq = cb.createQuery(Order.class);
Root<Order> o = cq.from(Order.class);
Join<Order, Order> m = o.join("member", JoinType.INNER);
List<Predicate> criteria = new ArrayList<>();
// 주문 상태 검색
if(orderSearch.getOrderStatus() != null) {
Predicate status = cb.equal(o.get("status"), orderSearch.getOrderStatus());
criteria.add(status);
}
//회원 이름 검색
if (StringUtils.hasText(orderSearch.getMemberName())) {
Predicate name =
cb.like(m.<String>get("name"), "%" +
orderSearch.getMemberName() + "%");
criteria.add(name);
}
cq.where(cb.and(criteria.toArray(new Predicate[criteria.size()])));
TypedQuery<Order> query = em.createQuery(cq).setMaxResults(1000); //최대 1000건
return query.getResultList();
}
persist는 DB에 바로 저장되지 않고 commit이 하는 순간 JPA 영속성 콘텍스트가 있는 멤버객체가 insert문이 만들어짐
Transactional : rollback 하기 때문에 commit 해서 DB결과를 볼 수 있음
1. @Rollback(false) - commit됨
@RunWith(SpringRunner.class) // 순수 단위테스트가 아닌 DB까지 JPA가 돌아가는 과정을 테스트하기 위함
@SpringBootTest
@Transactional
public class MemberServiceTest {
@Autowired MemberService memberService;
@Autowired MemberRepository memberRepository;
@Test
@Rollback(false)
public void 회원가입() throws Exception {
//given
Member member = new Member();
member.setName("kim");
//when
Long joinedId = memberService.join(member);
//then
assertEquals(member, memberRepository.findOne(joinedId));
}
}
2. em.flush(); - insert DB반영되지만 rollback됨
@RunWith(SpringRunner.class) // 순수 단위테스트가 아닌 DB까지 JPA가 돌아가는 과정을 테스트하기 위함
@SpringBootTest
@Transactional
public class MemberServiceTest {
@Autowired MemberService memberService;
@Autowired MemberRepository memberRepository;
@Autowired EntityManager em;
@Test
public void 회원가입() throws Exception {
//given
Member member = new Member();
member.setName("kim");
//when
Long joinedId = memberService.join(member);
//then
em.flush();
assertEquals(member, memberRepository.findOne(joinedId));
}
}