@Slf4j
public class JDBCTest {
static final String JDBC_DRIVER = "org.h2.Driver";
static final String DB_URL = "jdbc:h2:~/test";
static final String USER = "sa";
static final String PASS = "";
static final String DROP_TABLE_SQL = "DROP TABLE customers IF EXISTS";
static final String CREATE_TABLE_SQL = "CREATE TABLE customers(id SERIAL, first_name VARCHAR(255), last_name VARCHAR(255))";
static final String INSERT_SQL = "INSERT INTO customers (id, first_name, last_name) VALUES(1, 'honggu', 'kang')";
@Test
void jdbc_sample() {
try {
Class.forName(JDBC_DRIVER); // JDBC DRIBER 구현체
Connection connection = DriverManager.getConnection(DB_URL, USER, PASS);
log.info("Connection 획득");
Statement statement = connection.createStatement();//statement 객체를 통해 쿼리 날림
log.info("Statement 획득");
log.info("쿼리 실행");
statement.executeUpdate(DROP_TABLE_SQL);
statement.executeUpdate(CREATE_TABLE_SQL);
log.info("CRATED TABLE");
statement.executeUpdate(INSERT_SQL);
//ResultSet : 조회된 쿼리정보를 순환할수 있는 객체(업데이트성이 아닌 조회 쿼리에 이용)
ResultSet resultSet = statement.executeQuery("SELECT id, first_name, last_name FROM customers WHERE id = 1");
while(resultSet.next()) {
String fullName = resultSet.getString("first_name")+""+resultSet.getString("last_name");
//log.info(resultSet.getString("first_name"));
log.info("CUSTOMER FULL_NAME:{}",fullName);
}
log.info("반납, 반납");
statement.close();
connection.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
- 어떤 드라이버 쓸것인지 명시
- 컨넥션을 생성해 획득한 컨낵션을 통해 Statement객체를 만들고
Statement객체를 통해 통신- ResultSet을 통해 결과값을 조회
- 사용한 컨넥션 객체나 statement를 반납함
@Slf4j
@SpringBootTest //SpirngApplicationContext를 이용하기 위해
public class JDBCTest {
static final String JDBC_DRIVER = "org.h2.Driver";
static final String DB_URL = "jdbc:h2:~/test";
static final String USER = "sa";
static final String PASS = "";
static final String DROP_TABLE_SQL = "DROP TABLE customers IF EXISTS";
static final String CREATE_TABLE_SQL = "CREATE TABLE customers(id SERIAL, first_name VARCHAR(255), last_name VARCHAR(255))";
static final String INSERT_SQL = "INSERT INTO customers (id, first_name, last_name) VALUES(1, 'honggu', 'kang')";
@Autowired
JdbcTemplate jdbcTemplate;
@Test
void jdbcTemplate_sample(){
jdbcTemplate.update(DROP_TABLE_SQL);
jdbcTemplate.update(CREATE_TABLE_SQL);
log.info("Created Table Using Jdbc Template");
jdbcTemplate.update(INSERT_SQL);
log.info("INSERTED CUSTOMER INFORMATION USING JDBC TEMPLATE");
String fullName = jdbcTemplate.queryForObject(
"SELECT * FROM customers WHERE id = 1",
(resultSet,i) -> resultSet.getString("first_name")+" "+ resultSet.getString("last_name")
);
log.info("FULL_NAME : {}",fullName);
}
}
- JDBC Template를 이용해서, 데이터 계층에 접근이 가능
- 기존 JDBC를 이용했을때의 반복적인 작업을 JDBC Template이 대신 수행(코드간략)
- 한계: 자바 코드상에 sql문이 있음 -> 유지 보수 어려움 -> QueryMapper 등장
type-aliases-package:
자바객체가 resulteset의 결과를 자동으로 매핑 해줌
그런 쿼리결과를 어떤객체에 매핑할지 패키지에 명시 해줄 것인지
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.kdt.lecture.kdtchapter1.repository.CustomerXmlMapper">
<insert id="save">
INSERT INTO customers (id, first_name, last_name)
VALUES (#{id}, #{firstName}, #{lastName})
</insert>
<update id="update">
UPDATE customers
SET first_name=#{firstName},
last_name=#{lastName}
WHERE id = #{id}
</update>
<select id="findById" resultType="customers">
SELECT *
FROM customers
WHERE id = #{id}
</select>
<select id="findAll" resultType="customers">
SELECT *
FROM customers
</select>
</mapper>
//ResultSet의 결과를 개체에 매핑하기 위한 customer 객체
@Alias("customers") //테이블명 명시
public class Customer {
private long id;
private String firstName;
private String lastName;
public Customer(long id, String firstName, String lastName) {
this.id = id;
this.firstName = firstName;
this.lastName = lastName;
}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
}
-MYBATISTest
@Slf4j
@SpringBootTest
public class MybatisTest {
static final String DROP_TABLE_SQL = "DROP TABLE customers IF EXISTS";
static final String CREATE_TABLE_SQL = "CREATE TABLE customers(id SERIAL, first_name VARCHAR(255), last_name VARCHAR(255))";
@Autowired
JdbcTemplate jdbcTemplate;
@Autowired
CustomerMapper customerMapper;
@Test
void save_test(){
jdbcTemplate.update(DROP_TABLE_SQL);
jdbcTemplate.update(CREATE_TABLE_SQL);
customerMapper.save(new Customer(1L,"honggu","kang"));
Customer customer = customerMapper.findById(1L);
log.info("fullName:{} {}",customer.getFirstName(),customer.getLastName());
}
}
자바 코드상에 직접 쿼리를 날리는거에서 인터페이스를 이용해 자바코드와 쿼리를 분리
메서드 호출을 통해
직접쿼리를 작성해 자바 코드객체와 매핑시켜 쿼리결과를 객체로 변화시켜 가져올 수 있었음
@Entity
@Table(name = "customers") //테이블 이름으로 명시, 없을땐 클래스이름
public class CustomerEntity {
@Id
private long id;
private String firstName;
private String lastName;
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
}
package com.kdt.lecture.kdtchapter1.repository;
import com.kdt.lecture.kdtchapter1.repository.domain.CustomerEntity;
import org.springframework.data.jpa.repository.JpaRepository;
//인자로 Entity객체와 id이름
public interface CustomerRepository extends JpaRepository<CustomerEntity,Long> {
}
-JPATest
@SpringBootTest
@Transactional
@Slf4j
public class JPATest {
@Autowired
CustomerRepository repository;
@BeforeEach
void setUp() {
}
@AfterEach
void tearDown() {
repository.deleteAll();
}
@Test
void INSERT_TEST() {
// Given
CustomerEntity customer = new CustomerEntity();
customer.setId(1L);
customer.setFirstName("honggu");
customer.setLastName("kang");
// When
repository.save(customer); // INSERT INTO ..
// Then
CustomerEntity entity = repository.findById(1L).get(); // SELECT * FROM ..
log.info("{},{}", entity.getFirstName(), entity.getLastName());
}
@Test
@Transactional //영속성 컨텍스트 안에서 관리하겠다
void Update_Test() {
// Given
CustomerEntity customer = new CustomerEntity();
customer.setId(1L);
customer.setFirstName("honggu");
customer.setLastName("kang");
repository.save(customer);
// When
CustomerEntity entity = repository.findById(1L).get();
entity.setFirstName("guppy");
entity.setLastName("hong");
// Then
CustomerEntity updated = repository.findById(1L).get();
log.info("{} {}", updated.getFirstName(), updated.getLastName());
}
entity를 통해 테이블과 객체를 매핑
트랜잭션이 메서드가 실행할때 열리고 끝날떄 commit
영속성 컨텍스트에서 entitiy의 변경사항을 감지하고 있다가 entity의 속성이 변경되고
트랜잭션이 커밋 되면 자동으로 업데이트 쿼리가 날라감
-> 객체가 변경되면 테이블이 변경 : 테이블을 객체처럼 다룰수 있게 해줌
마이바티스나 ㅓㅔㅁqhek 간결하게 작성
변경에 유연함
jpa인터페ㅣㅇ스 중에서 하이버네이트 사용