DB연동
JDBC 프로그래밍을 하다보면 중복되는 코드가 많다 .
반복되는 줄이려고 탬플릿 메서드 패턴과 전략패턴을 사용해서
스프링이 만든것이 JdbcTemplate이다 이것을 활용하면 코드를 줄일수 있음
스프링으로 DB연동을 처리할때 얻을 수 있는 장점은 트랜잭견부분이다.
JDBC API를 사용할 경우 , 트랜잭션을 처리하려면 다음과 같이 Connection 의 setAutoCommit()을 이용해서 자동 커밋을 비활성화 하고
commit() 과 rollback() 메서드를 이용해서 트랜잭션을 커밋하거나 롤백해야한다,
public void insert(Member member){
Connetion conn = null;
PreparedStatement = null;
try{
conn = DriverManager.getConnection("jdbc:mysql://localhost/sprig4fs?characterEncoding=utf8","id","passward");
conn.setAutoCommit(false)
....
conn.commit();
}catch(SQLException ex){
if(conn!=null)
try{conn.rollback();}catch(SQLException e){}
}finally(){
if(pstmt!=null){
try{pstmt.colse();}catch(SQLException e){}
}
if(conn!=null){
try{conn.colse();}catch(SQLException e){}
}
}
}
스프링을 사용하면 트랜잭션을 적용하고 싶은 메서드에 @Transactional 애노테이션을 붙이기만 하면 된다.
pom.xml설정
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 | <?xml version="1.0" encoding="UTF-8"?> <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 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>sp4</groupId> <artifactId>sp4-chap08</artifactId> <version>0.0.1-SNAPSHOT</version> <dependencies> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>4.1.0.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> <version>4.1.0.RELEASE</version> </dependency> <dependency> <groupId>com.mchange</groupId> <artifactId>c3p0</artifactId> <version>0.9.2.1</version> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.30</version> </dependency> <dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>1.2.17</version> </dependency> </dependencies> <build> <plugins> <plugin> <artifactId>maven-compiler-plugin</artifactId> <version>3.1</version> <configuration> <source>1.7</source> <target>1.7</target> <encoding>utf-8</encoding> </configuration> </plugin> </plugins> </build> </project> | cs |
mysql 스키마 생성
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | create user 'spring4'@'localhost' identified by 'spring4'; create database spring4fs character set=utf8; grant all privileges on spring4fs.* to 'spring4'@'localhost'; create table spring4fs.MEMBER ( ID int auto_increment primary key, EMAIL varchar(255), PASSWORD varchar(100), NAME varchar(100), REGDATE datetime, unique key (EMAIL) ) engine=InnoDB character set = utf8; | cs |
1행 mysql 사용자 spring4 계정생성 (암호로 spring4 사용)
3행 spring4fs DB 생성
5행 spring4fs DB에 spring4 계정이 접근할 수 있도록 권한 부여
07 - 14 행 spring4fs DB에 Member테이블 생성 캐릭터셋은 utf8로 설정
그리고 예제에서 사용할 데이터를 미리 넣어둔다
insert into MEMBER(EMAIL, PASSWORD, NAME, REGDATE)
values('aaa@aaa.net','1234','kim',now());
03 DataSource 설정
JDBC API 는 DataSource를 이용해서 DB를 연결을 구하는 방법을 정의 하고 있다.
DataSoruce를 사용하면 다음과 같은 방식으로 Connection을 구할 수 있다.
스프링이 제공하는 DB 연동기능도 DataSource를 사용해서 DBConnection 을 구할 수 있도록 구현 되어 있다.
DB연동에 사용할 DataSource를 스프링 빈으로 등록하고
DB연동 기능을 구현한 빈객체는 DataSource를 주입받아 사용한다.
DataSource 기능을 제공하는 모듈로는 c3p0 와 dbcp 등이 존재하고,
스프링 테스트 목적으로 사용할 수 있는 DataSource 구현을 제공하고 있다.
c3p0 모듈이 제공하는 DataSource 구현을 사용한다.
c3p0모듈은 DataSource를 구현한 ComboPooledDataSource 클래스를 제공하고 있으므로, 이 클래스를 스프링 빈으로 등록해서 DataSource로 사용하면 된다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:tx="http://www.springframework.org/schema/tx" 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 http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd"> <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close"> <property name="driverClass" value="com.mysql.jdbc.Driver" /> <property name="jdbcUrl" value="jdbc:mysql://localhost/spring4fs?characterEncoding=utf8" /> <property name="user" value="spring4" /> <property name="password" value="spring4" /> </bean> </beans> | cs |
driverClass : JDBC 드라이버 클래스를 지정한다. 위설정은 MYSQL
jdbcUrl : JDBC URL 지정 , 데이터베이스와 테이블의 캐릭터 셋을 UTF-8로 설정 했으므로 JDBC URL의 caracterEncoding 파라미터를 이용해서 MYSQL에 연결할 사용할 캐릭터 셋을 UTF-8로 지정
user : 사용자 계정 지정
password : DB 연결할 때 사용할 암호 지정
close : 커넥션 풀에 보관된 Connection을 종료할 목적으로 사용됨.
04 JdbcTemplate 을 이용한 쿼리 실행
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | package spring; import java.util.List; import javax.sql.DataSource; import org.springframework.jdbc.core.JdbcTemplate; public class MemberDao { private JdbcTemplate jdbcTemplate; public MemberDao(DataSource dataSource) { super(); this.jdbcTemplate = new JdbcTemplate(dataSource); } | cs |
먼저 dataSource를 주입받도록 설정한다.
그리고 스프링에 MemberDao 클래스에 추가 했으므로 스프링 설정에 MemberDao 빈설정을 추가한다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:tx="http://www.springframework.org/schema/tx" 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 http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd"> <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close"> <property name="driverClass" value="com.mysql.jdbc.Driver" /> <property name="jdbcUrl" value="jdbc:mysql://localhost/spring4fs?characterEncoding=utf8" /> <property name="user" value="spring4" /> <property name="password" value="spring4" /> </bean> <bean id= "memberDao" class="spring.MemberDao"> <constructor-arg ref="dataSource"/> </bean> </beans> | cs |
JDBCTemplate를 이용한 조회 쿼리 실행
RowMapper의 mapRow() 메서드 SQL 실행결과로 구한 ResultSet으로부터 한 행의 데이터를 읽어와 이를 자바 객체로 변환해 주는 매퍼 기능을 구현한다.
한번 해보자
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 | package spring; import java.sql.ResultSet; import java.sql.SQLException; import java.util.List; import javax.sql.DataSource; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.jdbc.core.RowMapper; public class MemberDao { private JdbcTemplate jdbcTemplate; public MemberDao(DataSource dataSource) { super(); this.jdbcTemplate = new JdbcTemplate(dataSource); } public Member selectByEmail(String email) { //로우매퍼 인터페이스 구현 RowMapper<Member> rm=new RowMapper<Member>() { @Override public Member mapRow(ResultSet rs,int rowNum) throws SQLException { Member member = new Member(rs.getString("EMAIL"), rs.getString("PASSWORD"), rs.getString("NAME"), rs.getTimestamp("REGDATE")); member.setId(rs.getLong("ID")); return member; } }; //jdbc탬플레이트에 query 실행 List<Member> result = jdbcTemplate.query("select *from MEMBER where EMAIL =?", rm,email); //없으면 null 반환 있으면 리스트의 반환 return result.isEmpty() ? null : result.get(0); } } | cs |
selectAll도 구현
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | public List<Member> selectAll() { List<Member> results = jdbcTemplate.query("select * from MEMBER", new RowMapper<Member>() { @Override public Member mapRow(ResultSet rs, int rowNum) throws SQLException { Member member= new Member(rs.getString("EMAIL"), rs.getString("PASSWORD"), rs.getString("NAME"), rs.getTimestamp("REGDATE")); member.setId(rs.getLong("ID")); return member; } }); return results; } | cs |
결과가 1행인 경우 조회 메서드 : queryForObject()
1 2 3 4 | public int count() { Integer count = jdbcTemplate.queryForObject("select count(*) from MEMBER", Integer.class); return count; } | cs |
queryforObject의 주의점은 결과는 반드시 한 행
그 이상이면 오류가 발생한다.
정확히 1개가 아니라면 query 메서드를 사용해야한다.
JDBCTemplate을 이용한 변경 쿼리 실행
1 2 3 4 | public void update(Member member) { jdbcTemplate.update("update MEMBER set NAME = ?, PASSWORD = ? where EMAIL = ?", member.getName(), member.getPassword(), member.getEmail()); } | cs |
PreparedStatementCreator를 이용한 쿼리 실행
지금 까지 코드는 쿼리에서 사용할 값을 인자로 전달해 주었다.
1 2 3 4 | public void update(Member member) { jdbcTemplate.update("update MEMBER set NAME = ?, PASSWORD = ? where EMAIL = ?", member.getName(), member.getPassword(), member.getEmail()); } | cs |
경우에 따라 set 메서드를 사용해서 직접 인덱스 파라미터 값을 설정해 주어야 할 때가 있다.
이런 경우에는 PreparedStatementCreator를 인자로 받는 메서드를 이용해서 직접 PreparedStatement를 생성하고 설정해 주어야한다.
jdbc.Template,update(new PreparedStatementCreator(){
@Override
public PreparedStatement createPreparedStatement(Connection con)throws SQLException{
//파라미터로 전달받은 Connection 을 이용해서 PreparedStatement를 생성
PreparedStatement pstmt = con.preapeStatement("insert into MEMBER(EMAIL, PASSWORD, NAME, REGDATE)values (?,?,?,?)");
// 인덱스 파라미터 값 설정
pstmt.setString(1,member.getEmail());
pstmt.setString(2,member.getPasswordl());
pstmt.setString(3,member.getName());
pstmt.setTimestamp(4,new Timestamp(member.getRegisterDate().getTime()));
//생성한 pstmt 리턴
return pstmt
}
});
INSERT 쿼리 실행시 , KeyHolder를 이용해서 자동 생성 키 값을 구하기
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | KeyHolder keyHolder = new GeneratedKeyHolder(); jdbcTemplate.update(new PreparedStatementCreator() { @Override public PreparedStatement createPreparedStatement(Connection con) throws SQLException { PreparedStatement pstmt = con.prepareStatement( "insert into MEMBER (EMAIL, PASSWORD, NAME, REGDATE) "+ "values (?, ?, ?, ?)", new String[] {"ID"}); pstmt.setString(1, member.getEmail()); pstmt.setString(2, member.getPassword()); pstmt.setString(3, member.getName()); pstmt.setTimestamp(4, new Timestamp(member.getRegisterDate().getTime())); return pstmt; } }, keyHolder); Number keyValue = keyHolder.getKey(); member.setId(keyValue.longValue()); | cs |
여기에서 두번째 파라미터가 자동증가 칼럼이므로 아이디를줌
update()메서드 는 PreaparedStatement를 실행후 , 자동 생성된 키값을 KeyHolder에 보관한다.
보관된 키는 getKey 메서드로 구할 수있다.
Number로 받은후 원하는 타입으로 변경해서 사용한다.
다음코드는 long타입으로 변환
05 MemberDAO 테스트
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 | package main; import java.text.SimpleDateFormat; import java.util.Date; import java.util.List; import org.springframework.context.support.AbstractApplicationContext; import org.springframework.context.support.GenericXmlApplicationContext; import spring.Member; import spring.MemberDao; public class MainForMemberDao { private static MemberDao memberDao; public static void main(String[] args) { AbstractApplicationContext ctx = new GenericXmlApplicationContext("classpath:appCtx.xml"); memberDao = ctx.getBean("memberDao", MemberDao.class); selectAll(); updateMember(); insertMember(); ctx.close(); } private static void selectAll() { System.out.println("----- selectAll"); int total = memberDao.count(); System.out.println("전체 데이터: " + total); List<Member> members = memberDao.selectAll(); for (Member m : members) { System.out.println(m.getId() + ":" + m.getEmail() + ":" + m.getName()); } } private static void updateMember() { System.out.println("----- updateMember"); Member member = memberDao.selectByEmail("aaa@aaa.net"); String oldPw = member.getPassword(); String newPw = Double.toHexString(Math.random()); member.changePassword(oldPw, newPw); memberDao.update(member); System.out.println("암호 변경: " + oldPw + " > " + newPw); } private static void insertMember() { System.out.println("----- insertMember"); SimpleDateFormat dateFormat = new SimpleDateFormat("MMddHHmmss"); String prefix = dateFormat.format(new Date()); System.out.println("prefix :"+prefix); Member member = new Member(prefix + "@test.com", prefix, prefix, new Date()); memberDao.insert(member); System.out.println(member.getId() + " 데이터 추가"); } } | cs |
트랜잭션 처리
@Transaction을 이용한 트랜잭션 처리
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | package spring; import org.springframework.transaction.annotation.Transactional; public class ChangePasswordService { private MemberDao memberDao; public ChangePasswordService(MemberDao memberDao) { this.memberDao = memberDao; } @Transactional public void changePassword(String email, String oldPwd, String newPwd) { Member member = memberDao.selectByEmail(email); if (member == null) throw new MemberNotFoundException(); member.changePassword(oldPwd, newPwd); memberDao.update(member); } } | cs |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:tx="http://www.springframework.org/schema/tx" 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 http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd"> <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close"> <property name="driverClass" value="com.mysql.jdbc.Driver" /> <property name="jdbcUrl" value="jdbc:mysql://localhost/spring4fs?characterEncoding=utf8" /> <property name="user" value="spring4" /> <property name="password" value="spring4" /> </bean> <bean id = "transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource"></property> </bean> <tx:annotation-driven transaction-manager="transactionManager"/> <bean id= "memberDao" class="spring.MemberDao"> <constructor-arg ref="dataSource"/> </bean> </beans> | cs |
JDBC 연동을 사용하는 경우 DataSourceTracsactionManager클래스를
PlatformTransactionManager로 사용한 경우다.
위설정은 dataSource를 프로퍼티의 값으로 이용해서 트래잭션 연동에 사용할 DataSource를 지정한다.
<tx:annotation-driven> 태그는 @Transactional 애노태이션을 실행하는 기능을 활성화 .
transaction-manager 속성을 사용해서 트랜잭션을 수행할때 사용할 PlatformTransactionManager 빈을 지정한다.
앞서는 transactionManger 빈을 설정 했다.
트랜잭션 처리를 위한 설정을 완료하면 , 트랜잭션 범위에서 실행하고 싶은 스프링 빈 객체의 메서두애 @Transactional 애노테이션을 붙이면 된다.
chagePwdSvc를 실행할 메인클래스를 작성
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | package main; import org.springframework.context.support.AbstractApplicationContext; import org.springframework.context.support.GenericXmlApplicationContext; import spring.ChangePasswordService; import spring.IdPasswordNotMatchingException; import spring.MemberNotFoundException; public class MainForCPS { public static void main(String[] args) { AbstractApplicationContext ctx = new GenericXmlApplicationContext("classpath:appCtx.xml"); ChangePasswordService cps = ctx.getBean("changePwdSvc", ChangePasswordService.class); try { cps.changePassword("aaa@aaa.net", "1234", "1111"); System.out.println("암호를 변경했습니다."); } catch (MemberNotFoundException e) { System.out.println("회원 데이터가 존재하지 않습니다."); } catch (IdPasswordNotMatchingException e) { System.out.println("암호가 올바르지 않습니다."); } ctx.close(); } } | cs |
Log를 보기 위해 Log4j를 사용해 보자
pom.xml에 log4j.xml추가
1 2 3 4 5 | <dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>1.2.17</version> </dependency> | cs |
메이븐 업데이트 후
로그를 어떤형식으로 어디에 기록할지 에 대한 설정 파일로 부터 읽어온다.
src/main/resources
log4j.xml 에 다음과 같이 설정
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE log4j:configuration SYSTEM "log4j.dtd"> <log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/"> <appender name="console" class="org.apache.log4j.ConsoleAppender"> <layout class="org.apache.log4j.PatternLayout"> <param name="ConversionPattern" value="[%t] [%d{yyyy-MM-dd HH:mm:ss}] %-5p %c:%M - %m%n" /> </layout> </appender> <root> <priority value="INFO" /> <appender-ref ref="console" /> </root> <logger name="org.springframework.jdbc"> <level value="DEBUG" /> </logger> </log4j:configuration> | cs |
로그의 디버그 레벨을 보기위한 설정
메인을 실행했더니
<bean id="changePwdSvc" class="spring.ChangePasswordService">
<constructor-arg ref="memberDao"/>
</bean>
빈등록을 안했었음
아까 비번이 랜덤으로 바뀌어있을 것이므로
비민번호를 "1234"로 변경후
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | log4j:WARN Continuable parsing error 21 and column 23 log4j:WARN 요소 유형 "log4j:configuration"의 콘텐츠는 "(renderer*,throwableRenderer?,appender*,plugin*,(category|logger)*,root?,(categoryFactory|loggerFactory)?)"과(와) 일치해야 합니다. [main] [2019-03-26 03:10:06] INFO org.springframework.beans.factory.xml.XmlBeanDefinitionReader:loadBeanDefinitions - Loading XML bean definitions from class path resource [appCtx.xml] [main] [2019-03-26 03:10:06] INFO org.springframework.context.support.GenericXmlApplicationContext:prepareRefresh - Refreshing org.springframework.context.support.GenericXmlApplicationContext@1376c05c: startup date [Tue Mar 26 03:10:06 KST 2019]; root of context hierarchy [main] [2019-03-26 03:10:06] INFO com.mchange.v2.log.MLog:<clinit> - MLog clients using log4j logging. [main] [2019-03-26 03:10:07] INFO com.mchange.v2.c3p0.C3P0Registry:banner - Initializing c3p0-0.9.2.1 [built 20-March-2013 10:47:27 +0000; debug? true; trace: 10] [main] [2019-03-26 03:10:07] DEBUG org.springframework.jdbc.datasource.DataSourceTransactionManager:getTransaction - Creating new transaction with name [spring.ChangePasswordService.changePassword]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT; '' [main] [2019-03-26 03:10:07] INFO com.mchange.v2.c3p0.impl.AbstractPoolBackedDataSource:getPoolManager - Initializing c3p0 pool... com.mchange.v2.c3p0.ComboPooledDataSource [ acquireIncrement -> 3, acquireRetryAttempts -> 30, acquireRetryDelay -> 1000, autoCommitOnClose -> false, automaticTestTable -> null, breakAfterAcquireFailure -> false, checkoutTimeout -> 0, connectionCustomizerClassName -> null, connectionTesterClassName -> com.mchange.v2.c3p0.impl.DefaultConnectionTester, dataSourceName -> 1hge4n6a11eiedp6vm1k2z|462d5aee, debugUnreturnedConnectionStackTraces -> false, description -> null, driverClass -> com.mysql.jdbc.Driver, factoryClassLocation -> null, forceIgnoreUnresolvedTransactions -> false, identityToken -> 1hge4n6a11eiedp6vm1k2z|462d5aee, idleConnectionTestPeriod -> 0, initialPoolSize -> 3, jdbcUrl -> jdbc:mysql://localhost/spring4fs?characterEncoding=utf8, maxAdministrativeTaskTime -> 0, maxConnectionAge -> 0, maxIdleTime -> 0, maxIdleTimeExcessConnections -> 0, maxPoolSize -> 15, maxStatements -> 0, maxStatementsPerConnection -> 0, minPoolSize -> 3, numHelperThreads -> 3, preferredTestQuery -> null, properties -> {user=******, password=******}, propertyCycle -> 0, statementCacheNumDeferredCloseThreads -> 0, testConnectionOnCheckin -> false, testConnectionOnCheckout -> false, unreturnedConnectionTimeout -> 0, userOverrides -> {}, usesTraditionalReflectiveProxies -> false ] [main] [2019-03-26 03:10:07] DEBUG org.springframework.jdbc.datasource.DataSourceTransactionManager:doBegin - Acquired Connection [com.mchange.v2.c3p0.impl.NewProxyConnection@6ae5aa72] for JDBC transaction [main] [2019-03-26 03:10:07] DEBUG org.springframework.jdbc.datasource.DataSourceTransactionManager:doBegin - Switching JDBC Connection [com.mchange.v2.c3p0.impl.NewProxyConnection@6ae5aa72] to manual commit [main] [2019-03-26 03:10:07] DEBUG org.springframework.jdbc.core.JdbcTemplate:query - Executing prepared SQL query [main] [2019-03-26 03:10:07] DEBUG org.springframework.jdbc.core.JdbcTemplate:execute - Executing prepared SQL statement [select *from MEMBER where EMAIL =?] [main] [2019-03-26 03:10:07] DEBUG org.springframework.jdbc.core.JdbcTemplate:update - Executing prepared SQL update [main] [2019-03-26 03:10:07] DEBUG org.springframework.jdbc.core.JdbcTemplate:execute - Executing prepared SQL statement [update MEMBER set NAME = ?, PASSWORD = ? where EMAIL = ?] [main] [2019-03-26 03:10:07] DEBUG org.springframework.jdbc.core.JdbcTemplate:doInPreparedStatement - SQL update affected 1 rows [main] [2019-03-26 03:10:07] DEBUG org.springframework.jdbc.datasource.DataSourceTransactionManager:processCommit - Initiating transaction commit [main] [2019-03-26 03:10:07] DEBUG org.springframework.jdbc.datasource.DataSourceTransactionManager:doCommit - Committing JDBC transaction on Connection [com.mchange.v2.c3p0.impl.NewProxyConnection@6ae5aa72] [main] [2019-03-26 03:10:07] DEBUG org.springframework.jdbc.datasource.DataSourceTransactionManager:doCleanupAfterCompletion - Releasing JDBC Connection [com.mchange.v2.c3p0.impl.NewProxyConnection@6ae5aa72] after transaction [main] [2019-03-26 03:10:07] DEBUG org.springframework.jdbc.datasource.DataSourceUtils:doReleaseConnection - Returning JDBC Connection to DataSource 암호를 변경했습니다. [main] [2019-03-26 03:10:07] INFO org.springframework.context.support.GenericXmlApplicationContext:doClose - Closing org.springframework.context.support.GenericXmlApplicationContext@1376c05c: startup date [Tue Mar 26 03:10:06 KST 2019]; root of context hierarchy | cs |
진행하면 된다.