DAO란 실제 DB에 접근하여 service와 연결하는 객체이다.
domain logic(DB와 관련이 없는 코드)와 persistence layer와 분리하기 위해서 사용된다.
persistence layer는 db에서 data를 CRUD하는 계층이다.
이렇게 따로 분리하는 이유는 HTTP Request를 Web Application이 받게 될때 Thread를 생성하게 된다.
이 때, 비지니스 로직이 DB로부터 data를 얻어오기 위해 매번 Driver를 로드하고 Connection 객체를 생성하게 된다면 엄청나게 많은 Connection이 일어난다.
그러므로 DAO를 만들어 DB전용 객체로만 쓰는 것이다.
JPA에서는 DB에 데이터를 CRUD 하는 Repository 객체들이 DAO를 대체한다고 볼 수 있다.
MemberRepository class
@Repository//내부에 @Component가 있음
public class MemberRepository {
@PersistenceContext//스프링이 EntityManager를 만들어서 주입
private EntityManager em;
public void save(Member member){//jpa가 member를 저장
em.persist(member);//트랜잭션이 커밋되는 시점에 db에 반영
}
public Member findOne(Long id){//member를 찾아서 반환
return em.find(Member.class,id);
}
public List<Member> findAll(){//from의 대상이 테이블이 아니라 entity
return em.createQuery("select m from Member m",Member.class)//조회타입 member.class
.getResultList();
}
public List<Member> findByName(String name){
return em.createQuery("select m from Member m where m.name = :name",Member.class)
.setParameter("name",name)
.getResultList();
}
}
DTO란 VO(Value Object)라고도 하며, DB의 data를 mapping하기 위한 data 객체이다.
DTO는 보통 data, getter, setter값만 가지고 있으며, DB에서 data를 얻어 service나 controller등으로 보낼 때 사용하는 객체이다.
즉, 어떠한 비지니스 로직도 포함하지 않아도 되는 단순한 data 객체이다.
Member.class
@Getter @Setter
public class Member {
private Long id;
private String name;
private Address address;
}
Service란 비지니스 로직이 들어가는 부분이다.
비지니스 로직이란 사용자가 원하는 결과물을 도출할 수 있도록 짜여진 코드이다.
DAO로 DB에 접근한 후, DTO로 data를 전달 받고, 비지니스 로직을 처리한 후 결과를 반환한다.
MemberService.class
@Service
public class MemberService {
private final MemberRepository memberRepository;
//@Autowired안써도 됨 하나일때는
public MemberService(MemberRepository memberRepository){//=>@AllArgsConstructor로 해도 됨, @RequierdArgsConstructor은 final붙은 애를 생성자를 만들어줌
this.memberRepository=memberRepository;
}
//회원 가입
@Transactional
public Long join(Member member){
validateDuplicateMember(member);
memberRepository.save(member);
return member.getId();
}
//중복 예외처리
private void validateDuplicateMember(Member member) {
List<Member> findmembers = memberRepository.findByName(member.getName());//최후의 보루로 name를 unique로 잡는게 좋음
if (!findmembers.isEmpty()){
throw new IllegalStateException("이미 존재하는 회원입니다,");
}
}
//회원 조회
@Transactional(readOnly = true)
public Member findOne(Long memberId){
return memberRepository.findOne(memberId);
}
//회원 전체 조회
@Transactional(readOnly = true)
public List<Member> findMembers(){
return memberRepository.findAll();
}
}
참고참고
https://ko.wikipedia.org/wiki/%EB%8D%B0%EC%9D%B4%ED%84%B0_%EC%A0%91%EA%B7%BC_%EA%B0%9D%EC%B2%B4
https://ko.wikipedia.org/wiki/%EB%8D%B0%EC%9D%B4%ED%84%B0_%EC%A0%84%EC%86%A1_%EA%B0%9D%EC%B2%B4
https://lazymankook.tistory.com/30