Как класс драйвера находится в JDBC4
Одно из замечательных дополнений в версии 4 JDBC. Вам не нужно явно загружать
драйвера, вызвав Class.forName
больше. Когда приложение пытается подключиться к базе данных впервые, DriverManager
автоматически загружает драйвер, найденный в
приложение CLASSPATH
.
Мой вопрос: как? Что делать, если в пути к классам имеется несколько драйверов?
Одна вещь, которую я могу догадаться, состоит в том, что при разборе URL-адреса соединения, нужен ли драйвер JDBC или ODBC, можно выяснить, но как можно сказать из нескольких драйверов, совместимых с jdbc, которые нужно выбрать для базы данных, которую я использую? (скажем, я использую MySql, и мне нужен драйвер MySql-Connector). Есть ли статическое сопоставление таких драйверов базы данных в JVM?
Ответы
Ответ 1
Некоторая информация о загрузке драйвера JDBC4 взята из: http://www.onjava.com/2006/08/02/jjdbc-4-enhancements-in-java-se-6.html
Когда вызывается метод getConnection, DriverManager будет попытайтесь найти подходящий драйвер среди драйверов JDBC, которые были загружены при инициализации, и те, которые загружены явно с использованием тот же загрузчик классов, что и текущее приложение.
Методы DriverManager getConnection и getDrivers были расширенный для поддержки механизма поставщика услуг Java SE (SPM). Согласно SPM, услуга определяется как хорошо известный набор интерфейсы и абстрактные классы, а поставщик услуг - внедрение услуги. В нем также указывается, что услуга файлы конфигурации поставщика хранятся в META-INF/services каталог. Драйверы JDBC 4.0 должны включать файл META-INF/услуги/java.sql.Driver. Этот файл содержит имя Драйвер JDBC для java.sql.Driver. Например, чтобы загрузить драйвер JDBC для подключения к базе данных Apache Derby, Файл META-INF/services/java.sql.Driver будет содержать следующие запись:
org.apache.derby.jdbc.EmbeddedDriver
Теперь на ваш вопрос.
Мой вопрос: как? Что делать, если в Путь к классам?
В качестве правила загрузчика класса, любой найденный первый класс будет загружен, а если он уже загружен, он не будет перезагружен загрузчиком классов.
Ответ 2
Каждый драйвер, совместимый с JDBC 4, имеет в своем jar файле файл с именем META-INF/services/java.sql.Driver
, в котором он перечислит свои реализации java.sql.Driver
. Когда вы запрашиваете соединение, DriverManager
будет использовать ServiceLoader
для поиска всех (!) META-INF/services/java.sql.Driver
в пути к классам, а затем загрузит все перечисленные классы. Когда класс java.sql.Driver
загружен, он должен зарегистрироваться в DriverManager
, поэтому DriverManager
загружает все классы, используя загрузчик служб, и каждая реализация Driver
регистрирует себя.
Когда вы запрашиваете соединение от DriverManager
, DriverManager
будет перебирать все зарегистрированные драйверы, запрашивая у них Connection
. Драйвер будет использовать URL JDBC для проверки того, поддерживает ли он протокол (например, JDBC Jaybird/Firebird проверяет, начинается ли URL с "jdbc:firebirdsql:"
или "jdbc:firebird:"
). Если драйвер не поддерживает протокол, он вернет значение null
, если он поддерживает протокол, он либо вернет установленное соединение, либо выдаст SQLException
(например, если вы допустили ошибку в URL-адресе или не смогли подключения). Если все драйверы возвращают null
(ни один не поддерживает протокол), DriverManager
сгенерирует DriverManager
SQLException
с ошибкой "No suitable driver found for <url>"
Таким образом, наличие нескольких драйверов на пути к классам не имеет значения, если они поддерживают разные протоколы, однако, если для одной и той же базы данных имеется несколько драйверов (или, по крайней мере: одинаковые префиксы протоколов), он будет использовать первый в списке драйверов. В зависимости от версии Java, если этот драйвер завершится с ошибкой SQLException
, он продолжит работу со следующим драйвером (по крайней мере, Java 5 и выше) или прекратит попытки и сгенерирует исключение (я полагаю, это было в Java 1.4 или, возможно, даже раньше),
Ответ 3
В JDBC 4 драйверы регистрируются автоматически. Как это происходит?
Когда мы пишем
Connection con=DriverManager.getConnection("jdbc:mysql://localhost:3306/sonoo","root","root");
это вызовет статические блоки внутри класса DriverManager
. Если вы откроете исходный файл DriverManager, вы увидите статический блок
static {
loadInitialDrivers();
println("JDBC DriverManager initialized");
}
это вызовет функцию loadInitialDrivers();
и загрузит все драйверы и зарегистрируется автоматически. Поэтому нам не нужно явно регистрировать или загружать драйверы.