앞글과 이어져 진행 하는 작업이다.
28. MyBatis 의 로그 log4jdbc-log4j2 설정
SQL 이나 잘못된 속성의 이름으로 인해서 예외가 발생한다. 이런 경우를 대비해서 MyBatis 의 로그를 보다 자세히
조사할 수 있도록 로그를 설정 한다. 이때 필요한것이 log4jdbc-log4j2 라이브러리이다.
라이브러리 등록
http://mvnrepository.com/artifact/org.bgee.log4jdbc-log4j2/log4jdbc-log4j2-jdbc4
<!-- https://mvnrepository.com/artifact/org.bgee.log4jdbc-log4j2/log4jdbc-log4j2-jdbc4 --> <dependency> <groupId>org.bgee.log4jdbc-log4j2</groupId> <artifactId>log4jdbc-log4j2-jdbc4</artifactId> <version>1.16</version> </dependency>
driverClassName 을 다음과 같이 변경한다. => net.sf.log4jdbc.sql.jdbcapi.DriverSpy
url 에 log4jdbc 가 들어가야 한다 . => jdbc:log4jdbc:mysql://localhost:3305/simpleblog
/src/main/resources 폴더에 log4jdbc.log4j2.properties 파일과 logback.xml 파일을 추가 한다.
log4jdbc.log4j2.properties
log4jdbc.spylogdelegator.name=net.sf.log4jdbc.log.slf4j.Slf4jSpyLogDelegator
logback.xml
<?xml version="1.0" encoding="UTF-8"?> <configuration> <!-- log4jdbc-log4j2 --> <logger name="jdbc.sqlonly" level="DEBUG"/> <logger name="jdbc.sqltiming" level="INFO"/> <logger name="jdbc.audit" level="WARN"/> <logger name="jdbc.resultset" level="ERROR"/> <logger name="jdbc.resultsettable" level="ERROR"/> <logger name="jdbc.connection" level="INFO"/> <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender"> <layout class="ch.qos.logback.classic.PatternLayout"> <pattern>%d{HH:mm:ss.SSS} [%thread] %-4level [%logger.%method:%line]- %msg%n</pattern> </layout> </appender> <appender name="LOGFILE" class="ch.qos.logback.core.rolling.RollingFileAppender"> <file>/WEB-INF/logback.log</file> <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> <fileNamePattern>logback.%d{yyyy-MM-dd}.log</fileNamePattern> <!-- 30일 지난 파일은 삭제한다. --> <maxHistory>30</maxHistory> </rollingPolicy> <encoder> <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} %-4level [%logger.%method:%line] - %msg %n</pattern> </encoder> </appender> <!-- 로그의 레벨( 지정된 로그 레벨 이상만 수집 ) : DEBUG < INFO < WARN < ERROR < FATAL --> <logger name="myweb" additivity="false"> <level value="INFO" /> <appender-ref ref="LOGFILE" /> <appender-ref ref="CONSOLE" /> </logger> <root> <level value="INFO" /> <appender-ref ref="CONSOLE" /> </root> </configuration>
28번 까지 진행 했다면 위에 작성한 MyBatisTest 를 진행과
서버를 구동해서 라이브러리 버전에 문제가 없는지 테스트 해보자.
29.스프링 로깅툴(SLF4J) 적용
* 로깅툴을 사용하는 이유
- System.out.println() 명령어는 IO 리소스를 많이 사용하여 시스템이 느려질 수 있음
- 로그를 파일로 저장하여 분석할 필요가 있음
* 로깅툴의 종류
- commons-logging : 스프링 3에서 사용하던 로깅툴
- log4j : 효율적인 메모리 관리로 그동안 많이 사용되었음
- logback : log4j 보다 성능이 더 우수하여 최근에 많이 사용되고 있음
* SLF4J : logback을 사용하기 위한 인터페이스
* 설정방법
1. pom.xml 의 slf4j-version 을 1.7.21 로 수정
<properties> <java-version>1.8</java-version> <org.springframework-version>4.3.0.RELEASE</org.springframework-version> <org.aspectj-version>1.6.10</org.aspectj-version> <org.slf4j-version>1.7.21</org.slf4j-version> </properties>
프로젝트를 생성 하면 다음 아래 라이브러리가 디폴트 로 셋팅 되어 있다. 1.7.21 을
변경함으로 서 아래 셋팅 된 값들도 자동으로 버전에 맞게 변경 되어 진다.
<!-- Logging --> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> <version>${org.slf4j-version}</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>jcl-over-slf4j</artifactId> <version>${org.slf4j-version}</version> <scope>runtime</scope> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-log4j12</artifactId> <version>${org.slf4j-version}</version> <scope>runtime</scope> </dependency>
2. pom.xml 에 라이브러리 추가
maven 저장소
http://mvnrepository.com/artifact/ch.qos.logback/logback-classic
<!-- https://mvnrepository.com/artifact/ch.qos.logback/logback-classic --> <dependency> <groupId>ch.qos.logback</groupId> <artifactId>logback-classic</artifactId> <version>1.1.7</version> <scope>test</scope> </dependency>
WAS 없이 구동 하는 필자가 27번에 적어 놓은 WAS 없이 구동 테스트클래스인 SampleControllerTest 를 실행 하던지.
서버를 실행해서 오류가 생기지 않은지 SLF4J 가 뜨는지 확인하자.
29번 까지 아무런 오류 없이 실행 되면 다음과 같은 실행 후 콘솔창 화면이 보일 것이다.
SLF4J: Class path contains multiple SLF4J bindings. SLF4J: Found binding in [jar:file:/C:/Users/choi/.m2/repository/org/slf4j/slf4j-log4j12/1.7.21/slf4j-log4j12-1.7.21.jar!/org/slf4j/impl/StaticLoggerBinder.class] SLF4J: Found binding in [jar:file:/C:/Users/choi/.m2/repository/ch/qos/logback/logback-classic/1.1.7/logback-classic-1.1.7.jar!/org/slf4j/impl/StaticLoggerBinder.class] SLF4J: See http://www.slf4j.org/codes.html#multiple_bindings for an explanation. SLF4J: Actual binding is of type [org.slf4j.impl.Log4jLoggerFactory] INFO : org.springframework.test.context.web.WebTestContextBootstrapper - Loaded default TestExecutionListener class names from location [META-INF/spring.factories]: [org.springframework.test.context.web.ServletTestExecutionListener, org.springframework.test.context.support.DirtiesContextBeforeModesTestExecutionListener, org.springframework.test.context.support.DependencyInjectionTestExecutionListener, org.springframework.test.context.support.DirtiesContextTestExecutionListener, org.springframework.test.context.transaction.TransactionalTestExecutionListener, org.springframework.test.context.jdbc.SqlScriptsTestExecutionListener] INFO : org.springframework.test.context.web.WebTestContextBootstrapper - Using TestExecutionListeners: [org.springframework.test.context.web.ServletTestExecutionListener@36d4b5c, org.springframework.test.context.support.DirtiesContextBeforeModesTestExecutionListener@6d00a15d, org.springframework.test.context.support.DependencyInjectionTestExecutionListener@51efea79, org.springframework.test.context.support.DirtiesContextTestExecutionListener@5034c75a, org.springframework.test.context.transaction.TransactionalTestExecutionListener@396a51ab, org.springframework.test.context.jdbc.SqlScriptsTestExecutionListener@51081592] INFO : org.springframework.beans.factory.xml.XmlBeanDefinitionReader - Loading XML bean definitions from file [G:\dev\spring_simple_blog\test02\src\main\webapp\WEB-INF\spring\appServlet\servlet-context.xml] INFO : org.springframework.beans.factory.xml.XmlBeanDefinitionReader - Loading XML bean definitions from file [G:\dev\spring_simple_blog\test02\src\main\webapp\WEB-INF\spring\root-context.xml] INFO : org.springframework.web.context.support.GenericWebApplicationContext - Refreshing org.springframework.web.context.support.GenericWebApplicationContext@42dafa95: startup date [Fri Oct 13 17:19:08 KST 2017]; root of context hierarchy INFO : org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor - JSR-330 'javax.inject.Inject' annotation found and supported for autowiring INFO : org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping - Mapped "{[/],methods=[GET]}" onto public java.lang.String net.macaronics.web.HomeController.home(java.util.Locale,org.springframework.ui.Model) INFO : org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping - Mapped "{[/doD]}" onto public java.lang.String net.macaronics.web.SampleController.doD(org.springframework.ui.Model) INFO : org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping - Mapped "{[/doC]}" onto public java.lang.String net.macaronics.web.SampleController.doC(java.lang.String,java.lang.String) INFO : org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping - Mapped "{[/doA]}" onto public void net.macaronics.web.SampleController.doA() INFO : org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping - Mapped "{[/doB]}" onto public void net.macaronics.web.SampleController.doB() INFO : org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping - Mapped "{[/doE]}" onto public java.lang.String net.macaronics.web.SampleController.doE(net.macaronics.web.ProductVO) INFO : org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping - Mapped "{[/doF]}" onto public java.lang.String net.macaronics.web.SampleController.doF(org.springframework.web.servlet.mvc.support.RedirectAttributes) INFO : org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping - Mapped "{[/doG]}" onto public void net.macaronics.web.SampleController.doG(java.lang.String,javax.servlet.http.HttpServletRequest) INFO : org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping - Mapped "{[/doJson]}" onto public net.macaronics.web.ProductVO net.macaronics.web.SampleController.doJson() INFO : org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping - Mapped "{[/doJSON]}" onto public java.util.Map net.macaronics.web.SampleController.doJSON() INFO : org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter - Looking for @ControllerAdvice: org.springframework.web.context.support.GenericWebApplicationContext@42dafa95: startup date [Fri Oct 13 17:19:08 KST 2017]; root of context hierarchy INFO : org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter - Looking for @ControllerAdvice: org.springframework.web.context.support.GenericWebApplicationContext@42dafa95: startup date [Fri Oct 13 17:19:08 KST 2017]; root of context hierarchy INFO : org.springframework.web.servlet.handler.SimpleUrlHandlerMapping - Mapped URL path [/resources/**] onto handler 'org.springframework.web.servlet.resource.ResourceHttpRequestHandler#0' INFO : org.springframework.jdbc.datasource.DriverManagerDataSource - Loaded JDBC driver: net.sf.log4jdbc.sql.jdbcapi.DriverSpy INFO : org.springframework.mock.web.MockServletContext - Initializing Spring FrameworkServlet '' INFO : org.springframework.test.web.servlet.TestDispatcherServlet - FrameworkServlet '': initialization started INFO : org.springframework.test.web.servlet.TestDispatcherServlet - FrameworkServlet '': initialization completed in 17 ms INFO : net.macaronics.web.SampleController - setUp ---- INFO : net.macaronics.web.SampleController - doJSON ( ) - {name=홍길동, age=21} INFO : org.springframework.web.context.support.GenericWebApplicationContext - Closing org.springframework.web.context.support.GenericWebApplicationContext@42dafa95: startup date [Fri Oct 13 17:19:08 KST 2017]; root of context hierarchy
30. 연결 properties 로 변경하기
DB 연결 정보를 팀 프로젝트에서 좀 더 안전하고 편리하게 연결하기 위해 연결정보를 properties 로 변경 해보자.
src/main/resources 에 config 폴더를 생성하고
mysql-config.properties 파일을 생성 해보자.
중요한것은 파일명이 아니라 src/main/resources 아래 생성 하는 것이다.
properties 내용
db.driver=net.sf.log4jdbc.sql.jdbcapi.DriverSpy db.jdbcUrl=jdbc:log4jdbc:mysql://localhost:3305/simpleblog?useSSL=false db.user=simpleblog db.password=1111
그리고 root-context.xml 에 다음을 추가 하자.
classpath 가 src/main/resources 의 위치를 인식하고 있기 때문에 위와 같이 적는다.
마지막으로 dataSource 빈을 다음과 같이 변경한 후 이상이 없는지 테스트를 해보자.
<?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:jdbc="http://www.springframework.org/schema/jdbc" xmlns:mybatis-spring="http://mybatis.org/schema/mybatis-spring" xmlns:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation="http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-4.3.xsd http://mybatis.org/schema/mybatis-spring http://mybatis.org/schema/mybatis-spring-1.2.xsd 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/aop http://www.springframework.org/schema/aop/spring-aop-4.3.xsd"> <!-- Root Context: defines shared resources visible to all other web components --> <context:property-placeholder location="classpath:/config/mysql-config.properties" /> <!-- <context:property-placeholder location="classpath:/config/oralce-config.properties" /> --> <!-- <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> <property name="driverClassName" value="net.sf.log4jdbc.sql.jdbcapi.DriverSpy" /> <property name="url" value="jdbc:log4jdbc:mysql://localhost:3305/simpleblog?useSSL=false" /> <property name="username" value="simpleblog" /> <property name="password" value="1111" /> </bean> --> <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> <property name="driverClassName" value="${db.driver}" /> <property name="url" value="${db.jdbcUrl}" /> <property name="username" value="${db.user}" /> <property name="password" value="${db.password}" /> </bean> </beans>
31. XML Mapper 생성 및 작성 및 인식 및 SqlSessionTemplate 설정
위 그림 처럼 src/main/resource 경로 아래 Mapper 를 설정해두는 폴더 mappers 를 생성한다.
sampleMapper.xml
는 다음과 같은 샘플 내용이 있다.
<?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와 중복되지 않도록 네임스페이스 기재 --> <mapper namespace="sampleMapper"> </mapper>
상세 설정은 마이바티스 홈페이지에 가면 자세히 나와 있다.
http://www.mybatis.org/mybatis-3/ko/configuration.html
스프링에서 mapper 폴더를 인식 할 수 있게 다음과 같이 root-context.xml 을 변경하자
21번 Mybatis 설정 내용을 참조하자.
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> <property name="dataSource" ref="dataSource" /> <property name="configLocation" value="classpath:/mybatis-config.xml" /> <property name="mapperLocations" value="classpath:mappers/**/*Mapper.xml"/> </bean>
mappers 폴더 내에 어떤 폴더이건 관계없이 파일의 이름이 'Mapper.xml ' 로 끝나면 자동으로 인식하도록 설정 하는 것이다.
SqlSessionTemplate 의 설정
dao 의 작업에서 데이터베이스 연결을 맺고 작업이 완료 후에 close() 하는 작업이 있다.
jsp 에서는 root-context.xml 이 없어서 연결 처리와 close 처리를 자동으로 할 수 없었다. 그러나 스프링 프레임워크에서는
root-context.xml 가 존재하고 여기에 SqlSessionTemplate 클래스를 설정해서 연결과 종료 작업을 자동으로 처리 해준다.
또한, SqlSessionTemplate 는 MyBatis 의 SqlSession 인터페이스를 구현한 클래스로 기본적인 트랜젝션의 관리나 쓰레드
처리의 안정성 을 보장해 주고 , 데이터 베이스의 연결과 종료도 관리해 준다.
root-context.xml 에 다음과 같이 추가 하자.
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> <property name="dataSource" ref="dataSource" /> <property name="configLocation" value="classpath:/mybatis-config.xml" /> <property name="mapperLocations" value="classpath:mappers/**/*Mapper.xml"/> </bean> <!-- SqlSession 객체 주입 --> <bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate" destroy-method="clearCache"> <constructor-arg name="sqlSessionFactory" ref="sqlSessionFactory"/> </bean>
22 번 MyBatisTest 를 다음과 같이 수정하고 테스트를 진행 해보자.
만약 에러가 발생하면 필자와 다른 라이브러리를 사용했을 가능성이 있다. 다시한번 살펴 보자.
package net.macaronics.web; import org.apache.ibatis.session.SqlSession; import org.apache.ibatis.session.SqlSessionFactory; import org.junit.Test; import org.junit.runner.RunWith; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(locations={"file:src/main/webapp/WEB-INF/spring/**/*.xml"}) public class MyBatisTest { private static final Logger log = LoggerFactory.getLogger(MyBatisTest.class); @Autowired private SqlSessionFactory sqlSessionFactory; private SqlSession sqlSession; @Test public void testSqlSessionFactory(){ log.info("testSqlSessionFactory , {} " ,sqlSessionFactory); } @Test public void testSession() throws Exception{ try(SqlSession session=sqlSessionFactory.openSession()){ log.info("testSession() , {} " ,session); }catch(Exception e){ e.printStackTrace(); } } @Test public void testSqlSession(){ log.info("testSqlSession() , {} " ,sqlSession); } }
32. 데이터베이스 연동 및 Mybatis 연동 등 현재 프로젝트가 제대로
돌아가는 CRUD 샘플 테스트 개발해 본다.
31번 까지 완료 했으면 DB MyBatis 연동 CRUD 테스트를 해서 프로젝트가 이상없이 구동되는지 확인 해 보자.
다음과 같은 클래스파일을 만들어 보자.
Domain = VO =DTO
테이블 기준으로 데이터 전달 운송 단위
비슷한 의미들이다.
MemberVO
package net.macaronics.web.domain; import java.sql.Timestamp; import java.util.Date; public class MemberVO { private String userid ; private String userpw ; private String username; private String email ; private Timestamp regdate; private Timestamp updatedate; setter, getter
dao 패키지 또는 persistence
MemberDAO
package net.macaronics.web.persistence; import java.util.List; import net.macaronics.web.domain.MemberVO; public interface MemberDAO { //DB 시간정보 물러오기 public String getTime(); //멤버 생성 public void createMember(MemberVO vo); //회원 한명 정보 불러오기 public MemberVO getReadMember(String userid, String userpw); //회원 목록 출력 public List readListMember(); //회원 업데이트 public void updateMember(MemberVO vo); //회원 삭제 public void deleteMember(String userid); //회원수 public Integer getCount(); }
MemberDAOImpl
package net.macaronics.web.persistence; import java.util.HashMap; import java.util.List; import java.util.Map; import org.apache.ibatis.session.SqlSession; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Repository; import net.macaronics.web.domain.MemberVO; @Repository public class MemberDAOImpl implements MemberDAO { private static final Logger log = LoggerFactory.getLogger(MemberDAOImpl.class); private static final String namespace="net.macaronics.mapper.memberMapper."; @Autowired private SqlSession sqlSession; //DB 시간정보 물러오기 @Override public String getTime() { return sqlSession.selectOne(namespace+"getTime"); } //멤버 생성 @Override public void createMember(MemberVO vo) { sqlSession.insert(namespace+"createMember", vo); } //회원 한명 정보 불러오기 @Override public MemberVO getReadMember(String userid, String userpw) { Map map=new HashMap<>(); map.put("userid", userid); map.put("userpw", userpw); return sqlSession.selectOne(namespace+"getReadMember", map); } //회원 목록 출력 @Override public List readListMember() { return sqlSession.selectList(namespace+"readListMember"); } //회원 업데이트 @Override public void updateMember(MemberVO vo) { sqlSession.update(namespace+"updateMember", vo); } //회원 삭제 @Override public void deleteMember(String userid) { sqlSession.delete(namespace+"deleteMember", userid); } //회원수 @Override public Integer getCount() { return sqlSession.selectOne(namespace+"getCount"); } }
Service
컨트롤과 dao 완충 역할 즉,
dao 나 컨트롤에서 하던 복잡한 계산 작업은 서비스에서 하면 된다.
코드상으로 볼때는 dao 와 별차이없다. 하지만 역할이 다르다.
MemberService
package net.macaronics.web.service; import java.util.List; import net.macaronics.web.domain.MemberVO; public interface MemberService { //DB 시간정보 물러오기 public String getTime(); //멤버 생성 public void createMember(MemberVO vo); //회원 한명 정보 불러오기 public MemberVO getReadMember(String userid, String userpw); //회원 목록 출력 public List readListMember(); //회원 업데이트 public void updateMember(MemberVO vo); //회원 삭제 public void deleteMember(String userid); //회원수 public Integer getCount(); }
MemberServiceImpl
package net.macaronics.web.service; import java.util.List; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import net.macaronics.web.domain.MemberVO; import net.macaronics.web.persistence.MemberDAO; @Service public class MemberServiceImpl implements MemberService { private static final Logger log = LoggerFactory.getLogger(MemberServiceImpl.class); @Autowired private MemberDAO dao; @Override public String getTime() { return dao.getTime(); } @Override public void createMember(MemberVO vo) { dao.createMember(vo); } @Override public MemberVO getReadMember(String userid, String userpw){ return dao.getReadMember(userid, userpw); } @Override public List readListMember() { return dao.readListMember(); } @Override public void updateMember(MemberVO vo) { dao.updateMember(vo); } @Override public void deleteMember(String userid) { dao.deleteMember(userid); } @Override public Integer getCount() { return dao.getCount(); } }
Mapper
memberMapper.xml
<?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와 중복되지 않도록 네임스페이스 기재 --> <mapper namespace="net.macaronics.mapper.memberMapper"> <!-- DB 시간정보 물러오기 --> <select id="getTime" resultType="string"> <![CDATA[ select now() ]]> </select> <!-- 멤버 생성 --> <insert id="createMember"> insert INTO TBL_MEMBER (userid, userpw, username, email) values (#{userid}, #{userpw}, #{username}, #{email} ) </insert> <!-- 회원 한명 정보 불러오기 --> <select id="getReadMember" resultType="net.macaronics.web.domain.MemberVO"> select * from TBL_MEMBER where userid=#{userid} and userpw=#{userpw} </select> <!-- 회원 목록 출력 --> <select id="readListMember" resultType="net.macaronics.web.domain.MemberVO"> select * from TBL_MEMBER </select> <!-- 회원 업데이트 --> <update id="updateMember"> update TBL_MEMBER SET userpw=#{userpw}, email=#{email}, username=#{username} where userid=#{userid} </update> <!-- 회원 삭제 --> <delete id="deleteMember"> delete from TBL_MEMBER WHERE userid=#{userid} </delete> <select id="getCount" resultType="int"> select count(*) from TBL_MEMBER </select> </mapper>
위와 같이 코딩을 하였으면 다음과 같이 테스트 코드를 작성해 보자. 그전에 의존 성 주입이 잘 되었는지 S 자를 확인해 보자.
파일 위에 S 자 모양이 있어야 servlet-context.xml 의 component-scan 의해 파이들이 스켄되어서 스프링의 특징 중 하나인 DI 의존성 주입 이
설정 되었다는 것을 판단 할 수 있다.
테스트
MemberDAOImplTest
package net.macaronics.web.persistence; import static org.junit.Assert.fail; import java.util.List; import org.junit.Test; import org.junit.runner.RunWith; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import net.macaronics.web.domain.MemberVO; @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(locations={"file:src/main/webapp/WEB-INF/spring/**/*.xml"}) public class MemberDAOImplTest { private static final Logger log = LoggerFactory.getLogger(MemberDAOImplTest.class); @Autowired private MemberDAO dao; Integer count; @Test public void testGetTime() { log.info("testGetTime {} ", dao.getTime()); } @Test public void testCreateMember() { count =dao.getCount(); MemberVO vo=new MemberVO(); if(count==0){ vo.setUserid("user0"); vo.setUserpw("1111"); vo.setUsername("name0"); vo.setEmail("0@macaronics.net"); dao.createMember(vo); } ++count; vo.setUserid("user"+count); vo.setUserpw("1111"); vo.setUsername("name"+count); vo.setEmail(count+"@macaronics.net"); dao.createMember(vo); } @Test public void testReadListMember() { List list =dao.readListMember(); log.info("testReadListMember - {}" , list.toString()); } @Test public void testUpdateMember() { MemberVO vo =new MemberVO(); vo.setUserid("user0"); vo.setUserpw("1111"); vo.setUsername("2222name0"); vo.setEmail("update0@macaronics.net"); dao.updateMember(vo); } @Test public void testDeleteMember() { dao.deleteMember("user0"); } @Test public void testGetReadMember() { MemberVO vo=dao.getReadMember("user1", "1111"); log.info("testGetReadMember - {}" , vo.toString()); } }
테스트 결과 이미지 이다.
33. Mysql 에서 테스트를 했으면 Oracle 로 개발할경우 다음 과 같은 설정을 통해
테스트를 진행 해 보자.
DB - SQL
테이블 생성하기.
---------------------------- ---------------------------- ---------------------------- 오라클 --임의 폴더를 만든다. 필자는 D 드리버의 oracleDB 폴더를 생성했다. -- 콘솔창을 연다 -- C:> cmd -- DBA 접속 -- C:> sqlplus / as sysdba -- 테이블 스페이스 생성 create tablespace simpleblog datafile 'D:\oracleDB/simpleblog.dbf' size 20m autoextend on next 10m maxsize unlimited; -- 계정 생성 create user simpleblog identified by 1111 default tablespace simpleblog; -- 권한 설정 grant connect, resource, create view to simpleblog; CREATE TABLE tbl_member ( userid VARCHAR2 (100) PRIMARY KEY, userpw VARCHAR2 (100) NOT NULL, username VARCHAR2 (50) NOT NULL, email VARCHAR2 (100), regdate TIMESTAMP DEFAULT sysdate, updatedate TIMESTAMP DEFAULT sysdate );
pom.xml 에 다음과 같이 추가한다. 상단 부분
<properties> <java-version>1.8</java-version> <org.springframework-version>4.3.0.RELEASE</org.springframework-version> <org.aspectj-version>1.6.10</org.aspectj-version> <org.slf4j-version>1.7.21</org.slf4j-version> </properties> <!-- 오라클 연결 --> <repositories> <repository> <id>codelds</id> <url>https://code.lds.org/nexus/content/groups/main-repo</url> </repository> </repositories>
라이브러리 추가
https://mvnrepository.com/artifact/com.github.noraui/ojdbc7
<!-- 오라클 연결 드라이브--> <!-- https://mvnrepository.com/artifact/com.github.noraui/ojdbc7 --> <dependency> <groupId>com.github.noraui</groupId> <artifactId>ojdbc7</artifactId> <version>12.1.0.2</version> </dependency>
다음 이미처럼 oralce-config.properties, memberMapper.xml 추가 MemberDAOImpl , root-context.xml
변경한다.
oralce-config.properties
db.driver=net.sf.log4jdbc.sql.jdbcapi.DriverSpy db.jdbcUrl=jdbc:log4jdbc:oracle:thin:@localhost:1521:xe db.user=simpleblog db.password=1111
oracle/memberMapper.xml
<?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와 중복되지 않도록 네임스페이스 기재 --> <mapper namespace="net.macaronics.mapper.o.memberMapper"> <!-- DB 시간정보 물러오기 --> <select id="getTime" resultType="string"> <![CDATA[ select sysdate from dual]]> </select> <!-- 멤버 생성 --> <insert id="createMember"> insert INTO TBL_MEMBER (userid, userpw, username, email) values (#{userid}, #{userpw}, #{username}, #{email} ) </insert> <!-- 회원 한명 정보 불러오기 --> <select id="getReadMember" resultType="net.macaronics.web.domain.MemberVO"> select * from TBL_MEMBER where userid=#{userid} and userpw=#{userpw} </select> <!-- 회원 목록 출력 --> <select id="readListMember" resultType="net.macaronics.web.domain.MemberVO"> select * from TBL_MEMBER </select> <!-- 회원 업데이트 --> <update id="updateMember"> update TBL_MEMBER SET userpw=#{userpw}, email=#{email}, username=#{username} where userid=#{userid} </update> <!-- 회원 삭제 --> <delete id="deleteMember"> delete from TBL_MEMBER WHERE userid=#{userid} </delete> <select id="getCount" resultType="int"> select count(*) from TBL_MEMBER </select> </mapper>
MemberDAOImpl
@Repository public class MemberDAOImpl implements MemberDAO { private static final Logger log = LoggerFactory.getLogger(MemberDAOImpl.class); private static final String namespace="net.macaronics.mapper.o.memberMapper."; @Autowired private SqlSession sqlSession; }
root-context.xml
<?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:jdbc="http://www.springframework.org/schema/jdbc" xmlns:mybatis-spring="http://mybatis.org/schema/mybatis-spring" xmlns:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation="http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-4.3.xsd http://mybatis.org/schema/mybatis-spring http://mybatis.org/schema/mybatis-spring-1.2.xsd 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/aop http://www.springframework.org/schema/aop/spring-aop-4.3.xsd"> <!-- Root Context: defines shared resources visible to all other web components --> <context:property-placeholder location="classpath:/config/mysql-config.properties" /> <!-- <context:property-placeholder location="classpath:/config/oralce-config.properties" /> --> <!-- <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> <property name="driverClassName" value="net.sf.log4jdbc.sql.jdbcapi.DriverSpy" /> <property name="url" value="jdbc:log4jdbc:mysql://localhost:3305/simpleblog?useSSL=false" /> <property name="username" value="simpleblog" /> <property name="password" value="1111" /> </bean> --> <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> <property name="driverClassName" value="${db.driver}" /> <property name="url" value="${db.jdbcUrl}" /> <property name="username" value="${db.user}" /> <property name="password" value="${db.password}" /> </bean> <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> <property name="dataSource" ref="dataSource" /> <property name="configLocation" value="classpath:/mybatis-config.xml" /> <property name="mapperLocations" value="classpath:mappers/**/*Mapper.xml"/> </bean> <!-- SqlSession 객체 주입 --> <bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate" destroy-method="clearCache"> <constructor-arg name="sqlSessionFactory" ref="sqlSessionFactory"/> </bean> </beans>
위 같이 진행 후 MemberDAOImplTest 테스트를 하면 될 것이다.
제작 : macaronics.net - Developer Jun Ho Choi
소스 : 소스가 필요한 분은 비밀 댓글로 작성해 주세요.
댓글 ( 6)
댓글 남기기