셀렉트 두 번 하는 것보다 조인해서 들고오는게 좋음 I/O가 한번만 일어나니까
user라는 object를 적을 수 있음 (컴포지션해서)
ORM : object끼리 릴레이션을 맺고 매핑할 수 있어요. (오브젝트가 오브젝트를 포함하과 있다 -> 오브젝트끼리 릴레이션을 맺고 있다고 말함)
둘 중 어느 형태든 모델에 담아서 뷰에 뿌리면 끝나~
<select id="findByIdtoDetail" >
SELECT b.id, b.title, b.content, b.usersId, b.createdAt,
u.id, u.username, u.password, u.email, u.createdAt
FROM boards b INNER JOIN users u
ON b.usersId = u.id
WHERE b.id = #{id}
</select>
SELECT할 때 무조건 다 들고 오세요
DAO는 DB에 있는 걸 다 들고오고 무엇을 출력할지는 service에서 결정함
근데 문제가 하나 있어
b.id u.id가 id로 return되니까 DB에서
column값에 _1이 붙어서 나중에 매핑이 안됨
사실상
<select id="findByIdtoDetail" >
SELECT b.id, b.title, b.content, b.usersId, b.createdAt,
u.id as userId, u.username, u.password, u.email, u.createdAt
FROM boards b INNER JOIN users u
ON b.usersId = u.id
WHERE b.id = #{id}
</select>
인데 userId가 두개 있는 셈 -> b.userId를 지우고 u.id에 별칭을 지어주자
<select id="findByIdtoDetail" >
SELECT b.id, b.title, b.content, b.createdAt,
u.id as userId, u.username, u.password, u.email, u.createdAt
FROM boards b INNER JOIN users u
ON b.usersId = u.id
WHERE b.id = #{id}
</select>
(혹은 반대로 해서 u.id(PK)를 쓰지 않고 b.userId를 쓰고 별칭을 안 써도 됨)
createdAt도 중복되어서 삭제.
<select id="findByIdtoDetail" >
SELECT b.id, b.title, b.content, b.userId, b.createdAt,
u.username, u.password, u.email
FROM boards b INNER JOIN users u
ON b.usersId = u.id
WHERE b.id = #{id}
</select>
나는 이 쿼리를 사용하겠다.
package site.metacoding.red.domain.boards.mapper;
import java.sql.Timestamp;
import lombok.Getter;
import lombok.Setter;
@Setter
@Getter
public class BoardDetail {
private Integer id;
private String title;
private String content;
private Timestamp createdAt;
private Integer usersId;
private String username;
private String password;
private String email;
}
result Type 경로 맞춰주기
<select id="findByIdtoDetail" resultType="site.metacoding.red.domain.boards.mapper.BoardDetail" >
SELECT b.id, b.title, b.content, b.userId, b.createdAt,
u.username, u.password, u.email
FROM boards b INNER JOIN users u
ON b.usersId = u.id
WHERE b.id = #{id}
</select>
package site.metacoding.red.domain.boards;
import java.util.List;
import site.metacoding.red.domain.boards.mapper.BoardsDetail;
import site.metacoding.red.web.dto.reqest.boards.WriteDto;
public interface BoardsDao {
public void insert(WriteDto writeDto);
public Boards findById(Integer id);
public List<Boards> findAll();
//나중에 findAll할 때도 join해서 받아야 할 것임
//왜냐면 userId가 아닌 작성자 정보를 줘야 하기 때문에
public void update(Boards boards);
public void delete(Integer id);
public BoardsDetail findByIdtoDetail(Integer id);
}
// @GetMapping("/boards/{id}")
// public RespDto<?> getOne(@PathVariable Integer id){
// return new RespDto<>(1,"한건조회성공",boardsDao.findById(id));
// }
//같은 기능을 하기에 기존의 getOne을 삭제(주석처리)
//하지만 findById자체는 필요함 (update 때 영속화를 하기 위해 사용하기 때문)
@GetMapping("/boards/{id}")
public RespDto<?> getOne(@PathVariable Integer id){
return new RespDto<>(1,"한건조회성공",boardsDao.findByIdtoDetail(id));
}
=> 모델에 담았다면 모델의 key값.code= 1
이렇게 뿌리고 싶은 것만 뿌리면 됨
ORM(Object Relational Mapping)
객체와 관계형 데이터베이스의 데이터를 자동으로 매핑(연결)해주는 것을 말한다.