데이터베이스의 테이블을 객체로 매핑해서, 프로그래머가 객체 지향 방식으로 데이터베이스를 조작할 수 있게 도와준다.
ORM의 주요 개념과 특징
1. 객체와 테이블의 매핑
- 객체는 프로그래밍 언어에서 사용하는 데이터 구조이며, 테이블은 데이터베이스에서 데이터를 저장하는 구조
- ORM은 클래스(객체)와 테이블, 속성과 컬럼 간의 매핑을 정의하여 객체와 데이터베이스 간의 변환을 자동화
2. CRUD 작업의 자동화
- ORM은 Create, Read, Update, Delete와 같은 기본 데이터베이스 작업을 자동화
- 이를 통해 개발자는 SQL을 직접 작성하지 않고도 데이터 조작이 가능
3. 추상화 수준의 향상
- ORM을 사용하면 데이터베이스의 구체적인 구현에 대한 의존도를 줄이고, 애플리케이션의 비즈니스 로직에 집중할 수 있음
- 데이터베이스에 대한 추상화 계층을 제공하여 데이터베이스 관리 시스템(DBMS) 간의 전환이 비교적 용이
4. SQL Injection 방지
- ORM은 SQL 쿼리를 자동으로 생성하며, 이 과정에서 파라미터 바인딩을 사용하여 SQL 인젝션 공격을 방지하는 데 도움
5. 관계형 데이터의 처리
- ORM은 객체 간의 관계를 정의하고 관리할 수 있습니다. 예를 들어, 일대일(One-to-One), 일대다(One-to-Many), 다대다(Many-to-Many) 관계를 객체 모델로 표현 가능
ORM의 장점
- 생산성 향상: SQL 작성 및 데이터베이스 관리에 드는 시간을 절약
- 유지보수 용이성: 코드와 데이터베이스 간의 일관성을 유지하기 쉬움
- 데이터베이스 독립성: 데이터베이스 종류에 따라 코드를 변경할 필요 없이 ORM이 추상화 계층을 제공하여 여러 데이터베이스를 지원 가능
- 안전성: SQL 인젝션과 같은 보안 취약점을 줄이는 데 도움
ORM의 단점
- 성능 오버헤드: ORM의 추상화 계층이 추가되어, SQL을 직접 작성하는 것보다 성능이 떨어질 수 있음
- 복잡한 쿼리 처리의 어려움: 복잡한 쿼리나 특정 데이터베이스 기능을 사용하는 경우, ORM이 이를 지원하지 않을 수 있음
- 초기 학습 비용: ORM 프레임워크를 사용하는 데 필요한 초기 학습 비용이 발생할 수 있음
연습 코드
1.ex01(Setter, 생성자 활용)
user
package ex01.model;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@NoArgsConstructor
@AllArgsConstructor
@Data
public class User {
private int userId;
private String username;
private String email;
}
App1
package ex01;
import ex01.model.User;
public class App1 {
public static void main(String[] args) {
// 1. DB에서 가져온 데이터 - Flat(평평) 하게 가져올 수 밖에 없다
DBData1 dbData = new DBData1(1, "제목1", "내용1", 3, "love", "love@nate.com");
//DBData1는 db에서 조회한 데이터
//ViewData1는 view 에 뿌리기 위해
// 2. dbData1를 ViewData1에 옮기시오 - ORM
//1. setter로 하나씩 넣기
ViewData1 v1 = new ViewData1();
v1.setBoardId(dbData.getBoardId());
v1.setTitle(dbData.getTitle());
v1.setContent(dbData.getContent());
User user = new User();
user.setUserId(dbData.getUserId());
user.setUsername(dbData.getUsername());
user.setEmail(dbData.getEmail());
v1.setUser(user);
//2. 생성자 이용
User user1 = new User(dbData.getUserId(), dbData.getUsername(), dbData.getEmail());
ViewData1 v2 = new ViewData1(dbData.getBoardId(), dbData.getTitle(), dbData.getContent(),user);
}
}
DBData1
package ex01;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@NoArgsConstructor
@AllArgsConstructor
@Data
public class DBData1 {
//평평한 데이터는 테이블 데이터
private int boardId;
private String title;
private String content;
private int userId;
private String username;
private String email;
}
viewdata1
package ex01;
import ex01.model.User;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@AllArgsConstructor
@NoArgsConstructor
@Data
//굴곡진 데이터
public class ViewData1 {
private int boardId;
private String title;
private String content;
private User user;
}
2. ex01v2
user
package ex01v2.model;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@NoArgsConstructor
@AllArgsConstructor
@Data
public class User {
private int userId;
private String username;
private String email;
}
App1
package ex01v2;
import ex01.model.User;
public class App1 {
public static void main(String[] args) {
// 1. DB에서 가져온 데이터 - Flat(평평) 하게 가져올 수 밖에 없다
DBData1 dbData = new DBData1(1, "제목1", "내용1", 3, "love", "love@nate.com");
//DBData1는 db에서 조회한 데이터
//ViewData1는 view 에 뿌리기 위해
// 2. dbData1를 ViewData1에 옮기시오 - ORM
//오류가 나서 주석처리 이렇게 하는거임
ViewData1 viewData = new ViewData1(dbData);
}
}
dbdata1
package ex01v2;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@NoArgsConstructor
@AllArgsConstructor
@Data
public class DBData1 {
//평평한 데이터는 테이블 데이터
private int boardId;
private String title;
private String content;
private int userId;
private String username;
private String email;
}
viewdata1
package ex01v2;
import ex01.model.User;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
//굴곡진 데이터
public class ViewData1 {
private int boardId;
private String title;
private String content;
private User user;
//생성자 직접 만들어야됨
public ViewData1(DBData1 dbData) {
this.boardId = dbData.getBoardId();
this.title = dbData.getTitle();
this.content = dbData.getContent();
this.user = new User(dbData.getUserId(), dbData.getUsername(), dbData.getEmail());
}
}
3. ex01v3
user
package ex01v3.model;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@NoArgsConstructor
@AllArgsConstructor
@Data
public class User {
private int userId;
private String username;
private String email;
}
App1
package ex01v3;
public class App1 {
public static void main(String[] args) {
// 1. DB에서 가져온 데이터 - Flat(평평) 하게 가져올 수 밖에 없다
DBData1 dbData = new DBData1(1, "제목1", "내용1", 3, "love", "love@nate.com");
//DBData1는 db에서 조회한 데이터
//ViewData1는 view 에 뿌리기 위해
// 2. dbData1를 ViewData1에 옮기시오 - ORM
ViewData1 viewData1 = dbData.toViewData();
}
}
dbdata
package ex01v3;
import ex01.model.User;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@NoArgsConstructor
@AllArgsConstructor
@Data
public class DBData1 {
//평평한 데이터는 테이블 데이터
private int boardId;
private String title;
private String content;
private int userId;
private String username;
private String email;
public ViewData1 toViewData(){
return new ViewData1(boardId,title,content,new User(userId,username,email));
}
}
viewdata
package ex01v3;
import ex01.model.User;
import ex01v2.DBData1;
import lombok.AllArgsConstructor;
import lombok.Data;
@AllArgsConstructor
@Data
//굴곡진 데이터
public class ViewData1 {
private int boardId;
private String title;
private String content;
private User user;
//생성자 직접 만들어야됨
}
4. ex02
reply
package ex02.model;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@NoArgsConstructor
@AllArgsConstructor
@Data
public class Reply {
private int replyId;
private String comment;
}
app
package ex02;
import ex02.model.Reply;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class App2 {
public static void main(String[] args) {
// 1. DB에서 가져온 데이터 - Flat(평평) 하게 가져올 수 밖에 없다
DBData2 dbData1 = new DBData2(1, "제목1", "내용1", 1, "댓글1");
DBData2 dbData2 = new DBData2(1, "제목1", "내용1", 2, "댓글2");
DBData2 dbData3 = new DBData2(1, "제목1", "내용1", 3, "댓글3");
List<DBData2> dbList = Arrays.asList(dbData1, dbData2, dbData3);
// 2. ddbList(컬렉션을) ViewData(오브젝트)에 옮기시오 - ORM
if(dbList.size()==0)return; // dbList 값이 없으면 종료
ViewData2 viewData2 = new ViewData2(
dbList.get(0).getBoardId(),
dbList.get(0).getTitle(),
dbList.get(0).getContent()
);
for(DBData2 data : dbList){
Reply r = new Reply(data.getReplyId(), data.getComment());
viewData2.addReply(r);
}
}
}
dbdata
package ex02;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@NoArgsConstructor
@AllArgsConstructor
@Data
public class DBData2 {
private int boardId;
private String title;
private String content;
private int replyId;
private String comment;
}
viewdata
package ex02;
import ex02.model.Reply;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.ArrayList;
import java.util.List;
@NoArgsConstructor
@Data
public class ViewData2 {
private int boardId;
private String title;
private String content;
// Board 데이터만 넣는 생성자
public ViewData2(int boardId, String title, String content) {
this.boardId = boardId;
this.title = title;
this.content = content;
}
// 댓글들은 addReply로 추가하기
private List<Reply> replies = new ArrayList<>();
public void addReply(Reply reply){
replies.add(reply);
}
}
5. ex02v2
Reply
package ex02v2.model;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@NoArgsConstructor
@AllArgsConstructor
@Data
public class Reply {
private int replyId;
private String comment;
}
App
package ex02v2;
import java.util.Arrays;
import java.util.List;
public class App2 {
public static void main(String[] args) {
// 1. DB에서 가져온 데이터 - Flat(평평) 하게 가져올 수 밖에 없다
DBData2 dbData1 = new DBData2(1, "제목1", "내용1", 1, "댓글1");
DBData2 dbData2 = new DBData2(1, "제목1", "내용1", 2, "댓글2");
DBData2 dbData3 = new DBData2(1, "제목1", "내용1", 3, "댓글3");
List<DBData2> dbList = Arrays.asList(dbData1, dbData2, dbData3);
// 2. ddbList(컬렉션을) ViewData(오브젝트)에 옮기시오 - ORM
ViewData2 viewData2 = new ViewData2(dbList);
System.out.println(viewData2);
}
}
DBData2
package ex02v2;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@NoArgsConstructor
@AllArgsConstructor
@Data
public class DBData2 {
private int boardId;
private String title;
private String content;
private int replyId;
private String comment;
}
ViewData2
package ex02v2;
import ex02.model.Reply;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.ArrayList;
import java.util.List;
@AllArgsConstructor
@NoArgsConstructor
@Data
public class ViewData2 {
private int boardId;
private String title;
private String content;
// 댓글들은 addReply로 추가하기
private List<Reply> replies = new ArrayList<>();
// Board 데이터만 넣는 생성자
public void addReply(Reply reply){
replies.add(reply);
}
public ViewData2(List<DBData2> dbList) {
if(dbList.size()>0){
this.boardId = dbList.get(0).getBoardId();
this.title = dbList.get(0).getTitle();
this.content = dbList.get(0).getContent();
}
// dbList.stream().forEach(db ->{
// addReply(new Reply(db.getReplyId(),db.getComment()));
// } );
//이렇게 해도 됨.
// replies = dbList.stream().map(db ->new Reply(db.getReplyId(),db.getComment())).toList();
for(DBData2 data : dbList){
Reply r = new Reply(data.getReplyId(),data.getComment());
addReply(r);
}
}
}
Share article