Время от времени я включаю музыку, выключаю отвлечения, такие как электронная почта и телефон, и перерабатываю некоторые базовые программы. Вещи, которые я знаю, и я сделал несколько раз. Цель состоит в том, чтобы попрактиковаться, вернуться к основам и получить новое понимание. Позже я прочитал о
CodeKata и понял, что то, что я делал, было не совсем неслыханным. Для тех, кто относится к созданию
программного обеспечения как к ремеслу , я могу смело рекомендовать эту практику.
Здесь я хочу поговорить об использовании Java для подключения к базе данных. Элементарно, говорите вы. Абсолютно, я согласен. Я настоятельно рекомендую ссылки
Соединение с базой данных Oracle ,
Закрытие соединений с базой данных в Java для ясного, краткого чтения, на случай, если вы хотите получить эти ответы. Однако, если вас интересует более подробное практическое путешествие по этой теме, я предлагаю вам продолжить.
Инструменты
Oracle. Я работал с различными приложениями, основанными на RDBMS и / или NoSql (
link ), и не имею широкого мнения за / против любого из них. Тем не менее, я склонен выбирать Oracle (
экспресс-издание ) даже для своей среды разработки. Называйте меня старомодным, но пока я не могу войти на «сервер базы данных» и выполнить запросы, чтобы подтвердить, что то, что я «думаю», делало мое приложение в базе данных, я не чувствую уверенности в своем коде.
Maven + Eclipse. Я бы предпочел согласиться со всеми, кто говорит, что Maven — это избыточное решение для простых приложений (до 10 классов). Но опять же, это моя интуиция. Я не чувствую уверенности, если не буду использовать инструменты, которые я буду использовать в любом приложении корпоративного уровня в моих кодекатах (из-за отсутствия лучшего названия). В конце концов, когда вы практикуете свои навыки, если вы не используете надлежащий набор инструментов, практические занятия немного бессмысленны, не так ли?
Разогрев
Как я уже говорил, я использую Maven. У меня есть пакетный файл с основными командами Maven (
подробнее об этом ), который я использую для создания любого нового Java-приложения, а затем импортирую его в Eclipse. Минус всего шума, вот так выглядит командный файл.
Файл: \ MavenCommands.bat
REM =============================
REM Set the env. variables.
REM =============================
SET PATH=%PATH%;C:\ProgramFiles\apache-maven-3.0.4\bin;
SET JAVA_HOME=C:\ProgramFiles\Java\jdk1.7.0
REM =============================
REM Standalone java application.
REM =============================
call mvn archetype:generate ^
-DarchetypeArtifactId=maven-archetype-quickstart ^
-DinteractiveMode=false ^
-DgroupId=foo.bar ^
-DartifactId=javadb001
Это создает полное Java-приложение с фиктивным классом, тестовым набором и т. Д. Файл pom содержит большинство деталей. Я склонен добавлять несколько стандартных элементов в файл pom, прежде чем пытаться что-либо еще. В этом случае я также добавлю тонкий клиент Oracle.
Файл: \ javadb001 \ pom.xml
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<!-- Unit test. -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.10</version>
<scope>test</scope>
</dependency>
<!-- Logging -->
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.0.7</version>
</dependency>
<!-- Oracle database driver. -->
<dependency>
<groupId>ojdbc</groupId>
<artifactId>ojdbc</artifactId>
<version>14</version>
</dependency>
</dependencies>
<build>
<!-- Compile and run with current Java version -->
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.5.1</version>
<configuration>
<source>1.6</source>
<target>1.6</target>
</configuration>
</plugin>
</plugins>
</build>
Если вы запустите эту «mvn -e clean install», это должно загрузить все зависимости и скомпилироваться просто.
Код (наконец)
В этом случае я думаю, что тестовый пример JUnit будет работать просто отлично. Нам просто нужно создать экземпляр драйвера (для подключения к Oracle), предоставить ему некоторые стандартные данные, выполнить попытку подключения, а затем выполнить попытку отключения.
Файл: /javadb001/src/test/java/foo/bar/database/TestConnection.java
public class TestConnection {
private final static Logger logger = LoggerFactory
.getLogger(TestConnection.class);
@Test
public void test() {
Connection connection = null;
try {
// Load the JDBC driver
String driverName = "oracle.jdbc.driver.OracleDriver";
Class.forName(driverName);
// Create a connection to the database
String serverName = "127.0.0.1";
String portNumber = "1521";
String sid = "XE";
String url = "jdbc:oracle:thin:@" + serverName + ":" + portNumber
+ ":" + sid;
String username = "funngames";
String password = "funngames";
connection = DriverManager.getConnection(url, username, password);
assertNotNull(connection);
logger.debug("All well");
} catch (ClassNotFoundException e) {
logger.debug(e.getMessage());
} catch (SQLException e) {
logger.debug(e.getMessage());
} finally {
if (connection != null) {
try {
connection.close();
} catch (SQLException e) {
logger.debug(e.getMessage());
fail("The connection could not be closed.");
}
}
}
}
}
Вы заметите, что, хотя это самый базовый (и бесполезный по функциональности) фрагмент кода, он довольно хорошо себя ведет. Он перехватывает требуемые исключения и пытается закрыть соединение. Что, возможно, не так легко увидеть, это то, что этот код также хорошо работает в сценариях корпоративных приложений. Он использует стандартный и надежный механизм регистрации, т. Е. Logback. Он использует стандартную сборку, релиз (и многое другое) инструмент, то есть Maven.
Короче говоря, если бы вы могли подумать о некой виртуальной полке, куда ваши инженеры-программисты могли бы подойти и выбрать стандартные шаблоны кода, это один из них. Непрактично в его нынешнем виде, но я надеюсь, что вы поняли концепцию.
Для тех, кто все еще со мной (кстати, поздравляю) и интересуюсь концепцией кодеката, о которой я говорил в начале статьи, есть еще немного.
Можем ли мы снять шаблонный код?
Я люблю Java, потому что это стабильность и прочее. Но, будучи ленивым человеком, я ненавижу писать код, который «кажется» мог бы обрабатываться самим языком. В этом текущем коде множество try-catches является бельмом на глазу. Я понимаю, почему они мне нужны, но это не обязательно означает, что я люблю их писать. Возможно, вы уже догадались, что я имею в виду
лучшее управление ресурсами, представленное
Project Coin .
В двух словах, Java 7 обещает обработать закрытие ресурсов, то есть Connection в этом случае, само по себе. Давайте попробуем.
Нам нужно сообщить maven, что мы хотим использовать jdk 7.
Файл: /javadb001/pom.xml
<!-- Compile and run with current Java version --> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>2.5.1</version> <configuration> <source>1.7</source> <target>1.7</target> </configuration> </plugin> </plugins>
И нам нужно обновить наш тестовый пример, чтобы создать Connection в попытке позволить java закрыть его самостоятельно.
public void test() throws SQLException {
String driverName;
try {
// Load the JDBC driver
driverName = "oracle.jdbc.driver.OracleDriver";
Class.forName(driverName);
} catch (ClassNotFoundException e) {
logger.debug(e.getMessage());
e.printStackTrace();
}
// Create a connection to the database
String serverName = "127.0.0.1";
String portNumber = "1521";
String sid = "XE";
String url = "jdbc:oracle:thin:@" + serverName + ":" + portNumber
+ ":" + sid;
String username = "funngames";
String password = "funngames";
try(Connection connection = DriverManager.getConnection(url, username, password)){
assertNotNull(connection);
logger.debug("Connection made.");
}
}
Если вы сравните этот фрагмент кода с предыдущим, мы избавились как минимум от трех блоков try-catch. Но этот код бесполезен в практическом сценарии, говорите вы. Полностью согласен. Как я упоминал ранее, цель состоит в том, чтобы практиковать написание кода — что-то обыденное — но несколькими способами (надеюсь, новыми способами) и учиться на практике. Целью является не производство готовых, многоразовых компонентов. Качество кода, мастерство важно в этом контексте. Преимущество будет в том, что касается более опытных инженеров в организации и связанных с этим преимуществ для бизнеса.
Наконец мой лакмусовый тест …
это якобы хороший, высококачественный код, насколько он хорош, когда мы запускаем его 10 000 раз в 5 потоках. Я ненавижу сообщать вам новости, но это не слишком хорошо. Вылетает после 20 — 25 казней. Зачем? И как это исправить? Я обсудил проблему и решение в
stackoverflow . Надеюсь, вам будет интересно.
Re-factor
Эта статья становится длиннее, и я должен завершить сейчас. Давайте переформулируем этот код в положение, когда вещи больше не находятся в модульных тестах. Код должен быть в некоторых классах, где они могут быть использованы клиентским кодом. Как выглядит обновленный тестовый код?
Файл: /javadb001/src/test/java/foo/bar/database/TestConnection.java
@Test
@PerfTest(invocations = 100, threads = 1)
@Required(max = 1200, average = 1000)
public void testConnectionFactoryAndUtil(){
Connection connection = ConnectionFactory.getConnection();
assertNotNull(connection);
Util.closeConnection(connection);
}
Сравните это с более ранним тестом. Это было 24 строки. Предполагая, что вы уверены, что этот тест выглядит лучше, как нам провести рефакторинг, чтобы это произошло? Это действительно ваш звонок, и вы можете сделать это несколькими способами. Вот мой дубль.
Файл: /javadb001/src/main/java/foo/bar/database/ConnectionFactory.java
public class ConnectionFactory {
private final static Logger logger = LoggerFactory
.getLogger(ConnectionFactory.class);
public static Connection getConnection() {
return getConnection("oracle.jdbc.driver.OracleDriver", "127.0.0.1",
"1521", "XE", "funngames", "funngames");
}
public static Connection getConnection(String driver, String host,
String port, String sid, String user, String pass) {
Connection connection = null;
try {
// Load the JDBC driver
Class.forName(driver);
String url = "jdbc:oracle:thin:@" + host + ":" + port + ":" + sid;
connection = DriverManager.getConnection(url, user, pass);
logger.info("Connection opened [{}]", connection.toString());
} catch (ClassNotFoundException e) {
logger.debug(e.getMessage());
e.printStackTrace();
} catch (SQLException e) {
logger.debug(e.getMessage());
e.printStackTrace();
}
return connection;
}
}
Файл: /javadb001/src/main/java/foo/bar/database/Util.java
public class Util {
private final static Logger logger = LoggerFactory.getLogger(Util.class);
public static void closeConnection(Connection connection){
if (connection != null) {
try {
logger.info("Attempting connection close [{}]", connection.toString());
connection.close();
Thread.sleep(500);
logger.info("Connection succesfuly closed.");
} catch (SQLException e) {
logger.debug(e.getMessage());
e.printStackTrace();
} catch (InterruptedException e){
logger.debug(e.getMessage());
e.printStackTrace();
}
}
}
}
Излишне говорить, что любой из этого кода вряд ли является новым или новаторским. Возможно, вы захотите проверить
этот класс для более полного набора служебных функций для закрытия соединения и связанных ресурсов. Не стесняйтесь использовать эту утилиту (это от Apache) или свернуть свою собственную.