자바의 ORM 기술 표준
JAP가 개발자 대신 적합한 SQL을 생성하고 DB에 전달하고, 객체를 자동으로 Mapping 해주기에 SQL을 직접 작성할 필요가 없다.
ex) Hibernate ( JPA를 구현한 대표적 오픈소스)
장점 | 단점 |
생산성이 뛰어나고 유지보수가 용이하다 | JPA의 장점을 살려 잘 사용하기 위해서는 학습 비용이 높고, 복잡한 쿼리를 사용할 때 불리하다. |
DBMS에 대한 종속성이 줄어든다. | 잘못 사용할 경우 SQL을 직접 사용하는 것보다 성능이 떨어질 수 있다. |
JPA 사용하기
1. build.gradle
- JPA를 사용하기 위해 dependency 추가
2. application.properties 수정
#기본 설정
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/sesac?useUnicode=yes&characterEncoding=UTF-8&allowMultiQueries=true&serverTimezone=Asia/Seoul
spring.datasource.username=root
spring.datasource.password=3306
#mysql connect
spring.jpa.database=sesac
spring.jpa.database-platform=org.hibernate.dialect.MySQL5InnoDBDialect
#DB function use
spring.jpa.show-sql = true
spring.jpa.hibernate.ddl-auto=create
# none : not create / create : auto create / update : only update structure
logging.level.org.hibernate=info
spring.jpa.properties.hibernate.show_sql=true
spring.jpa.properties.hibernate.format_sql=true
spring.jpa.properties.hibernate.use_sql_comments=true
- create : 정의되어 있는 table을 기반으로 만들어준다. 아무리 데이터를 많이 넣어도 삭제하고 다시시 만듦
- 데이터 정보를 유지하고 싶으면 update를 해야한다.
Entity
- 데이터베이스에 쓰일 필드와 여러 Entity 간의 관계를 설정하는 것
- @Entity를 이용해 해당 클래스가 Entity임을 알려주고, JPA에 정의된 필드를 바탕으로 데이터베이스에 테이블을 만들 수 있다.
Entity 관련 Annotation
@Entity | 데이터베이스의 Table 임을 의미 | @Table | 테이블의 이름 명시 |
@Id | primary key를 의미 | @GeneratedValue | primary key의 생성 전략 |
@Column | 테이블의 컬럼을 의미 |
3. domain/UserEntity
package sesac.jdbc.sesac.jdbc.domain;
import lombok.Getter;
import lombok.Setter;
import javax.persistence.*;
@Entity // 해당 클래스가 Entity 클래스라는 것을 알려준다.
@Table(name="user") // 테이블 이름 명시
@Getter
@Setter
public class UserEntity {
@Id
@GeneratedValue // AutoIncrement
private int id; // id primary key auto_increment
@Column(length = 5, nullable = false) // 길이, null 허용 여부
private String name;
// nickname varchar(10) not null
@Column(length = 10, nullable = false)
private String nickname;
}
4. repository/UserRepository
Repository
- Entity에 의해 생성된 DB에 접근하는 메서드를 사용하기 위한 인터페이스
- JPARepository를 상속받으면 기본적인 DB 접근 메서드를 사용할 수 있다.
- findAll( ) , findById( ), findBy컬럼명( ), save( )
package sesac.jdbc.sesac.jdbc.repository;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import sesac.jdbc.sesac.jdbc.domain.UserEntity;
import java.util.Optional;
@Repository
public interface UserRepository extends JpaRepository<UserEntity, Integer> {
Optional<UserEntity> findByName(String name); // SELECT ~~ WHERE name = #{name}
// Optional<UserEntity> findById(int id); // SELECT ~~ WHERE id = #{id}
// Optional<UserEntity> findByIdName(int id, String name); // SELECT ~~ WHERE id = #{id} AND name= #{name}
// findBy뒤에 대문자로 오는 컬럼을 기준으로 불러온다. (jpa 기능)
// UserEntity userEntity
// Optional<UserEntity> user; user.get()
// null 일 수도 있는 객체를 담는 클래스
}
5. Service/MainService
Optional
- Null 일 수도 있는 객체를 감싸는 Wrapper 클래스
- Optional<T> option
- Option 변수 내부에는 null이 아닌 T 객체가 있을 수도 있고 null이 있을 수도 있다.
- 즉, Optional 클래스는 여러가지 API를 제공해 null일 수도 아닐 수도 있는 객체를 다룰 수 있다.
- nullexception 오류를 예방하기 위해서 optional을 사용
@Service
public class MainService {
@Autowired
private UserRepository userRepository;
public List<UserDTO> getUserList() {
List<UserEntity> result = userRepository.findAll(); // select * from
List<UserDTO> users = new ArrayList<UserDTO>();
for(int i=0; i<result.size();i++) {
UserDTO user = new UserDTO();
user.setId(result.get(i).getId());
user.setName(result.get(i).getName());
user.setNickname(result.get(i).getNickname());
user.setNo(i+1); // no는 전달하기 위한 값
users.add(user);
}
return users;
}
public void addUser(UserEntity user) {
userRepository.save(user); // insert into
}
public ArrayList<UserDTO> getUserName(String name) {
Optional<UserEntity> user = userRepository.findByName(name);
ArrayList<UserDTO> userList = new ArrayList<>();
if(user.isPresent()) {
UserDTO dto = new UserDTO();
dto.setId(user.get().getId());
dto.setNo(0);
dto.setName(user.get().getName());
dto.setNickname(user.get().getNickname());
userList.add(dto);
}
return userList;
}
}
6. controller/MainController
@Controller
public class MainController {
@Autowired
MainService mainService;
@GetMapping("/users")
public String getUsers(Model model) {
ArrayList<UserDTO> userList = (ArrayList<UserDTO>) mainService.getUserList();
model.addAttribute("list", userList);
return "user";
}
@GetMapping("/user/insert")
public String getInsertUser(@RequestParam String name, @RequestParam String nickname, Model model) {
UserEntity user = new UserEntity();
user.setName(name);
user.setNickname(nickname);
mainService.addUser(user);
model.addAttribute("list", null);
return "user";
}
@GetMapping("/user")
public String getUser(@RequestParam String name, Model model) {
ArrayList<UserDTO> userList = mainService.getUserName(name);
model.addAttribute("list", userList);
return "user";
}
}
<결과>
localhost:8080/users를 하면 DB와 연결된 모든 유저들을 볼 수 있다.
localhoat:8080/user/insert?name=이름&nickname=닉네임을 하면 user 디비에 추가할 수 있다.
localhost:8080/user?name=이름 을 하면 name을 기준으로 한 컬럼을 select 할 수 있다.
- myBatis로만 해봤는데 JPA를 배우니까 mybatis를 안쓰고 JPA를 쓰는 이유를 알겠다....
- sequelize를 쓰는 것 같은 느낌이다. JPA를 쓰기 위해 API를 좀 더 공부해야 겠다는 생각이 든다. (기존 SQL문을 잘 다룬다는 하에ㅣ...!)
'Sesac 웹 풀스택[새싹X코딩온] > Spring' 카테고리의 다른 글
5. JDBC, MyBatis 연결 (0) | 2023.03.16 |
---|---|
4. GET, POST 방식 및 DTO, VO 전송 (0) | 2023.03.16 |
3. Rest API 정의(DTO,VO, Annotation) (0) | 2023.03.11 |
2. Spring Boot 사용하기(feat: Intellij, Spring initializer, thymeleaf) (0) | 2023.03.09 |
1. Spring framework 특징 (0) | 2023.03.09 |