Время от времени я включаю музыку, выключаю отвлечения, такие как электронная почта и телефон, и перерабатываю некоторые базовые программы. Вещи, которые я знаю, и я сделал несколько раз. Цель состоит в том, чтобы попрактиковаться, вернуться к основам и получить новое понимание. Позже я прочитал о
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) или свернуть свою собственную.