๐ 2024๋ 01์ 16์ผ
- build.gradle
# ์์กด์ฑ ์ถ๊ฐ implementation 'org.springframework.boot:spring-boot-starter-jdbc' implementation 'org.mariadb.jdbc:mariadb-java-client'
- application.yml
server: port: 8080 spring: profiles: active: dev datasource: url: jdbc:mariadb//localhost:3306/member username: ์ฌ์ฉ์ ์์ด๋ password: ์ฌ์ฉ์ ๋น๋ฐ๋ฒํธ
- MemberJdbcRepository
@Repository public class MemberJdbcRepository implements MemberRepository { @Autowired private DataSource dataSource; @Override public List<Member> findAll() { try { Connection connection = dataSource.getConnection(); String sql = "select * from member"; PreparedStatement preparedStatement = connection.prepareStatement(sql); ResultSet resultSet = preparedStatement.executeQuery(); List<Member> members = new ArrayList<>(); while(resultSet.next()){ int id = resultSet.getInt("id"); String name = resultSet.getString("name"); String emil = resultSet.getString("email"); String password = resultSet.getString("password"); LocalDateTime creat_at = resultSet.getTimestamp("create_at").toLocalDateTime(); Member member = new Member(name, emil, password); member.setId(id); member.setCreate_at(creat_at); members.add(member); } return members; }catch (SQLException e){ e.printStackTrace(); } return null; } @Override public Member save(Member member) { try { Connection connection = dataSource.getConnection(); String sql = "insert into member(name,email,password) values(?,?,?)"; PreparedStatement preparedStatement = connection.prepareStatement(sql); preparedStatement.setString(1,member.getName()); preparedStatement.setString(2,member.getEmail()); preparedStatement.setString(3,member.getPassword()); preparedStatement.executeUpdate(); }catch (SQLException e){ e.printStackTrace(); } return null; } @Override public Optional<Member> findById(long id) { Member member = null; try { Connection connection = dataSource.getConnection(); String sql = "select * from member where id = ?"; PreparedStatement preparedStatement = connection.prepareStatement(sql); preparedStatement.setLong(1, id); ResultSet resultSet = preparedStatement.executeQuery(); while(resultSet.next()){ int idx = resultSet.getInt("id"); String name = resultSet.getString("name"); String emil = resultSet.getString("email"); String password = resultSet.getString("password"); LocalDateTime creat_at = resultSet.getTimestamp("create_at").toLocalDateTime(); member = new Member(name, emil, password); member.setId(idx); member.setCreate_at(creat_at); } }catch (SQLException e){ e.printStackTrace(); } return Optional.ofNullable(member); } }
- Member
public class Member { private long id; private String name; private String email; private String password; private LocalDateTime create_at; public Member(String name, String email, String password) { this.name = name; this.email = email; this.password = password; this.create_at = LocalDateTime.now(); } public Member() { }
JDBC์ ๊ตฌ์ฑ์์
1. JDBC ๋๋ผ์ด๋ฒ: ํน์ ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ํต์ ํ๊ธฐ ์ํ ๋๋ผ์ด๋ฒ๊ฐ ํ์ํ๋ฉฐ, ๊ฐ ๋ฐ์ดํฐ๋ฒ ์ด์ค ๋ฒค๋๋ ํด๋น ๋๋ผ์ด๋ฒ๋ฅผ ์ ๊ณตํ๋ค. 2. JDBC URL: ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ์ฐ๊ฒฐํ๊ธฐ ์ํ URL๋ก, ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ์์น ๋ฐ ์ฐ๊ฒฐ์ ํ์ํ ๋งค๊ฐ๋ณ์๋ฅผ ํฌํจํ๋ค. 3. Connection ๊ฐ์ฒด: java.sql.Connection ์ธํฐํ์ด์ค๋ฅผ ๊ตฌํํ ๊ฐ์ฒด๋ก, ๋ฐ์ดํฐ๋ฒ ์ด์ค์์ ์ฐ๊ฒฐ์ ์ค์ ํ๋ค. 4. Statement ๊ฐ์ฒด: SQL ์ฟผ๋ฆฌ๋ฅผ ์คํํ๊ธฐ ์ํ java.sql.Statement ์ธํฐํ์ด์ค๋ฅผ ๊ตฌํํ ๊ฐ์ฒด๋ก, SQL ๋ฌธ์ ์คํํ๊ณ ๊ฒฐ๊ณผ๋ฅผ ๋ฐ์์จ๋ค. 5. ResultSet ๊ฐ์ฒด: SQL ์ฟผ๋ฆฌ์ ๊ฒฐ๊ณผ๋ฅผ ์ ์ฅํ๋ java.sql.ResultSet ์ธํฐํ์ด์ค๋ฅผ ๊ตฌํํ ๊ฐ์ฒด๋ก, ์ฟผ๋ฆฌ ๊ฒฐ๊ณผ๋ฅผ ๊ฐ์ ธ์์ ์ฒ๋ฆฌํ๋ค.
- build.gradle
# ์์กด์ฑ ์ถ๊ฐ implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
- application.yml
jpa: database: mysql database-platform: org.hibernate.dialect.MariaDBDialect generate-ddl: true hibernate: # create = ํ ์ด๋ธ ์ญ์ ํ ์์ฑ # update = ๋ณ๊ฒฝ์ฌํญ๋ง ์์ ํด ์ ์ฉ # validate = ์ค์ DB ์์ ์ฐจ์ด๋ง์ ํ์ธ # ์ค๋ฌด์์ update ๋๋ validate ddl-auto: create # jap ๊ฐ ์๋์ผ๋ก ์ฟผ๋ฆฌ๋ฅผ ์คํํ ๋, ์ฟผ๋ฆฌ๊ฐ ์ฝ์์ฐฝ์ ๋ณด์ฌ์ง๋๋ก ์ค์ # jap ๊ฐ ์๋์ผ๋ก ์ฟผ๋ฆฌ๋ฅผ ์คํํ ๋, ์ฟผ๋ฆฌ๊ฐ ์ฝ์์ฐฝ์ ๋ณด์ฌ์ง๋๋ก ์ค์ show-sql: true
- MemberSpringDataJpaRepository
import com.encore.Spring_basic.domain.Member; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Query; import org.springframework.stereotype.Repository; @Repository /* spring data jpa ์ ๊ธฐ๋ณธ ๊ธฐ๋ฅ์ ์ฐ๊ธฐ ์ํด์๋ JpaRepository๋ฅผ ์์กํด์ผํจ ์์์์ entity ๋ช ๊ณผ ํด๋น pk ํ์ ๋ช ์ ์ค์ง์ ์ธ ๊ตฌํํด๋์ค์ ์คํฉ์ SimpleJpaRepository ํด๋์ค์ ์๊ณ ์ค์ง์ ์ธ ๊ตฌ๋์ํฉ์์ hibernate ๊ตฌํ์ฒด์ ๋์์์. SimpleJpaRepository: ๊ธฐ๋ณธ ๊ตฌํ์ฒด๋ก์ ๊ฐ์ฅ ์ผ๋ฐ์ ์ผ๋ก ์ฌ์ฉ๋ฉ๋๋ค. CRUD ๋ฉ์๋๋ฅผ ๊ตฌํํ๊ณ Spring Data JPA ์ ํน์ง์ ์ง์. QuerydslJpaRepository: Querydsl ์ ์ฌ์ฉํ์ฌ ๋์ ์ฟผ๋ฆฌ๋ฅผ ์์ฑํ ์ ์๋๋ก ์ง์ํ๋ ๊ตฌํ์ฒด. Querydsl ์ ํ์ ์์ ํ ์ฟผ๋ฆฌ๋ฅผ ์์ฑํ๋ ๋ฐ ๋์์ ์ฃผ๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ. SimpleJpaBatchRepository: ๋๋ ๋ฐ์ดํฐ ์ฒ๋ฆฌ์ ์ต์ ํ๋ ๊ตฌํ์ฒด, ๋ฐฐ์น ์์ ์ ์ฌ์ฉ๋ ์ ์๋ค. QueryByExampleExecutor: ์์ ๊ฐ์ฒด๋ฅผ ์ฌ์ฉํ์ฌ ๋์ ์ฟผ๋ฆฌ๋ฅผ ์ํํ๋ ๋ฐ ์ฌ์ฉ๋๋ ๊ตฌํ์ฒด. JdbcRepository: JDB C๋ฅผ ์ง์ ์ฌ์ฉํ๋ ๊ตฌํ์ฒด๋ก, JPA ๋ฅผ ์ฌ์ฉํ์ง ์๊ณ ์ง์ SQL ์ฟผ๋ฆฌ๋ฅผ ์์ฑํ๋ ๊ฒฝ์ฐ์ ์ ์ฉํ ์ ์๋ค. */ public interface MemberSpringDataJpaRepository extends MemberRepository, JpaRepository<Member, Long> { }
@Getter
@AllArgsConstructor
/*
@Entity ๋ฅผ ํตํด DB ํ
์ด๋ธ ๋ฐ ์ปฌ๋ผ์ ์๋ ์์ฑ
*/
@Entity
public class Member {
@Setter
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
private String name;
@Column(nullable = false, length = 50)
private String email;
private String password;
@Setter
@Column(name = "created_at")
private LocalDateTime create_at;
}
Spring ํ๋ ์์ํฌ์ ์ผ๋ถ๋ก, ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ์ํธ์์ฉ์ ๋จ์ํํ๊ณ ๊ฐ์ฒด ์งํฅ์ ์ธ ๋ฐ์ดํฐ ์ก์ธ์ค๋ฅผ ์ง์ํ๋ ๋ชจ๋
1. Repository ์ธํฐํ์ด์ค: ์ธํฐํ์ด์ค๋ฅผ ์ ์ํ๊ณ ์ด๋ฅผ ๊ตฌํํ ๊ฐ์ฒด๋ฅผ ์๋์ผ๋ก ์์ฑํ์ฌ CRUD ์ฐ์ฐ์ ์ ๊ณตํ๋ค.
2. ์ฟผ๋ฆฌ ๋ฉ์๋: ๋ฉ์๋ ์ด๋ฆ์ ๊ธฐ๋ฐ์ผ๋ก ์๋์ผ๋ก ์ฟผ๋ฆฌ๋ฅผ ์์ฑํ ์ ์์ผ๋ฉฐ, ๊ฐ๋จํ ๋ฉ์๋ ์ ์ธ์ผ๋ก ๋ฐ์ดํฐ๋ฒ ์ด์ค ๊ฒ์์ด ๊ฐ๋ฅํ๋ค.
3. ๋์ ์ฟผ๋ฆฌ ์์ฑ: ์กฐ๊ฑด์ ๋ฐ๋ผ ๋์ ์ผ๋ก ์ฟผ๋ฆฌ๋ฅผ ์์ฑํ ์ ์์ด ์ ์ฐํ ์ฟผ๋ฆฌ ์์ฑ์ด ๊ฐ๋ฅํ๋ค.
4. Entity ๋งคํ: JPA ์ํฐํฐ๋ฅผ ์ฌ์ฉํ์ฌ ๋ฐ์ดํฐ๋ฒ ์ด์ค ํ
์ด๋ธ๊ณผ์ ๋งคํ์ ์ํํ๋ฉฐ, ๊ฐ์ฒด ์งํฅ์ ์ธ ๋ฐฉ์์ผ๋ก ๋ฐ์ดํฐ๋ฅผ ์ฒ๋ฆฌํ๋ค.
5. ํ์ด์ง ๋ฐ ์ ๋ ฌ ๊ธฐ๋ฅ: ๋๋์ ๋ฐ์ดํฐ๋ฅผ ํจ๊ณผ์ ์ผ๋ก ์ฒ๋ฆฌํ๊ธฐ ์ํ ํ์ด์ง๊ณผ ์ ๋ ฌ ๊ธฐ๋ฅ์ ์ ๊ณตํ๋ค.
6. ์ฌ์ฉ์ ์ ์ ์ฟผ๋ฆฌ: JPQL์ด๋ ๋ค์ดํฐ๋ธ ์ฟผ๋ฆฌ๋ฅผ ์ฌ์ฉํ์ฌ ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ์ง์ ์ ๊ทผํ ์ ์๋ค.
- build.gradle
# ์์กด์ฑ ์ถ๊ฐ implementation 'org.mybatis.spring.boot:mybatis-spring-boot-starter:2.2.0'
- application.yml
mybatis: mapper-locations: classpath:/mapper/**/*.xml
- MemberMyBatisRepository
/* MyBatis ์ฐ๊ฒ ๋ค๋ ์ด๋ ธํ ์ด์ */ @Mapper @Repository public interface MemberMyBatisRepository extends MemberRepository{ /* ๋ณธ๋ฌธ์ MyBatisRepository ์์ ์ฌ์ฉํ ๋ฉ์๋ ํ์์ ์ ์ํด์ผ ํ๋, MemberRepository์์ ์์ ๋ฐ๊ณ ์์ผ๋ฏ๋ก, ์๋ต ๊ฐ๋ฅ ์ค์ง์ ์ธ ์ฟผ๋ฆฌ๋ฑ ๊ตฌํ์ resources/mapper/MemberMapper.xml ํ์ผ์ ์ํ */ }
- MemberMapper.xml
<?xml version="1.0" encoding="UTF-8" ?> <!-- mapper DTD ์ ์ธ --> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.encore.Spring_basic.repository.MemberMyBatisRepository"> <!-- ์ ์ฅ (Save) --> <select id="save"> INSERT INTO member(name, email, password ) VALUES (#{name}, #{email}, #{password}) </select> <!-- <insert id="save">--> <!-- INSERT INTO member(name, email, password, created_at) VALUES--> <!-- (#{name}, #{email}, #{password}, #{create_at})--> <!-- </insert>--> <select id="save" resultType="com.encore.Spring_basic.domain.Member"> INSERT INTO member(name, email, password, created_at) VALUES (#{name}, #{email}, #{password}, #{create_at}) </select> <!-- ์ ์ฒด ์กฐํ (FindAll) --> <select id="findAll" resultType="com.encore.Spring_basic.domain.Member"> SELECT * FROM member </select> </mapper>
MyBatis๋?
์๋ฐ ๊ธฐ๋ฐ์ ๋ฐ์ดํฐ๋ฒ ์ด์ค ์ฐ๋ ํ๋ ์์ํฌ๋ก, SQL ์ฟผ๋ฆฌ์ ์๋ฐ ๊ฐ์ฒด ๊ฐ์ ๋งคํ์ ์ฒ๋ฆฌํ๋ค.
1. SQL ๋งคํ: SQL ์ฟผ๋ฆฌ์ ์๋ฐ ๊ฐ์ฒด๋ฅผ XML ๋๋ ์ด๋ ธํ ์ด์ ์ ํตํด ๊ฐ๋จํ๊ฒ ๋งคํํ๋ค. 2. ๋์ SQL: ๋์ ์ธ ์ฟผ๋ฆฌ๋ฅผ ์ฝ๊ฒ ์์ฑํ๊ณ ๊ด๋ฆฌํ ์ ์๋ ๊ฐ๋ ฅํ ๋์ SQL ์์ฑ ๊ธฐ๋ฅ์ ์ ๊ณตํ๋ค. 3. ์๋ ๋งคํ: ์ฟผ๋ฆฌ ๊ฒฐ๊ณผ๋ฅผ ์๋์ผ๋ก ์๋ฐ ๊ฐ์ฒด์ ๋งคํํด์ฃผ๋ ๊ธฐ๋ฅ์ด ์๋ค. 4. ํธ๋์ญ์ ๊ด๋ฆฌ: JDBC์ ํธ๋์ญ์ ์ ๊ฐํธํ๊ฒ ์ ์ดํ ์ ์๋ค. 5. ๋ค์ํ ๋ฐ์ดํฐ๋ฒ ์ด์ค ์ง์: ๋ค์ํ ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ๋ํ ์ง์์ ์ ๊ณตํ๋ฉฐ, ์ค์ ์ ํตํด ๊ฐ๋จํ๊ฒ ๋ฐ์ดํฐ๋ฒ ์ด์ค๋ฅผ ๋ณ๊ฒฝํ ์ ์๋ค.