**Spring에서의 Transaction 사용
1. Spring에서의 Transaction 사용을 위한 설정
=> TransactionManager 클래스의 bean을 생성
=> 연동하는 프레임 워크에 따라 다르게 생성
=> Spring JDBC와 MyBatis를 사용할 때는 동일한 방식으로 생성
- DataSourceTransactionManager 클래스의 bean 생성, 이 때 dataSource 프로퍼티에 DataSource 빈 주입
=> Hibernate는 위와는 다른 방식으로 생성
- Hibernate는 트랜잭션 사용이 필수
2. 적용
=> 데이터베이스 작업을 수행하는 메소드 위에 @Transactional을 추가하는 방법
=> xml 파일에 tx:advice 와 tx:method 태그를 이용하여 설정하는 방식
3. 트랜잭션 적용
=> Service에 적용
**트랜잭션 실습
1. Simple Spring Maven Project 생성
2. 필요한 의존성 라이브러리를 pom.xml 파일에 작성
=> Oracle, Spring-JDBC
1) Oracle을 위한 Repository 생성
<repositories>
<repository>
<id>oracle</id>
<name>ORACLE JDBC Repository</name>
<url>http://maven.jahia.org/maven2</url>
</repository>
</repositories>
2) Oracle, Spring의 의존성을 dependencies에 추가
<!-- 오라클 -->
<dependency>
<groupId>com.oracle</groupId>
<artifactId>ojdbc7</artifactId>
<version>12.1.0.2</version>
</dependency>
<!-- 스프링에서 데이터베이스 사용을 위한 의존성 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>${spring-framework.version}</version>
</dependency>
3. SpringBeanConfiguration 파일생성, DB 접속정보를 저장하는 DataSource 클래스의 Bean을 추가하는 코드를 작성
=> Spring MVC Project이면 파일을 생성할 필요없고 제공되는 파일에 코드를 작성
<!-- Oracle -->
<bean
class="org.springframework.jdbc.datasource.DriverManagerDataSource"
id="dataSource">
<property name="driverClassName"
value="oracle.jdbc.driver.OracleDriver"/>
<property name="url"
value="jdbc:oracle:thin:@192.168.0.200:1521:xe"/>
<property name="username" value="system"/>
<property name="password" value="********" />
</bean>
4. main메소드를 소유한 클래스를 src(src/main/java) 디렉토리에 생성하고 데이터베이스 접속을 테스트
public static void main(String[] args) {
try {
//스프링 설정 파일의 경로를 설정
GenericXmlApplicationContext context =
new GenericXmlApplicationContext("applicationContext.xml");
//데이터베이스 접속 정보 가져오기
DataSource ds = context.getBean(DataSource.class);
Connection con = ds.getConnection();
System.out.println(con);
context.close();
}catch (Exception e) {
System.out.println(e.getMessage());
e.printStackTrace();
}
}
5. 트랜잭션 처리를 테스트할 DAO 클래스 생성하고 작성
=> hibernate.dao.TransactionDAO
@Repository
public class TransactionDAO {
//Spring JDBC 에서 제공하는 데이터 삽입 클래스의 변수
@Autowired
private SimpleJdbcInsert template;
public void insert() {
//테이블 이름 설정
template.withTableName("GOODS");
//삽입할 데이터 생성
Map<String, Object> map =
new HashMap<String, Object>();
map.put("code", 20);
map.put("name", "고구마");
map.put("regdate", new Date());
//동일한 데이터를 2번 삽입하므로 2번째 삽입할 때
//기본키 중복 예외 발생
template.execute(map);
template.execute(map);
}
}
6. applicationContext.xml 파일에 SimpleJdbcInsert 클래스의 bean을 생성해주는 코드와 DAO클래스의 bean을 자동생성해주는 코드를 작성
1) context 네임스페이스 추가
2) bean을 자동생성하기 위한 패키지 등록
<!-- SimpleJdbcInsert bean -->
<bean id="template"
class="org.springframework.jdbc.core.simple.SimpleJdbcInsert">
<constructor-arg>
<ref bean="dataSource" />
</constructor-arg>
</bean>
3) bean을 자동 생성하기 위한 패키지를 설정
<!-- bean을 자동 생성하기 위한 패키지 등록 -->
<context:annotation-config/>
<context:component-scan base-package="hibernate"/>
7. main 메소드를 소유한 클래스에서 DAO 클래스의 bean을 가져와서 메소드를 호출하는 코드를 작성하고 실행
//DAO 인스턴스를 가져와서 삽입하는 메소드 호출
TransactionDAO dao = context.getBean(TransactionDAO.class);
dao.insert();
8. 결과 확인
=> 트랜잭션을 적용하지 않았기 때문에 첫번째 삽입문장은 성공, 두번째 삽입문장은 실패
- Auto Commit이 적용되어 첫번째 삽입문장은 데이터베이스에 반영
**트랜잭션 적용
1. applicationContext.xml 파일에 tx 네임스페이스를 추가
2. applicationContext.xml 파일에 TransactionManager 클래스의 bean을 생성하여 등록하는 코드 추가
=> 데이터베이스 연동 프레임워크에 따라 달라짐
<!-- Spring JDBC나 MyBatis 에서의 트랜잭션처리를 위한 클래스의 bean -->
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>
<tx:annotation-driven transaction-manager="transactionManager"/>
3. DAO 메소드 상단에 @Transactional을 추가하고 실행
4. main 메소드를 실행하고 결과 확인
5. @Transactional이 적용된 메소드에서 예외 발생시 모든 DB작업이 취소됨
**ORM(Object Relationshop Mapper)
=> 관계형 데이터베이스의 테이블의 하나의 행을 하나의 객체와 매핑시켜 사용하는 데이터베이스 프레임워크
- 이때 사용되는 DTO 클래스나 Map 클래스로부터 만들어진 객체
=> 최근의 프로그래밍 언어에서는 데이터베이스 연동을 대부분 ORM방식을 이용하도록 권장
=> Java에서는 JPA, Apple의 Core Data, MS의 LINQ 등이 ORM 사용하는 대표적인 경우
=> SQL을 사용해도 되고, 자신들만의 문법으로 만들어진 쿼리문을 사용하기도 함
**Hibernate
=> Java ORM Framework
=> Java 진영에서 나중에 JPA라고하는 ORM 표준 Spec을 발표하고 실제 구현은 대부분 Hibernate로 함
1. SQL Mapper인 MyBatis(iBatis)와의 비교
=> Hibernate는 데이터베이스 구조를 알아야하기때문에 학습하는 것이 어렵지만 성능이 우수(Solution 개발에 이용)
- 데이터베이스를 새로 구축하는 경우 종종 이용
=> MyBatis는 학습이 쉽지만 성능은 Hibernate에 비해 떨어질 가능성이 높아 SI에 주로 이용됨
- 기존의 데이터베이스를 활용하는 경우에 종종 이용
2. Hibernate 구성요소
1) Configuration : 데이터베이스 테이블과 클래스 매핑 설정
2) SessionFactory : Configuration를 이용하여 생성하는 객체로 Session객체를 생성하여 DB사용(Connection 개념)
3) Session : SessionFactory로 부터 만들어지는 객체로 실제 DB작업을 수행하며 가벼운 객체(PreparedStatement 개념)
=> 가볍기 때문에 필요할 때 생성하고 사용이 끝나면 소멸
4) Transaction
5) Query : SQL 또는 HQL(하이버네이트에서만 사용하는 쿼리)
=> SQL : 관계형 데이터베이스마다 문법이 다름
=> HQL : 모든 관계형 데이터베이스에 동일한 문법을 적용
=> 최근에는 서비스의 변화가 심하기 때문에 확장성을 고려하여 프로그래밍하는 것을 권장
6) Criteria : Query문법과는 다른 형태의 질의중 하나로 Query를 직접 사용하지 않고 메소드를 호출하는 형태로 생성
3. 자료형 매핑
1) Number(숫자), int : int, java.lang.Integer
2) number(숫자1, 숫자2), float, double : double, java.lang.Double
3) boolean, yes/no, true/false : boolean, java.lang.Boolean
4) Date : java.sql.Date, java.util.Date
5) Time : java.sql.Time, java.util.Date
6) Timestamp : java.sql.Timestamp
7) char, varchar(varchar2), clob, text, String : java.lang.String
8) blob : java.sql.Blob
=> 모든 자료형은 java.lang.String과 매핑이 가능
- 실제로는 String으로 가져와서 형변환 하는 구조
4. 하이버네이트 매핑 파일 작성 방법
=> id를 primary key와 매핑, property를 이용하여 나머지 컬럼을 매핑
=> 컬럼명 작성시 Oracle은 대문자 MySQL은 소문자를 사용
- DTO 클래스가 아니라 Map 연동시 중요
=> Sequence를 사용하는 경우
5. SessionFactory를 생성하기 위한 bean 설정
6. 질의
1) SQL
2) HQL
3) Criteria
7. Session의 메소드
1) save(Object object) : 데이터 삽입
2) update(Object object) : 기본키 컬럼을 가지고 where절을 만들어 나머지 수정
3) delete(Object object) : 기본키 컬럼을 가지고 삭제
4) get(class 이름, 조건) : 조건에 맞는 데이터를 찾아오는 메소드
5) createSQLQuery(String sql) : SQL 실행 가능한 객체를 생성
8. 필요 의존성
=> 데이터베이스, Spring-jdbc, spring-orm, hibernate
**Hibernate 실습
1. 연동할 테이블을 생성 - Oracle
2. 프로젝트에 의존성을 설정
=> 연동할 데이터베이스, spring-jdbc, spring-orm, hibernate
1) hibernate 버전 설정 - properties에서 변경
<!-- Hibernate / JPA -->
<hibernate.version>5.4.2.Final</hibernate.version>
2) 사용할 데이터의 의존성 추가
=> oracle은 repositories 와 dependency를 같이 추가
=>mysql은 dependency 만 추가
<repositories>
<repository>
<id>oracle</id>
<name>ORACLE JDBC Repository</name>
<url>http://maven.jahia.org/maven2</url>
</repository>
</repositories>
<!-- 오라클 -->
<dependency>
<groupId>com.oracle</groupId>
<artifactId>ojdbc7</artifactId>
<version>12.1.0.2</version>
</dependency>
3) spring-jdbc 의존성 설정
<!-- 스프링에서 데이터베이스 사용을 위한 의존성 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>${spring-framework.version}</version>
</dependency>
4) spring-orm 의존성 설정
<!-- 스프링에서 JPA(Hibernate)를 사용하는 경우 필요한 의존성-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-orm</artifactId>
<version>${spring-framework.version}</version>
</dependency>
5) hibernate는 Spring project에서는 기본적으로 의존성이 설정되어 있어 앞에서처럼 버전만 변경하면 됨
3. Spring 설정 파일에 접속할 데이터베이스 정보를 저장할 DataSource Bean을 생성하고 테스트
=> applicationContext.xml 파일에 작성
<!-- Oracle -->
<bean
class="org.springframework.jdbc.datasource.DriverManagerDataSource"
id="dataSource">
<property name="driverClassName"
value="oracle.jdbc.driver.OracleDriver"/>
<property name="url"
value="jdbc:oracle:thin:@192.168.0.200:1521:xe"/>
<property name="username" value="system"/>
<property name="password" value="********" />
</bean>
4. 테이블과 매핑할 DTO 클래스를 생성
=> 이름은 하이버네이트 설정파일에서 매핑하기 때문에 자료형에 유의하면서 생성
=> hibernate.domain.item
=> 내 소스에는 @Data로 처리
5. 하이버네이트 설정 파일을 생성
=> 테이블과 클래스를 매핑
=> dao.item.hbm.xml(하이버네이트 매핑파일)
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="hibernate.domain">
<class name="item" table="item">
<id name="code" column="code"></id>
<property name="name" column="name" />
<property name="manufacture" column="manufacture" />
<property name="price" column="price" />
<property name="builtdate" column="builtdate" />
</class>
</hibernate-mapping>
6. Spring 설정파일에 hibernate 사용을 위한 bean을 설정
=> context와 tx 네임스페이스를 추가
<!-- bean을 자동 생성하기 위한 패키지 등록 -->
<context:annotation-config/>
<context:component-scan base-package="hibernate"/>
<!-- 하이버네이트 사용을 위한 bean 설정 -->
<bean id="sessionFactory"
class="org.springframework.orm.hibernate5.LocalSessionFactoryBean">
<!-- 접속할 데이터베이스 정보 -->
<property name="dataSource" ref="dataSource" />
<!-- 매핑 파일 정보 설정-->
<property name="mappingResources">
<list>
<value>dao/item.hbm.xml</value>
</list>
</property>
<!-- 데이터베이스 종류 -->
<property name="hibernateProperties">
<value>
hibernate.dialect=org.hibernate.dialect.Oracle10gDialect
</value>
</property>
</bean>
<!-- 하이버네이트 트랜잭션 매니저 -->
<bean id="transactionManager"
class="org.springframework.orm.hibernate5.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
<bean
class="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor"/>
<!-- 트랜잭션 처리를 어노테이션으로 하도록 설정 -->
<tx:annotation-driven/>
7. main 메소드에서 테스트
=> SessionFactory를 주입받아서 출력
//하이버네이트 설정 확인
SessionFactory sessionFactory = context.getBean(SessionFactory.class);
System.out.println(sessionFactory);
=> 설정파일의 경로가 틀리거나 하면 예외가 발생
8. Hibernate 사용하는 DAO 클래스를 생성해서 작업을 수행하는 메소드를 작성
=> SessionFactory를 주입받아서 사용
=> Hibernate를 사용할 때는 반드시 트랜잭션을 사용해야 함
=> Service에 트랜잭션을 적용
package hibernate.dao;
import java.util.Date;
import java.util.List;
import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;
import hibernate.domain.Item;
@Repository
public class ItemDAO {
@Autowired
//하이버 네이트 사용 객체
private SessionFactory sessionFactory;
//데이터 삽입
@Transactional
public void insert(int code, String name, String manufacture, int price) {
Item item = new Item();
item.setCode(code);
item.setName(name);
item.setManufacture(manufacture);
item.setPrice(price);
item.setBuiltdate(new Date());
//데이터 삽입
sessionFactory.getCurrentSession().save(item);
}
//데이터 수정
//기본키를 조건으로 해서 나머지 항목을 수정
//없는 기본키를 대입하면 아무일도 하지 않음
@Transactional
public void update() {
Item item = new Item();
item.setCode(3);
item.setName("포도");
item.setManufacture("음성");
item.setPrice(2000);
item.setBuiltdate(new Date());
//데이터 삽입
sessionFactory.getCurrentSession().update(item);
}
//데이터 삭제
//기본키 항목외 아무것도 필요 없음
//기본키를 조건으로 삭제
@Transactional
public void delete() {
Item item = new Item();
item.setCode(3);
//데이터 삽입
sessionFactory.getCurrentSession().delete(item);
}
//전체 데이터 가져오기
@Transactional
public void list() {
//List<Item> list = (List<Item>)sessionFactory.getCurrentSession().createCriteria(Item.class).list();
List<Item> list = (List<Item>)sessionFactory.getCurrentSession().createSQLQuery("select * from item").addEntity(Item.class).list();
for(Item item : list)
System.out.println(item);
}
//기본키를 가지고 데이터 1개 가져오기
@Transactional
public void getItem() {
//Criteria 사용
Item item = sessionFactory.getCurrentSession().get(Item.class, 1);
System.out.println(item);
}
}
9. main 메소드에서 확인
**Oracle로 작업한 것을 MySQL로 변환
1. MySQL에 테이블 생성
2. pom.xml 파일에 MySQL 의존성을 추가
<!-- MySQL -->
<!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.49</version>
</dependency>
3. DataSource 변경
<!-- MySQL 사용을 위한 설정 -->
<bean
class="org.springframework.jdbc.datasource.DriverManagerDataSource"
id="dataSource">
<!-- 데이터 베이스 종류 : MySQL -->
<property name="driverClassName"
value="com.mysql.jdbc.Driver" />
<!-- 연결할 데이터베이스 URL -->
<property name="url"
value="jdbc:mysql://localhost:3306/myproject?useUnicode=true&characterEncoding=utf8" />
<property name="username" value="root" />
<property name="password" value="900826" />
</bean>
4. Framework 별로 할일
1) MyBatis : mapper 파일에서 쿼리를 수정
2) Hibernate : Spring 설정 파일에서 데이터베이스 종류만 변경하면 됨
<!-- 데이터베이스 종류 -->
<property name="hibernateProperties">
<value>
<!-- 오라클
hibernate.dialect=org.hibernate.dialect.Oracle10gDialect -->
<!-- MySQL -->
hibernate.dialect=org.hibernate.dialect.MySQLDialect
</value>
</property>
**DataBase의 언어 또는 기능
1. 언어
=> DDL : Create, Alter, Drop, Truncate
=> DML
- DQL : Select
- DML : Insert, Delete, Update - Transaction 처리 대상
=> DCL
- DCL : Grant, Revoke
- TCL : Commit, Rollback, SavePoint
2. 기능
=> 정의 기능 : DBA(분석 및 설계)의 작업
=> 조작 기능 : Programming Developer 또는 User
=> 제어 기능 : DBA(운영 - System Management)의 작업
**DataBase 연동
1. JDK가 제공하는 JDBC 만을 이용해서 연동
2. Java Web Application을 만들며 DB 접속 정보를 context.xml 파일에 작성, web.xml이 정보를 읽고 사용
=> Connection Pool을 이용하는 방법
=> 연결과 해제를 직접하지 않고 미리 만들어진 Connection을 빌려쓰는 개념
3. Spring-MyBatis를 이용
=> SQL을 xml이나 인터페이스에 작성하고 자바코드에서 SQL을 호출하여 사용
=> SQL과 자바코드가 분리
=> 작업이 쉽고, DB 연결이나 파라미터 매핑, 결과 매핑 등의 작업이 필요없어 개발시간이 단축됨
=> SI에서 주로 이용
4. Spring-Hibernate를 이용
=> SQL 없이 테이블과 클래스(인스턴스)를 매핑시켜 사용하는 방식
=> 데이터베이스가 변경되더라도 수정할 부분이 거의 없음
=> MyBatis보다 성능이 좋은 경우가 많음
=> 데이터베이스에 대한 이해가 필요하므로 앞의 방법들보다 어려울 수 있음
**소프트웨어 개발 과정
1. 분석(요구사항 정의 - 무엇을 어떻게 언제까지 할 것인지)
2. 설계
1) 개념적 설계 : 도식화
2) 논리적 설계 : 컴퓨터가 이해할 수 있도록 변환(자료형 등)
3) 물리적 설계 : 실제 구현할 내용을 설계(create 등)
- 저장소
- 서버 애플리케이션
- 클라이언트 애플리케이션(PC Application, Web Browser, Android, iOS 등)
=> 저장소 <-> 서버 애플리케이션 <-> 클라이언트 애플리케이션
=> 클라이언트 애플리케이션은 로컬 저장소에는 직접 연동하지만 외부 저장소에는 직접연동하지 않음
3. 구현
1) 저장소 구현
2) 저장소와 서버 애플리케이션 연동
3) 서버 애플리케이션과 클라이언트 애플리케이션이 연동
=> 1번, 2번 작업중에 View는 동시 제작이 가능
=> 서버 애플리케이션의 구현 방법은 Socket Server를 만드는 방법과 Web Server를 만드는 방법이 있음
- 성능은 Socket Server가 좋으나 구현이 어렵고, Web Server는 구현이 쉽지만 성능이 떨어짐
=> 여러종류의 클라이언트에 각각의 서버를 구현하지 않고 서비스하려면 뷰가 아닌 데이터를 만들어 넘겨주어야 함
- 이러한 방식을 Restful or REST API 라고 함
- 이때 가장 많이 사용되는 데이터 포맷이 json
=> 서버 애플리케이션 구현시 가장 중요한 것은 사용자가 요청시 저장소에 요청을 수행하고 결과를 넘겨주는 것
=> 클라이언트에서 가장 중요한 것은 서버의 데이터를 가져와서 원하는 형태로 가공(Parsing) 및 보여주는 것
- 이때 오프라인 상태에서 보여줄수 있도록 할 것인지 그리고 트래픽을 얼마나 줄일것인지 여부를 고민해야 함
4. 테스트
1) 디버깅 : White box, Black box 테스트
2) 검증 : 요구사항과 일치하는 지 테스트, 알파 테스트, 베타 테스트
5. 인수나 이행, 배포
6. 유지보수
'수업 정리' 카테고리의 다른 글
63~66일차 수업 정리(Spring MVC Project) (0) | 2020.07.07 |
---|---|
63일차 수업 정리(Spring - MVC패턴) (0) | 2020.07.06 |
61일차 수업정리(Spring - MyBatis) (0) | 2020.07.02 |
60일차 수업정리(Spring - lombok) (0) | 2020.07.01 |
59일차 수업 정리(Spring) (0) | 2020.06.30 |