Java 프레임워크 만들기 - JSP

자바 BasicDataSource(아파치 공통 DBCP) - Java BasicDataSource(Apache Commons DBCP), 이클립스(Eclipse)

carrotweb 2021. 6. 29. 12:09
728x90
반응형

"org.apache.commons.dbcp2"에 있는 "BasicDataSource"를 이용하여 데이터베이스 커넥션 풀(Pool)을 생성하여 이용하겠습니다.

1. "test2" 프로젝트의 "pom.xml"을 오픈하여 "commons-dbcp2"는 주석 처리를 해제하고 "tomcat-jdbc"는 주석처리합니다.

<dependency>
	<groupId>org.apache.commons</groupId>
	<artifactId>commons-dbcp2</artifactId>
	<version>2.8.0</version>
</dependency>
<!--
<dependency>
	<groupId>org.apache.tomcat</groupId>
	<artifactId>tomcat-jdbc</artifactId>
	<version>8.5.68</version>
</dependency>
-->

 

작업을 위해 JNDI 이용을 위해 설정한 정보들을 주석처리합니다.

2. "Servers"에서 "Tomcat8-config"이나 "Tomcat9-config"의 "server.xml"의 "<GlobalNamingResources>"태그안에 "<Resource>"를 주석처리합니다.

<!--
<Resource name="jdbc/test"
	auth="Container"
	type="javax.sql.DataSource"
	driverClassName="org.mariadb.jdbc.Driver"
	url="jdbc:mariadb://localhost:3306/test"
	username="root"
	password="password"
	initialSize="20"
	maxTotal="100"
	maxIdle="100"
	minIdle="20"
	maxWaitMillis="30000"
/>
-->

 

"context.xml"의 "<Context>"태그안에 "<ResourceLink>"를 주석처리합니다.

<!--
<ResourceLink global="jdbc/test" name="jdbc/test" type="javax.sql.DataSource"/>
-->

 

"web.xml"의 를 주석처리합니다.

<!--
<resource-ref>
	<description>MariaDB Connection Pool</description>
	<res-ref-name>jdbc/test</res-ref-name>
	<res-type>javax.sql.DataSource</res-type>
	<res-auth>Container</res-auth>
</resource-ref>
-->

 

3. "test2" 프로젝트의 "Java Resources/src/main/java"에서 "com.hom.project.test2.database"에서 오른쪽 버튼을 클릭하여 컨텍스트 메뉴 [New > Class]를 클릭하고 "TestDatabaseDataSource.java"를 생성합니다.

 

데이터소스 객체와 데이터베이스 프로퍼티, 커넥션 풀이 생성되었는지 확인하기 위해 부울값 필드를 추가하고 커넥션 풀 생성 여부 확인 메서드를 추가합니다.

/**
 * 데이터소스 객체
 */
private BasicDataSource dataSource = null;

/**
 * 데이터베이스 프로퍼티
 */
private Properties databaseInfo = new Properties();

/**
 * 데이터베이스 커넥션 풀 생성 여부
 */
private boolean initDatabasePool = false;

/**
 * 데이터베이스 커넥션 풀 생성 여부를 가져옵니다.
 * @return 데이터베이스 커넥션 풀 생성 여부
 */
public boolean isInitDatabasePool() {
	return initDatabasePool;
}

 

데이터베이스 프로퍼티(properties) 파일을 읽어 프로퍼티로 로드하게 메소드를 추가합니다.

/**
 * 데이터베이스 매니저 프로퍼티를 로드하고 검증합니다.
 * @param databaseManagerPath 데이터베이스 매니저 프로퍼티 경로
 * @return 프로퍼티 로드 여부
 */
private boolean loadProperties(String databaseManagerPath) {
	boolean result = true;

	InputStream inputStream = getClass().getResourceAsStream(databaseManagerPath);
	if (inputStream != null) {
		try {
			databaseInfo.load(inputStream);
			System.out.println("데이터베이스 프로퍼티를 읽음");

			String id = databaseInfo.getProperty("id");
			if (id == null || id.trim().isEmpty()) {
				System.out.println("데이터베이스 프로퍼티에 id가 없음");
				result = false;
			}
			String driverClassName = databaseInfo.getProperty("driverClassName");
			if (driverClassName == null || driverClassName.trim().isEmpty()) {
				System.out.println("데이터베이스 프로퍼티에 driverClassName이 없음");
				result = false;
			}
			String url = databaseInfo.getProperty("url");
			if (url == null || url.trim().isEmpty()) {
				System.out.println("데이터베이스 프로퍼티에 url이 없음");
				result = false;
			}
			String username = databaseInfo.getProperty("username");
			if (username == null || username.trim().isEmpty()) {
				System.out.println("데이터베이스 프로퍼티에 username이 없음");
				result = false;
			}
			String password = databaseInfo.getProperty("password");
			if (password == null || password.trim().isEmpty()) {
				System.out.println("데이터베이스 프로퍼티에 password가 없음");
				result = false;
			}

			setPropertyInit("initialSize", "0");
			setPropertyInit("maxWaitMillis", "0");
			setPropertyInit("maxTotal", "8");
			setPropertyInit("maxIdle", "8");

			setPropertyInit("validationQuery", "");
			setPropertyInit("validationQueryTimeoutSeconds", "-1");

			setPropertyInit("poolStatements", "False");
			setPropertyInit("maxOpenPreparedStatements", "-1");

			setPropertyInit("maxConnLifetimeMillis", "-1");
			setPropertyInit("minIdle", "0");

			setPropertyInit("testOnBorrow", "False");
			setPropertyInit("testOnReturn", "False");
			setPropertyInit("testOnCreate", "False");
			setPropertyInit("testWhileIdle", "False");
			setPropertyInit("evictionPolicyClassName", "org.apache.commons.pool2.impl.DefaultEvictionPolicy");
			setPropertyInit("timeBetweenEvictionRunsMillis", "-1");

			setPropertyInit("numTestsPerEvictionRun", "3");
			setPropertyInit("minEvictableIdleTimeMillis", "1800000");
			setPropertyInit("softMinEvictableIdleTimeMillis", "-1");

			setPropertyInit("removeAbandonedOnBorrow", "False");
			setPropertyInit("removeAbandonedTimeout", "300000");
			setPropertyInit("logAbandoned", "False");

			if (!result) {
				System.out.println("데이터베이스 프로퍼티 정보가 정확하지 않음");
			}
		} catch (IOException e) {
			System.out.println("데이터베이스 프로퍼티를 읽지 못함");
			result = false;
			e.printStackTrace();
		} finally {
			try {
				inputStream.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	} else {
		System.out.println("데이터베이스 프로퍼티를 읽지 못함");
		result = false;
	}
	return result;
}

 

프로퍼티의 키가 값이 없을 경우 프로퍼티 키와 기본값을 설정할 수 있게 "setPropertyInit()"메소드를 생성합니다.

/**
 * 프로퍼티 키가 비어 있을 경우에 기본값을 설정합니다.
 * @param propertyKey 프로퍼티 키
 * @param defaultValue 기본값
 */
private void setPropertyInit(String propertyKey, String defaultValue) {
	String propertyValue = databaseInfo.getProperty(propertyKey);
	if (propertyValue == null || propertyValue.trim().isEmpty()) {
		if (defaultValue == null || defaultValue.trim().isEmpty()) {
			System.out.println("데이터베이스 프로퍼티에 " + propertyKey + "가 없어 기본값(공백)으로 설정합니다.");
			defaultValue = "";
		} else {
			System.out.println("데이터베이스 프로퍼티에 " + propertyKey + "가 없어 기본값(" + defaultValue + ")으로 설정합니다.");
		}
		databaseInfo.setProperty(propertyKey, defaultValue);
	}
}

 

"id"로 여러개의 데이터베이스들을 구분하여 관리 할 수 있도록 메소드를 추가합니다.

/**
 * 데이터베이스 프로퍼티에 id를 가져옵니다.
 * @return id
 */
public String getId() {
	return databaseInfo.getProperty("id") == null ? "" : databaseInfo.getProperty("id").trim();
}

 

org.apache.commons.dbcp2.BasicDataSource"를 이용하여 데이터소스를 생성하는 메소드를 추가합니다.

"BasicDataSource"의 인스턴스를 생성하고 데이터베이스 드라이버와 데이터베이스 연결 정보를 설정합니다.

String driverClassName = databaseInfo.getProperty("driverClassName");
String url = databaseInfo.getProperty("url");
String username = databaseInfo.getProperty("username");
String password = databaseInfo.getProperty("password");

dataSource = new BasicDataSource();

// 데이터베이스 드라이버
dataSource.setDriverClassName(driverClassName);
// 데이터베이스와 연결 URL
dataSource.setUrl(url);
// 데이터베이스와 연결 계정
dataSource.setUsername(username);
// 데이터베이스와 연결 패스워드
dataSource.setPassword(password);

 

풀(Pool)에서 생성하고 유지되는 커넥션 수와 대기 시간을 설정합니다.

String initialSizeInfo = databaseInfo.getProperty("initialSize");
int initialSize = Integer.parseInt(initialSizeInfo);
String maxTotalInfo = databaseInfo.getProperty("maxTotal");
int maxTotal = Integer.parseInt(maxTotalInfo);
String maxIdleInfo = databaseInfo.getProperty("maxIdle");
int maxIdle = Integer.parseInt(maxIdleInfo);
String maxWaitMillisInfo = databaseInfo.getProperty("maxWaitMillis");
long maxWaitMillis = Long.parseLong(maxWaitMillisInfo);
String minIdleConnection = databaseInfo.getProperty("minIdle");
int minIdle = Integer.parseInt(minIdleConnection);

// 최초에 데이터베이스와 연결되는 커넥션 수
dataSource.setInitialSize(initialSize);
// 동시에 사용할 수 있는 최대 커넥션 개수
dataSource.setMaxTotal(maxTotal);
// 커넥션이 반환될 때 최대로 유지될 수 있는 커넥션 개수
dataSource.setMaxIdle(maxIdle);
// 커넥션을 가져오기 위해 대기하기 최대 시간
dataSource.setMaxWaitMillis(maxWaitMillis);
// 커넥션이 반환될 때 최소로 유지될 수 있는 커넥션 개수
dataSource.setMinIdle(minIdle);

 

커넥션이 유효한지 검사하는 쿼리와 응답시간을 설정합니다.

String validationQuery = databaseInfo.getProperty("validationQuery");
String validationQueryTimeoutSecondsInfo = databaseInfo.getProperty("validationQueryTimeoutSeconds");
int validationQueryTimeoutSeconds = Integer.parseInt(validationQueryTimeoutSecondsInfo);

// 커넥션이 유효한지 검사하기 위한 쿼리
dataSource.setValidationQuery(validationQuery);
// 커넥션이 유효한지 검사하는 쿼리가 실행되고 응답을 기다리는 시간
dataSource.setValidationQueryTimeout(validationQueryTimeoutSeconds);

 

커넥션마다 쿼리문을 풀링할지 여부와 풀링할 쿼리문 수를 설정합니다.

String poolStatementsInfo = databaseInfo.getProperty("poolStatements");
boolean poolStatements = Boolean.parseBoolean(poolStatementsInfo);
String maxOpenPreparedStatementsInfo = databaseInfo.getProperty("maxOpenPreparedStatements");
int maxOpenPreparedStatements = Integer.parseInt(maxOpenPreparedStatementsInfo);

// 커넥션마다 PreparedStatement 풀링 여부
dataSource.setPoolPreparedStatements(poolStatements);
// 커넥션마다 최대로 풀링할 PreparedStatement의 개수
dataSource.setMaxOpenPreparedStatements(maxOpenPreparedStatements);

 

커넥션의 생성후 최대로 이용 가능한 시간을 설정합니다.

String maxConnLifetimeMillisInfo = databaseInfo.getProperty("maxConnLifetimeMillis");
long maxConnLifetimeMillis = Long.parseLong(maxConnLifetimeMillisInfo);

// 커넥션의 생성후 최대로 이용 가능한 시간
dataSource.setMaxConnLifetimeMillis(maxConnLifetimeMillis);

 

풀(Pool)에서 사용되지 않는 커넥션들에 대한 유효성 검사를 설정합니다.

// 풀에서 사용되지 않는 커넥션들에 대한 유효성 검사
String testOnBorrowInfo = databaseInfo.getProperty("testOnBorrow");
boolean testOnBorrow = Boolean.parseBoolean(testOnBorrowInfo);
String testOnReturnInfo = databaseInfo.getProperty("testOnReturn");
boolean testOnReturn = Boolean.parseBoolean(testOnReturnInfo);
String testOnCreateInfo = databaseInfo.getProperty("testOnCreate");
boolean testOnCreate = Boolean.parseBoolean(testOnCreateInfo);
String testWhileIdleInfo = databaseInfo.getProperty("testWhileIdle");
boolean testWhileIdle = Boolean.parseBoolean(testWhileIdleInfo);

// 풀에서 커넥션을 가져올 때 커넥션이 유효한지 검사 여부
dataSource.setTestOnBorrow(testOnBorrow);
// 풀에 커넥션을 반환할 때 커넥션이 유효한지 검사 여부
dataSource.setTestOnReturn(testOnReturn);
// 풀에서 커넥션을 생성한 후 커넥션이 유효한지 검사 여부
dataSource.setTestOnCreate(testOnCreate);
// 풀에서 사용되지 않는 커넥션들에 대해 유효한지 검사 여부 (유효하지 않으면 제거)
dataSource.setTestWhileIdle(testWhileIdle);

 

풀(Pool)에서 사용되지 않는 커넥션들에 대한 추출 조건을 설정합니다.

// 풀에서 사용되지 않는 커넥션들에 대한 추출(제거)
String evictionPolicyClassName = databaseInfo.getProperty("evictionPolicyClassName");
String timeBetweenEvictionRunsMillisInfo = databaseInfo.getProperty("timeBetweenEvictionRunsMillis");
long timeBetweenEvictionRunsMillis = Long.parseLong(timeBetweenEvictionRunsMillisInfo);
String numTestsPerEvictionRunInfo = databaseInfo.getProperty("numTestsPerEvictionRun");
int numTestsPerEvictionRun = Integer.parseInt(numTestsPerEvictionRunInfo);
String minEvictableIdleTimeMillisInfo = databaseInfo.getProperty("minEvictableIdleTimeMillis");
long minEvictableIdleTimeMillis = Long.parseLong(minEvictableIdleTimeMillisInfo);
String softMinEvictableIdleTimeMillisInfo = databaseInfo.getProperty("softMinEvictableIdleTimeMillis");
long softMinEvictableIdleTimeMillis = Long.parseLong(softMinEvictableIdleTimeMillisInfo);

// 추출 정책 클래스 명 설정
dataSource.setEvictionPolicyClassName(evictionPolicyClassName);
// 풀에서 사용되지 않는 커넥션들에 대해 추출하는 Evictor 스레드의 검사 주기 (-1이면 검사하지 않음)
dataSource.setTimeBetweenEvictionRunsMillis(timeBetweenEvictionRunsMillis);
// Evictor 스레드의 검사 주기 때마다 풀에서 사용되지 않는 커넥션 중 검사할 커넥션 수
dataSource.setNumTestsPerEvictionRun(numTestsPerEvictionRun);
// 풀에서 사용되지 않는 커넥션이 최소로 유지될 수 있는 시간 (최소 유지 시간이 초과되면 제거)
dataSource.setMinEvictableIdleTimeMillis(minEvictableIdleTimeMillis);
// 풀에서 사용되지 않는 커넥션이 추출되기 전에 최소로 유지될 수 있는 시간
dataSource.setSoftMinEvictableIdleTimeMillis(softMinEvictableIdleTimeMillis);

 

풀(Pool)에서 버려진 커넥션들에 대한 복구 조건을 설정합니다.

// 풀에서 버려진 커넥션들에 대한 복구(재생)
String removeAbandonedOnBorrowInfo = databaseInfo.getProperty("removeAbandonedOnBorrow");
boolean removeAbandonedOnBorrow = Boolean.parseBoolean(removeAbandonedOnBorrowInfo);
String removeAbandonedTimeoutInfo = databaseInfo.getProperty("removeAbandonedTimeout");
int removeAbandonedTimeout = Integer.parseInt(removeAbandonedTimeoutInfo);

// 풀에서 커넥션을 가져올 때 버려진 커넥션을 찾아 제거할지 여부
dataSource.setRemoveAbandonedOnBorrow(removeAbandonedOnBorrow);
// 풀에서 버려진 커넥션으로 인정할 수 있는 시간
dataSource.setRemoveAbandonedTimeout(removeAbandonedTimeout);

 

풀(Pool)에서 버려진 커넥션들에 대한 로그 저장 여부를 설정합니다.

String logAbandonedInfo = databaseInfo.getProperty("logAbandoned");
boolean logAbandoned = Boolean.parseBoolean(logAbandonedInfo);

// 버려진 커넥션에 대한 로그 저장 여부
dataSource.setLogAbandoned(logAbandoned);

 

데이터소스를 시작하여 데이터베이스 커넥션 풀(Pool)을 생성합니다.

try {
	dataSource.start();
	initDatabasePool = true;
	System.out.println("데이터베이스 커넥션 풀을 생성함");
} catch (SQLException e) {
	e.printStackTrace();
	System.out.println("시스템 문제로 인해 데이터베이스 커넥션 풀을 생성하지 못함");
}

 

위에서 설명한 코드 전체를 "initDatabasePool()"메소드로 생성합니다.

/**
 * 데이터베이스 커넥션 풀을 생성합니다.
 */
private void initDatabasePool() {
	{Code}
}

 

클래스 생성자를 통해 데이터베이스 프로퍼티 파일을 읽고 데이터베이스 커넥션 풀(Pool)을 생성하게 생성자를 추가합니다.

/**
 * 생성자
 * @param databaseManagerPath 데이터베이스 매니저 프로퍼티 경로
 */
public TestDatabaseDataSource(String databaseManagerPath) {
	if (loadProperties(databaseManagerPath)) {
		initDatabasePool();
	}
}

 

데이터소스를 통해 커넥션을 가져오는 메소드를 추가합니다.

/**
 * 데이터소스를 통해 데이터베이스 연결 객체를 가져옵니다.
 * @return 데이터베이스 연결 객체
 */
public Connection getConnection() {
	Connection connection = null;

	try {
		connection = dataSource.getConnection();
		System.out.println("[" + Thread.currentThread().getName() + "] 데이터베이스 커넥션 객체[" + connection.toString() + "]를 가져옴");
	} catch (SQLException e) {
		System.out.println("[" + Thread.currentThread().getName() + "] 데이터베이스 커넥션 객체를 가져오지 못함");
		e.printStackTrace();
	}

	return connection;
}

 

커넥션을 반환하는 메소드를 추가합니다.

/**
 * 데이터소스에 데이터베이스 연결 객체를 반환합니다.
 * @param connection 데이터베이스 연결 객체
 */
public void closeConnection(Connection connection) {
	try {
		System.out.println("[" + Thread.currentThread().getName() + "] 데이터베이스 커넥션 객체[" + connection.toString() + "]를 반환함");
		connection.close();
	} catch (SQLException e) {
		e.printStackTrace();
	}
}

 

데이터소스를 파괴하는 메소드를 추가합니다.

/**
 * 데이터소스를 파괴합니다.
 */
public void destroyDatabasePool() {
	try {
		dataSource.close();
	} catch (SQLException e) {
		e.printStackTrace();
	}
}

 

4. "test2" 프로젝트의 "Java Resources"에 "src/main/resources"에서 "/com/home/project/test2/config/database-maria.properties"파일에서 "jndi"를 주석처리하고 다른 설정들은 주석을 해제합니다. 그리고 "removeAbandonedOnBorrow", "removeAbandonedTimeout", "logAbandoned" 등 추가로 설정합니다.

id=databaseMaria
#jndi=java:/comp/env/jdbc/test
driverClassName=org.mariadb.jdbc.Driver
url=jdbc:mariadb://localhost:3306/test
username=root
password=password
initialSize=20
maxWaitMillis=-1
maxTotal=20
maxIdle=20
validationQuery=select 1
validationQueryTimeoutSeconds=-1
poolStatements=True
maxOpenPreparedStatements=40
maxConnLifetimeMillis=-1
#blockWhenExhausted=True
minIdle=20
testOnBorrow=False
testOnReturn=False
testOnCreate=False
testWhileIdle=True
evictionPolicyClassName=org.apache.commons.pool2.impl.DefaultEvictionPolicy
timeBetweenEvictionRunsMillis=-1
numTestsPerEvictionRun=3
minEvictableIdleTimeMillis=1800000
softMinEvictableIdleTimeMillis=-1
removeAbandonedOnBorrow=True
removeAbandonedTimeout=300000
logAbandoned=False

 

5. "test2" 프로젝트의 "Java Resources/src/main/java"에서 "com.home.project.test2.listener.TestServletContextListener"의 "contextInitialized()"메소드에 있는 "databaseMappingMap"의 인자를 "TestDatabaseJNDI"에서 "TestDatabaseDataSource"로 수정합니다.

// DBId-Database 맵
Map<String, TestDatabaseDataSource> databaseMappingMap = new HashMap<String, TestDatabaseDataSource>();

String databaseManagers = sce.getServletContext().getInitParameter("DatabaseManager");
if (databaseManagers != null && !databaseManagers.trim().isEmpty()) {
	String[] databaseManagerPaths = databaseManagers.trim().split("\n|,|;|\\s+");
	for (String databaseManagerPath : databaseManagerPaths) {
		databaseManagerPath = databaseManagerPath.trim();
		if (!databaseManagerPath.isEmpty()) {
			TestDatabaseDataSource testDatabaseManager = new TestDatabaseDataSource(databaseManagerPath);
			if (testDatabaseManager.isInitDatabasePool()) {
				databaseMappingMap.put(testDatabaseManager.getId(), testDatabaseManager);
			}
		}
	}
}

 

"contextInitialized()"메소드에서 DAO를 "databaseMappingMap"의 형 변환을 "TestDatabaseJNDI"에서 "TestDatabaseDataSource"로 수정합니다.

if (repositoryeInstance != null) {
	Field[] Fields = findClass.getDeclaredFields();
	for (Field field : Fields) {
		TestAnnAutowired testAnnAutowired = field.getAnnotation(TestAnnAutowired.class);
		TestAnnQualifier testAnnQualifier = field.getAnnotation(TestAnnQualifier.class);
		if (testAnnAutowired != null && testAnnQualifier != null) {
			System.out.println("[Repository Field] " + field.getType().getName() + " 타입의 " + field.getName() + " 맴버 필드을 찾음");
			TestDatabaseDataSource testDatabaseManager = (TestDatabaseDataSource) databaseMappingMap.get(testAnnQualifier.value());
			if (testDatabaseManager != null) {
				field.setAccessible(true);
				try {
					field.set(repositoryeInstance, testDatabaseManager);
					System.out.println("[Repository Field] " + field.getName() + "에 의존성 주입을 처리함");
				} catch (IllegalArgumentException | IllegalAccessException e) {
					e.printStackTrace();
					System.out.println("[Repository Field] " + field.getName() + "에 의존성 주입을 처리하지 못함");
				}
			}
		}
	}
}

 

"contextDestroyed()"메소드에서 "databaseMappingMap"의 인자를 "TestDatabaseJNDI"에서 "TestDatabaseDataSource"로 수정합니다.

public void contextDestroyed(ServletContextEvent sce)  {
	System.out.println("ServletContext 파괴 실행"); 
	@SuppressWarnings("unchecked")
	Map<String, TestDatabaseDataSource> databaseMappingMap = (Map<String, TestDatabaseDataSource>)sce.getServletContext().getAttribute("DatabaseMappingMap");
	Iterator<String> keyIter = databaseMappingMap.keySet().iterator();
	while (keyIter.hasNext()) {
		String dbId = (String) keyIter.next();
		TestDatabaseDataSource testDatabaseManager = databaseMappingMap.get(dbId);
		testDatabaseManager.destroyDatabasePool();
	}
}

 

6. "test2" 프로젝트의 "Java Resources/src/main/java"에서 "com.home.project.test2.dao.TestLoginDaoImpl.java"의 멤버 필드 형을 "TestDatabaseJNDI"에서 "TestDatabaseDataSource"로 수정합니다.

@TestAnnAutowired
@TestAnnQualifier("databaseMaria")
private TestDatabaseDataSource testDatabaseManager;

 

7. 디비버(DBeaver) 툴을 실행하고 쿼리 스크립트에 현재 연결된 커넥션 수를 확인하면 최초에 데이터베이스와 연결되는 커넥션 수만큼 생성된 것을 확인할 수 있습니다.

결과 값이 23인 것은 디비버(DBeaver) 툴이 실행되면서 연결되는 커넥션 3개가 포함되어있기 때문입니다.

8. "Servers"탭에서 "tomcat8"를 선택하고 "start"버튼(start the server)을 클릭합니다. 웹 브라우저에서 "http://localhost:8080/test2/testform.do"를 입력합니다. 아이디에는 "testid"를 패스워드에는 "testpwd"를 입력하고 "로그인"버튼을 클릭합니다.

 

"Console"탭을 보면 JNDI를 통해 커넥션을 가져와 쿼리가 실행된 것을 확인할 수 있습니다.

[Console]

id : testid, password : testpwd
[http-nio-8080-exec-4] 데이터베이스 커넥션 객체[954616923, URL=jdbc:mariadb://localhost:3306/test, MariaDB Connector/J]를 가져옴
PreparedStatement를 생성함
Query[sql : 'SELECT MBR_ID, MBR_PWD, MBR_PWD_SALT, MBR_NM FROM MBR_ACCOUNT_TB WHERE MBR_ID=?', parameters : ['testid']]를 실행함
PreparedStatement를 종료함
[http-nio-8080-exec-4] 데이터베이스 커넥션 객체[954616923, URL=jdbc:mariadb://localhost:3306/test, MariaDB Connector/J]를 반환함
43ms 소요됨

 

 

728x90
반응형