본문 바로가기

카테고리 없음

62일차 공부 Transaction, Hibernate

** Spring 에서의 Transaction 사용

1. Spring에서의 Transaction 사용을 위한 설정

=> TransactionManager 클래스의 bean을 생성

=> 연동하는 프레임워크에 따라 다르게 생성

=> Spirng JDBC 와 MyBatis를 사용할 때는 동일한 방식으로 생성

DataSourceTransactionManager 클래스의 bean을 생성하면 되는데 이 때 dataSource라는 프로퍼티에 DataSource 빈을 주입해주면 된다.

 

=> Hibernate는 위와는 다른 방식으로 생성

Hibernate는 트랜잭션 사용이 필수

 

2. 적용

=> 데이터베이스 작업을 수행하는 메소드 위에 @Transaction을 추가하는 방식

=> xml 파일에 tx:advice 와 tx:method 태그를 이용해서 설정하는 방식

 

3. 트랜잭션 적용

=> Service에 적용

 

** 트랜잭션 실습

1. Simple Spring Maven : Project 생성

내껀 안되니까 java project만들어서 [Configure] - [Convert to Maven Project]로 변경

 

2. 필요한 의존성 라이브러리를 pom.xml파일에 작성

=> Oracle, Spring-JDBC만 사용할 꺼지만 난 다 복사해넣었다.

 

1) Oracle을 위한 Repository

	<!-- 중앙 저장소가 아닌 곳에서 라이브러리를 다운로드 받고자 하는 경우 설정 : Oracle 때문에 설정 -->
	<repositories>
		<repository>
			<id>oracle</id>
			<name>ORACLE JDBC Repository</name>
			<url>http://maven.jahia.org/maven2</url>
		</repository>
	</repositories>

 

2) Oracle과 Spring-JDBC 의존성을 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>

 

pom.xml

<project xmlns="http://maven.apache.org/POM/4.0.0"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<groupId>SpringMyBatis</groupId>
	<artifactId>SpringMyBatis</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<build>
		<sourceDirectory>src</sourceDirectory>
		<plugins>
			<plugin>
				<artifactId>maven-compiler-plugin</artifactId>
				<version>3.8.1</version>
				<configuration>
					<source>1.8</source>
					<target>1.8</target>
				</configuration>
			</plugin>
		</plugins>
	</build>

	<properties>

		<!-- Generic properties -->
		<java.version>1.8</java.version>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
		<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>

		<!-- Spring -->
		<spring-framework.version>5.0.7.RELEASE</spring-framework.version>

		<!-- Hibernate / JPA -->
		<hibernate.version>4.2.1.Final</hibernate.version>

		<!-- Logging -->
		<logback.version>1.0.13</logback.version>
		<slf4j.version>1.7.5</slf4j.version>

		<!-- Test -->
		<junit.version>4.12</junit.version>
	</properties>

	<!-- 중앙 저장소가 아닌 곳에서 라이브러리를 다운로드 받고자 하는 경우 설정 : Oracle 때문에 설정 -->
	<repositories>
		<repository>
			<id>oracle</id>
			<name>ORACLE JDBC Repository</name>
			<url>http://maven.jahia.org/maven2</url>
		</repository>
	</repositories>


	<dependencies>
		<!-- MyBatis Log 기록 라이브러리 -->
		<dependency>
			<groupId>org.bgee.log4jdbc-log4j2</groupId>
			<artifactId>log4jdbc-log4j2-jdbc4</artifactId>
			<version>1.16</version>
		</dependency>	
	
		<!-- 오라클 의존성 -->
		<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>
		<!-- MyBatis 의존성 -->
		<dependency>
			<groupId>org.mybatis</groupId>
			<artifactId>mybatis</artifactId>
			<version>3.4.6</version>
		</dependency>
		<!-- Spring에서 MyBatis를 사용할 때 필요한 의존성 -->
		<dependency>
			<groupId>org.mybatis</groupId>
			<artifactId>mybatis-spring</artifactId>
			<version>1.3.2</version>
		</dependency>

		<!-- Spring and Transactions -->
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-context</artifactId>
			<version>${spring-framework.version}</version>
		</dependency>

		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-tx</artifactId>
			<version>${spring-framework.version}</version>
		</dependency>

		<!-- Logging with SLF4J & LogBack -->
		<dependency>
			<groupId>org.slf4j</groupId>
			<artifactId>slf4j-api</artifactId>
			<version>${slf4j.version}</version>
			<scope>compile</scope>
		</dependency>

		<dependency>
			<groupId>ch.qos.logback</groupId>
			<artifactId>logback-classic</artifactId>
			<version>${logback.version}</version>
			<scope>runtime</scope>
		</dependency>

		<!-- Hibernate -->
		<dependency>
			<groupId>org.hibernate</groupId>
			<artifactId>hibernate-entitymanager</artifactId>
			<version>${hibernate.version}</version>
		</dependency>

		<!-- Test Artifacts -->
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-test</artifactId>
			<version>${spring-framework.version}</version>
		</dependency>

		<dependency>
			<groupId>junit</groupId>
			<artifactId>junit</artifactId>
			<version>${junit.version}</version>
			<scope>test</scope>
		</dependency>
	</dependencies>
</project>

 

 

3. SpringBeanConfiguration 파일을 생성하고 데이터베이스 접속정보를 저장하는 DataSource 클래스의 Bean을 추가하는 코드를 작성

=> Spring MVC Project이면 파일을 생성할 필요없고 제공되는 파일에 코드를 작성

 

	<!-- Oracle -->
	<bean class="org.springframework.jdbc.datasource.DriverManagerDataSource" id="dataSource">
		<!-- 데이터베이스 종류 : Oracle -->
		<property name="driverClassName" value="oracle.jdbc.driver.OracleDriver"/>
		<!-- 연결할 데이터베이스 URL -->	
		<property name="url" value="jdbc:log4jdbc:oracle:thin:@192.168.0.200:1521:xe"/>
		<!-- 사용할 데이터베이스 계정 -->
		<property name="username" value="user05"/>
		<!-- 사용할 계정의 비밀번호 -->
		<property name="password" value="user05" />
	</bean>

 

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

	<!-- 데이터베이스 접속 정보를 생성 -->
	
	<!-- Oracle -->
	<bean class="org.springframework.jdbc.datasource.DriverManagerDataSource" id="dataSource">
		<!-- 데이터베이스 종류 : Oracle -->
		<property name="driverClassName" value="oracle.jdbc.driver.OracleDriver"/>
		<!-- 연결할 데이터베이스 URL -->	
		<property name="url" value="jdbc:log4jdbc:oracle:thin:@192.168.0.200:1521:xe"/>
		<!-- 사용할 데이터베이스 계정 -->
		<property name="username" value="user05"/>
		<!-- 사용할 계정의 비밀번호 -->
		<property name="password" value="user05" />
	</bean>

</beans>

 

 

 

4. main 메소드를 소유한 클래스를 src(src/main/java) 디렉토리에 생성하고 데이터베이스 접속을 테스트

import java.sql.Connection;

import javax.sql.DataSource;

import org.springframework.context.support.GenericXmlApplicationContext;

public class Main {

	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);
		}catch(Exception e) {
			System.out.println(e.getLocalizedMessage());
			e.printStackTrace();
		}

	}

}

 

 

5. 트랜잭션 처리를 테스트할 DAO 클래스를 생성

=> hibernate.dao.TransactionDAO

 

ackage hibernate.dao;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.simple.SimpleJdbcInsert;
import org.springframework.stereotype.Repository;

@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 네임스페이스 추가 후 작성

 

	<!-- SimpleJdbcInsert bean -->
	<bean id="template" class="org.springframework.jdbc.core.simple.SimpleJdbcInsert">
		<constructor-arg>
			<ref bean="dataSource"/>
		</constructor-arg>			
	</bean>

위의 코드를 아래 처럼

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:context="http://www.springframework.org/schema/context"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd">

	<!-- 데이터베이스 접속 정보를 생성 -->
	
	<!-- Oracle -->
	<bean class="org.springframework.jdbc.datasource.DriverManagerDataSource" id="dataSource">
		<!-- 데이터베이스 종류 : Oracle -->
		<property name="driverClassName" value="oracle.jdbc.driver.OracleDriver"/>
		<!-- 연결할 데이터베이스 URL -->	
		<property name="url" value="jdbc:log4jdbc:oracle:thin:@192.168.0.200:1521:xe"/>
		<!-- 사용할 데이터베이스 계정 -->
		<property name="username" value="user05"/>
		<!-- 사용할 계정의 비밀번호 -->
		<property name="password" value="user05" />
	</bean>
	
	<!-- SimpleJdbcInsert bean -->
	<bean id="template" class="org.springframework.jdbc.core.simple.SimpleJdbcInsert">
		<constructor-arg>
			<ref bean="dataSource"/>
		</constructor-arg>			
	</bean>

</beans>

 

 

3) bean을 자동 생성하기 위한 패키지를 설정

	<!-- bean을 자동생성하기 위한 패키지 등록 -->
	<context:annotation-config/>
	<context:component-scan base-package="hibernate"/>

위의 코드를 아래처럼

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:context="http://www.springframework.org/schema/context"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd">

	<!-- 데이터베이스 접속 정보를 생성 -->
	
	<!-- Oracle -->
	<bean class="org.springframework.jdbc.datasource.DriverManagerDataSource" id="dataSource">
		<!-- 데이터베이스 종류 : Oracle -->
		<property name="driverClassName" value="oracle.jdbc.driver.OracleDriver"/>
		<!-- 연결할 데이터베이스 URL -->	
		<property name="url" value="jdbc:log4jdbc:oracle:thin:@192.168.0.200:1521:xe"/>
		<!-- 사용할 데이터베이스 계정 -->
		<property name="username" value="user05"/>
		<!-- 사용할 계정의 비밀번호 -->
		<property name="password" value="user05" />
	</bean>
	
	<!-- SimpleJdbcInsert bean -->
	<bean id="template" class="org.springframework.jdbc.core.simple.SimpleJdbcInsert">
		<constructor-arg>
			<ref bean="dataSource"/>
		</constructor-arg>			
	</bean>
	
	<!-- bean을 자동생성하기 위한 패키지 등록 -->
	<context:annotation-config/>
	<context:component-scan base-package="hibernate"/>

</beans>

 

 

7. main 메소드를 소유한 클래스에서 DAO 클래스의 bean을 가져와서 메소드를 호출하는 코드를 작성하고 실행

			//DAO 인스턴스를 가져와서 삽입하는 메소드 호출
			TransactionDAO dao = context.getBean(TransactionDAO.class);
			dao.insert();		
import java.sql.Connection;

import javax.sql.DataSource;

import org.springframework.context.support.GenericXmlApplicationContext;

import hibernate.dao.TransactionDAO;

public class Main {

	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);
			*/
			
			//DAO 인스턴스를 가져와서 삽입하는 메소드 호출
			TransactionDAO dao = context.getBean(TransactionDAO.class);
			dao.insert();			
			
		}catch(Exception e) {
			System.out.println(e.getLocalizedMessage());
			e.printStackTrace();
		}

	}

}

 

 

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"/>
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:context="http://www.springframework.org/schema/context"
	xmlns:tx="http://www.springframework.org/schema/tx"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd
		http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.3.xsd">

	<!-- 데이터베이스 접속 정보를 생성 -->
	
	<!-- Oracle -->
	<bean class="org.springframework.jdbc.datasource.DriverManagerDataSource" id="dataSource">
		<!-- 데이터베이스 종류 : Oracle -->
		<property name="driverClassName" value="oracle.jdbc.driver.OracleDriver"/>
		<!-- 연결할 데이터베이스 URL -->	
		<property name="url" value="jdbc:log4jdbc:oracle:thin:@192.168.0.200:1521:xe"/>
		<!-- 사용할 데이터베이스 계정 -->
		<property name="username" value="user05"/>
		<!-- 사용할 계정의 비밀번호 -->
		<property name="password" value="user05" />
	</bean>
	
	<!-- SimpleJdbcInsert bean -->
	<bean id="template" class="org.springframework.jdbc.core.simple.SimpleJdbcInsert">
		<constructor-arg>
			<ref bean="dataSource"/>
		</constructor-arg>			
	</bean>
	
	<!-- bean을 자동생성하기 위한 패키지 등록 -->
	<context:annotation-config/>
	<context:component-scan base-package="hibernate"/>
	
	<!-- 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"/>

</beans>

 

 

3. DAO 메소드 상단에 @Transactional 을 추가하고 실행

 

4. main 메소드를 실행하고 결과 확인

 

5. @Transactional 이 적용된 메소드에서 예외가 발생하면 모든 데이터베이스 작업이 취소된다.

 

 

** ORM(Object Relationship 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 객체를 생성해서 데이터베이스를 사용 - Connection의 개념

무겁기 때문에 미리 생성해두고 유지한 상태로 사용

 

3) Session : SessionFactory로 부터 만들어지는 객체로 실제 데이터베이스 작업을 수행하며 가벼운 객체 - 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를 이용해서 나머지 컬럼을 매핑

 

<hibernate-mapping package="매핑할 DTO 클래스의 경로 - 패키지까지">
	<class name="DTO 클래스이름" table="매핑할 테이블이름">
		<id name="primary key 와 매핑될 프로퍼티"
			colunm="primary key 컬럼이름" />
		<property name="프로퍼티이름" column="컬럼이름"/>
		...
	</class>
<hibernate-mapping>

 

=> 컬럼이름을 작성할 때 Oracle은 대문자, MySQL은 소문자를 사용

DTO 클래스가 아니라 Map 연동할 때 중요

 

=> Sequence를 사용하는 경우

<id name="프로퍼티이름" column="컬럼이름">
	<generator class="sequence">
		<param name="sequence">시퀀스 이름</param>
	</generator>
</id>

 

5. SessionFactory를 생성하기 위한 bean 설정 - 우리가 사용하는 버전은 5

<bean id="식별자" class="org.springframework.orm.hibernate버전.LocationSessionFactoryBean">
	<property name="dataSource" ref="DataSource의 id"/>
	<property name="mappingResources">
		<list>
			<value>설정파일의 경로</value>
			...
		</list>
	</property>
	<property name="hibernateProperties">
		<value>
			hibernate.dialect=데이터베이스 종류
		</value>
	</property>
</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

drop table item;

create table item(
	code number(10) primary key,
	name varchar2(100),
	manufacture varchar2(100),
	price number(10),
	builtdate DATE	
);

 

 

2. 프로젝트에 의존성을 설정 - pom.xml

=> 연동할 데이터베이스, spinrg-jdbc, spring-orm, hibernate

1) hibernate 버전 설정

		<!-- 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">
		<!-- 데이터베이스 종류 : Oracle -->
		<property name="driverClassName" value="oracle.jdbc.driver.OracleDriver"/>
		<!-- 연결할 데이터베이스 URL -->	
		<property name="url" value="jdbc:log4jdbc:oracle:thin:@192.168.0.200:1521:xe"/>
		<!-- 사용할 데이터베이스 계정 -->
		<property name="username" value="user05"/>
		<!-- 사용할 계정의 비밀번호 -->
		<property name="password" value="user05" />
	</bean>

 

4. 테이블과 매핑할 DTO 클래스를 생성

=> 이름은 하이버네이트 설정 파일에서 매핑을 하기 때문에 자료형에 유의하면서 생성

=> hibernate.domain.Item

getter and setter 와 toString을 source에서 설정해준다.

 

package hibernate.domain;

import java.util.Date;

public class Item {
	private int code;
	private String name;
	private String manufacture;
	private int price;
	private Date builtdate;
	public int getCode() {
		return code;
	}
	public void setCode(int code) {
		this.code = code;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public String getManufacture() {
		return manufacture;
	}
	public void setManufacture(String manufacture) {
		this.manufacture = manufacture;
	}
	public int getPrice() {
		return price;
	}
	public void setPrice(int price) {
		this.price = price;
	}
	public Date getBuiltdate() {
		return builtdate;
	}
	public void setBuiltdate(Date builtdate) {
		this.builtdate = builtdate;
	}
	@Override
	public String toString() {
		return "Item [code=" + code + ", name=" + name + ", manufacture=" + manufacture + ", price=" + price
				+ ", builtdate=" + builtdate + "]";
	}
	
}

 

 

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"/>
			<property name="name" column="NAME"/>
			<property name="manufacture" column="MANUFACTURE"/>
			<property name="price" column="PRICE"/>
			<property name="builtdate" column="BUILTDATE"/>
		</class>	
	</hibernate-mapping>

 

 

6. 스프링 설정 파일에 hibernate 사용을 위한 bean 설정 - applicationContext.xml

=> 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/>

 

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:context="http://www.springframework.org/schema/context"
	xmlns:tx="http://www.springframework.org/schema/tx"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd
		http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.3.xsd">

	<!-- 데이터베이스 접속 정보를 생성 -->
	
	<!-- 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="user05"/>
		<property name="password" value="user05" />
	</bean>
	
	<!-- 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/>
	

	<!-- SimpleJdbcInsert bean -->
	<bean id="template" class="org.springframework.jdbc.core.simple.SimpleJdbcInsert">
		<constructor-arg>
			<ref bean="dataSource" />
		</constructor-arg>
	</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"/>
	 -->
</beans>

 

 

7. main 메소드에서 테스트

=> SessionFactory에서 주입받아서 출력해보자.

import java.sql.Connection;

import javax.sql.DataSource;

import org.hibernate.SessionFactory;
import org.springframework.context.support.GenericXmlApplicationContext;

import hibernate.dao.TransactionDAO;

public class Main {

	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);
			*/
			
			//DAO 인스턴스를 가져와서 삽입하는 메소드 호출
			/*
			TransactionDAO dao = 
				context.getBean(TransactionDAO.class);
			dao.insert();
			*/
			
			SessionFactory sessionFactory = context.getBean(SessionFactory.class);
			System.out.println(sessionFactory);
			
			
		}catch(Exception e) {
			System.out.println(e.getMessage());
			e.printStackTrace();
		}

	}

}

 

=> 설정 파일의 경로가 틀리거나 하면 예외 발생

 

8. Hibernate를 사용하는 DAO 크랠스를 생성해서 작업을 수행하는 메소드를 작성

=> SessionFactory를 주입받아서 사용

=> Hibernate를 사용할 대는 반드시 트랜잭션을 사용해야 한다.

=> Service에 트랜잭션을 적용

=> hibernate.dao.ItemDAO

 

9. main 메소드에서 메소드를 호출해서 확인

import java.sql.Connection;

import javax.sql.DataSource;

import org.hibernate.SessionFactory;
import org.springframework.context.support.GenericXmlApplicationContext;

import hibernate.dao.ItemDAO;
import hibernate.dao.TransactionDAO;

public class Main {

	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);
			*/
			
			//DAO 인스턴스를 가져와서 삽입하는 메소드 호출
			/*
			TransactionDAO dao = context.getBean(TransactionDAO.class);
			dao.insert();
			*/
			
			//하이버네이트 설정 확인
			/*
			SessionFactory sessionFactory = context.getBean(SessionFactory.class);
			System.out.println(sessionFactory);
			*/
			
			ItemDAO itemDao = context.getBean(ItemDAO.class);
			itemDao.insert();			
			
		}catch(Exception e) {
			System.out.println(e.getMessage());
			e.printStackTrace();
		}

	}

}

왠일로 한번에 잘되서 당황스럽다.

 

데이터 수정하는 코드는.. ItemDAO에서

package hibernate.dao;

import java.util.Date;

import javax.transaction.Transactional;

import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;

import hibernate.domain.Item;

@Repository
public class ItemDAO {
	@Autowired
	//하이버네이트 사용 객체
	private SessionFactory sessionFactory;
	
	//데이터 삽입
	@Transactional
	public void insert() {
		Item item = new Item();
		item.setCode(3);
		item.setName("오징어");
		item.setManufacture("속초");
		item.setPrice(2000);
		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(9000);
		item.setBuiltdate(new Date());
		
		//데이터 수정
		sessionFactory.getCurrentSession().update(item);
	}	
}

 

수정 main

import java.sql.Connection;

import javax.sql.DataSource;

import org.hibernate.SessionFactory;
import org.springframework.context.support.GenericXmlApplicationContext;

import hibernate.dao.ItemDAO;
import hibernate.dao.TransactionDAO;

public class Main {

	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);
			*/
			
			//DAO 인스턴스를 가져와서 삽입하는 메소드 호출
			/*
			TransactionDAO dao = context.getBean(TransactionDAO.class);
			dao.insert();
			*/
			
			//하이버네이트 설정 확인
			/*
			SessionFactory sessionFactory = context.getBean(SessionFactory.class);
			System.out.println(sessionFactory);
			*/
			
			ItemDAO itemDao = context.getBean(ItemDAO.class);
			//itemDao.insert();
			itemDao.update();
			
			
		}catch(Exception e) {
			System.out.println(e.getMessage());
			e.printStackTrace();
		}

	}

}

결과

 

 

 

데이터 삭제하는 코드 - ItemDAO에서

	//데이터 삭제
	//기본키 항목이외는 아무것도 필요 없다. 기본키를 조건으로 해서 삭제
	@Transactional
	public void delete() {
		Item item = new Item();
		item.setCode(3);
		
		//데이터 삭제
		sessionFactory.getCurrentSession().delete(item);
	}	

추가하고

 

main에서 코드 수정후 실행

 

import java.sql.Connection;

import javax.sql.DataSource;

import org.hibernate.SessionFactory;
import org.springframework.context.support.GenericXmlApplicationContext;

import hibernate.dao.ItemDAO;
import hibernate.dao.TransactionDAO;

public class Main {

	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);
			*/
			
			//DAO 인스턴스를 가져와서 삽입하는 메소드 호출
			/*
			TransactionDAO dao = context.getBean(TransactionDAO.class);
			dao.insert();
			*/
			
			//하이버네이트 설정 확인
			/*
			SessionFactory sessionFactory = context.getBean(SessionFactory.class);
			System.out.println(sessionFactory);
			*/
			
			ItemDAO itemDao = context.getBean(ItemDAO.class);
			//itemDao.insert();
			//itemDao.update();
			itemDao.delete();
			
			
		}catch(Exception e) {
			System.out.println(e.getMessage());
			e.printStackTrace();
		}

	}

 

결과

 

전체 데이터 조회

ItemDAO에서

	//전체 데이터 가져오기
	@Transactional
	public void list() {
		List<Item> list = (List<Item>)sessionFactory.getCurrentSession().createCriteria(Item.class).list();
		//데이터 출력
		for(Item item : list) {
			System.out.println(item);
		}
	}

 

main

import java.sql.Connection;

import javax.sql.DataSource;

import org.hibernate.SessionFactory;
import org.springframework.context.support.GenericXmlApplicationContext;

import hibernate.dao.ItemDAO;
import hibernate.dao.TransactionDAO;

public class Main {

	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);
			*/
			
			//DAO 인스턴스를 가져와서 삽입하는 메소드 호출
			/*
			TransactionDAO dao = context.getBean(TransactionDAO.class);
			dao.insert();
			*/
			
			//하이버네이트 설정 확인
			/*
			SessionFactory sessionFactory = context.getBean(SessionFactory.class);
			System.out.println(sessionFactory);
			*/
			
			ItemDAO itemDao = context.getBean(ItemDAO.class);
			//itemDao.insert();
			//itemDao.update();
			//itemDao.delete();
			
			itemDao.list();
			
			
		}catch(Exception e) {
			System.out.println(e.getMessage());
			e.printStackTrace();
		}

	}

}

결과

 

SQL 을 사용해서 전체데이터 출력은

ItemDAO에서

	//전체 데이터 가져오기
	@Transactional
	public void list() {
		//전체 데이터 가져오기 Criteria 사용
		//List<Item> list = (List<Item>)sessionFactory.getCurrentSession().createCriteria(Item.class).list();
		//SQL 사용
		List<Item> list = (List<Item>)sessionFactory.getCurrentSession().createSQLQuery("select * from item").addEntity(Item.class).list();
		//데이터 출력
		for(Item item : list) {
			System.out.println(item);
		}
	}

 

이렇게 수정하고 메인에서 실행하면 Criteria를 이용한 것과 같은 결과가 나온다.

 

 

기본키를 가지고 데이터 1개 가져오기

DAO에서

	//기본키를 가지고 데이터 1개 가져오기
	@Transactional
	public void getItem() {
		//Criteria 사용
		Item item = sessionFactory.getCurrentSession().get(Item.class, 1);
		System.out.println(item);
	}

main에서 

import java.sql.Connection;

import javax.sql.DataSource;

import org.hibernate.SessionFactory;
import org.springframework.context.support.GenericXmlApplicationContext;

import hibernate.dao.ItemDAO;
import hibernate.dao.TransactionDAO;

public class Main {

	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);
			*/
			
			//DAO 인스턴스를 가져와서 삽입하는 메소드 호출
			/*
			TransactionDAO dao = context.getBean(TransactionDAO.class);
			dao.insert();
			*/
			
			//하이버네이트 설정 확인
			/*
			SessionFactory sessionFactory = context.getBean(SessionFactory.class);
			System.out.println(sessionFactory);
			*/
			
			ItemDAO itemDao = context.getBean(ItemDAO.class);
			//itemDao.insert();
			//itemDao.update();
			//itemDao.delete();			
			//itemDao.list();	
			itemDao.getItem();
			
		}catch(Exception e) {
			System.out.println(e.getMessage());
			e.printStackTrace();
		}

	}

}

결과

 

 

 

 

 

** Oracle로 작업한 것을 MySQL로 변환

1. MySQL에 테이블 생성

 

2. pom.xml에 의존성 추가

		<!-- MySQL -->
		<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
			<version>5.1.49</version>
		</dependency>

 

3. DataSource 변경

오라클 부분은 주석처리

	<!-- MySQL -->
	<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
		<property name="driverClassName" value="com.mysql.jdbc.Driver" />
		<property name="url" value="jdbc:mysql://localhost:3306/sample?useUnicode=true&amp;characterEncoding=utf8" />
		<property name="username" value="root" />
		<property name="password" value="asdqwe123" />
	</bean>

 

4. Framework 별로 할 일

MyBatis이면 mapper 파일에서 쿼리를 수정

Hibernate이면 Spring 설정파일에서 데이터베이스 종류만 변경하면 됨

 

** 데이터베이스 연동

1. JDK가 제공하는 JDBC만을 이용해서 연동

 

2. Java Web Application을 만들면서 데이터베이스 접속정보를 context.xml 파일에 작성하고 web.xml에 이 정보를 읽어서 사용하는 방법

=> Connection Pool을 이용하는 방법

=> 연결과 해제를 직접하지 않고 미리 만들어진 Connection을 빌려쓰는 개념

 

3. Spring-MyBatis를 이용

=> SQL을 xml이나 인터페이스에 작성하고 자바 코드에서 SQL을 호출해서 사용

=> SQL 과 자바코드가 분리되어 좋다.

=> 작업이 쉽고 데이터베이스 연결이나 파라미터 매핑 또는 결과 매핑 등의 작업을 수행할 필요가 없어서 개발시간이 단축됨

=> SI에 주로 이용

 

4. Spring-Hibernate를 이용

=> SQL 없이 테이블과 클래스(인스턴스)를 매핑시켜서 사용하는 방식

=> 데이터베이스가 변경되더라도 수정할 부분이 거의 없고 성능도 MyBatis보다 좋은 경우가 많음

=> 데이터베이스에 대한 이해가 필요하기 때문에 앞의 방법들보다 어려울 수 있다.

 

 

** 소프트웨어 개발 과정

1. 분석(요구사항 정의 - 무엇을 어떻게 언제까지 할 것인지?)

2. 설계

 1) 개념적 설계 : 도식화

 2) 논리적 설계 : 컴퓨터가 이해할 수 있도록 변환

 3) 물리적 설계 : 실제 구현할 내용을 설계

 

저장소

서버 애플리케이션

클라이언트 애플리케이션(PC Application, Web Browser, Android, iOS 등)

 

저장소 <-> 서버 애플리케이션 <-> 클라이언트 애플리케이션

 

클라이언트 애플리케이션은 로컬 저장소에는 직접 연동을 하지만 외부 저장소에는 직접 연동하는경우가 거의 없다.

 

3. 구현

1) 저장소 구현

2) 저장소와 서버 애플리케이션이 연동

3) 서버 애플리케이션과 클라이언트 애플리케이션이 연동

=> 1번이나 2번 작업 중에 View는 동시에 제작하는 것이 가능

=> 서버 애플리케이션을 구현하는 방법은 Socket Server를 만드는 방법과 Web Server를 만드는 방법 2가지

성능은 Socket Server가 좋은데 구현하기가 어렵고 Web Server는 구현하기는 쉬운데 Socket Server보다 성능은 떨어진다.

=> 서버를 만들 때 클라이언트가 여러 종류이면 여러 개의 서버를 구현하지 않고 서비스 할 수 있도록 하기 위해서 뷰가 아니라 데이터를 만들어서 넘겨주어야 한다.

이러한 방식을 Restful 또는 REST API라고 한다.

이 때 가장 많이 사용되는 데이터 포맷이 json이다.

=> 서버 애플리케이션을 구현할 때 가장 중요한 것은 사용자의 요청이 왔을 때 저장소에 요청을 수행하고 결과를 가져와서 넘겨주는 것이다.

=> 클라이언트 애플리케이션에서 가장 중요한 것은 서버의 데이터를 가져와서 원하는 형태로 가공(Parsing)해서 어떻게 보여줄 것인가 하는 것이고 이 때 오프라인 상태에서 보여줄 수 있도록 할 것인지 그리고 트래픽을 얼마나 줄일 것인지 여부를 고민해야 한다.

 

4. 테스트

1) 디버깅 : white box 나 black box테스트

2) 검증 : 요구 사항과 일치하는지 테스트, 알파 테스트, 베타 테스트

 

5. 인수 나 이행, 배포

 

6. 유지보수

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

** DataBase의 언어 또는 기능

1. 언어

DDL : Create, Alter, Drop, Truncate

DML

   - DQL : Select

   - DML : Insert, Delete, Update

DCL

   - DCL : Grant, Revoke

   - TCL : Commit, Rollback, SavePoint

 

2. 기능

정의 기능 : DBA(분석 및 설계)의 작업

조작 기능 : Programming Developer 또는 User

제어 기능 : DBA(운영 - SystemManagement)의 작업