Вопрос или проблема
Реальная проблема заключается в том, что сборка Java Maven должна создавать исполняемый JAR-файл приложения, а затем вставлять данные о JAR-файле в базу данных MySQL. Подключение SQL и вставки работают нормально в Windows без каких-либо проблем. Но когда это развернуто и выполняется на Linux, оно всегда возвращает нулевое подключение, и записи не могут быть внесены в базу данных. Подключение использует приведенную ниже строку подключения, которая прекрасно работает в пулах подключения GlassFish: 127.0.0.1:3306
. Поэтому я предполагаю, что с этим все в порядке.
Чтобы выяснить, в чем проблема, я создал простой исполняемый JAR-файл, подключающийся к базе данных MySQL. Также был создан пользователь для подключения к базе данных следующим образом:
CREATE USER 'dbUser'@'localhost' IDENTIFIED BY 'dbUserPWD';
GRANT SELECT, INSERT, UPDATE, DELETE ON test_db.* TO 'dbUser'@'localhost';
Строка подключения выглядит следующим образом:
jdbc:mysql://127.0.0.1:3306/@DB?zeroDateTimeBehavior=CONVERT_TO_NULL&serverTimezone=UTC&useSSL=false&allowPublicKeyRetrieval=true
Фактическое приложение, подключающееся к базе данных, выглядит следующим образом:
import java.sql.ResultSet;
import java.sql.PreparedStatement;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
public class DbConnect {
private static final String DB_DRIVER = "com.mysql.cj.jdbc.Driver";
private static final String DB_CONNECTION = "jdbc:mysql://127.0.0.1:3306/@DB?zeroDateTimeBehavior=CONVERT_TO_NULL&serverTimezone=UTC&useSSL=false&allowPublicKeyRetrieval=true";
/**
* @param args аргументы командной строки
*/
public static void main(String[] args) {
String db = args[0];
String user = args[1];
String pwd = args[2];
Connection con = null;
System.out.println("ТЕСТ ПОДКЛЮЧЕНИЯ К БД ЗАПУЩЕН");
System.out.println("БД : " + db + " - Пользователь : " + user + " - Пароль : " + pwd);
try {
con = getDBConnection(db, user, pwd);
if (con != null) {
if (con.isValid(10)) {
PreparedStatement stmt = null;
ResultSet rs = null;
String sql = "SHOW TABLES";
StringBuilder sb = new StringBuilder();
try {
stmt = con.prepareStatement(sql);
rs = stmt.executeQuery();
int count = 0;
while (rs.next()) {
count++;
if(count == 1){
sb.append(rs.getString(1));
}else{
sb.append(", ").append(rs.getString(1));
}
}
System.out.println("Количество таблиц : " + count);
System.out.println("Таблицы : " + sb);
rs.close();
stmt.close();
} catch (SQLException ex) {
System.out.println("Исключение : " + ex.getMessage());
}
}else{
System.out.println("Подключение недействительно");
}
con.close();
}else{
System.out.println("Подключение нулевое");
}
} catch (SQLException ex) {
System.out.println("Исключение : " + ex.getMessage());
} finally {
if (con != null){
try{
con.close();
} catch (SQLException ex){
System.out.println("Исключение : " + ex.getMessage());
}
}
}
}
public static Connection getDBConnection(String db, String user, String pwd) {
Connection conn = null;
try {
Class.forName(DB_DRIVER);
} catch (ClassNotFoundException e) {
System.out.println("НЕ НАЙДЕН DB_DRIVER : " + DB_DRIVER);
}
try {
System.out.println("СТРОКА ПОДКЛЮЧЕНИЯ К БД : " + DB_CONNECTION.replace("@DB", db));
conn = DriverManager.getConnection(DB_CONNECTION.replace("@DB", db), user, pwd);
return conn;
} catch (SQLException e) {
}
return conn;
}
}
Затем он выполняется в командной строке с помощью следующего вызова:
java -jar dbconnectiontester.jar "testDB" "dbUser" "dbUserPWD"
Таким образом, я могу легко продемонстрировать сценарий в контексте сборки Maven. Это работает без каких-либо проблем в Windows, но не работает в Linux Ubuntu 20.04. Может ли вышеупомянутое подключение быть отклонено из-за проблемы с правами пользователя Linux, о которой я не знаю?
Ваше мнение было бы очень полезно.
Проверено права пользователя в SQL:
SHOW GRANTS FOR 'dbUser'@'localhost';
+-----------------------------------------------------------------------------+
| Привилегии для dbUser@localhost |
+-----------------------------------------------------------------------------+
| GRANT USAGE ON *.* TO `dbUser`@`localhost` |
| GRANT SELECT, INSERT, UPDATE, DELETE ON `testDB`.* TO `dbUser`@`localhost` |
+-----------------------------------------------------------------------------+
Когда я запускаю (изменил пароль):
java -jar dbconntester.jar “testDB” “dbUser” “dbUser@PWD000”
ТЕСТ ПОДКЛЮЧЕНИЯ К БД ЗАПУЩЕН
БД : testDB – Пользователь : dbUser – Пароль : dbUser@PWD000
СТРОКА ПОДКЛЮЧЕНИЯ К БД : jdbc:mysql://127.0.0.1:3306/testDB?zeroDateTimeBehavior=CONVERT_TO_NULL&serverTimezone=UTC&useSSL=false&allowPublicKeyRetrieval=true
Количество таблиц : 0
Таблицы :
Таким образом, подключение к MySQL из JAR-файла работает без проблем. Мне предстоит разобраться с моей фактической проблемой, связанной со сборками Maven.
Спасибо
Ответ или решение
В вашем случае проблема, с которой вы столкнулись при подключении к MySQL из Java-приложения на Linux Ubuntu 20.04, может быть связана с несколькими возможными факторами, в том числе с конфигурацией MySQL, правами доступа пользователя, настройками сети или особенностями среды выполнения Java. Давайте детально разберёмся в вашей ситуации и предложим несколько шагов для решения проблемы.
1. Проверка конфигурации MySQL
Убедитесь, что MySQL сервер работает и слушает на правильном адресе и порту. В Linux используется такой же IP-адрес, как и в Windows, если приложение работает на том же сервере, что и MySQL. Однако стоит выполнить следующие проверки:
-
Запустите команду, чтобы проверить, что ваш MySQL сервер доступен по адресу
127.0.0.1
(илиlocalhost
):mysql -u dbUser -p -h 127.0.0.1 -P 3306
Если запрос пароля не проходит, возможно, вы не используете правильное имя пользователя или пароль.
-
Убедитесь, что MySQL настроен на прослушивание на нужном интерфейсе. Откройте файл конфигурации MySQL (
/etc/mysql/mysql.conf.d/mysqld.cnf
или аналогичный) и посмотрите, установлен ли параметрbind-address
на127.0.0.1
.
2. Настройка прав доступа пользователя
Вы создали пользователя, но в вашем случае есть вероятность, что есть ограничения по подключению по IP-адресу. Поскольку по умолчанию MySQL использует разные хосты для пользователей, попробуйте создать пользователя с правами доступа со всех хостов:
CREATE USER 'dbUser'@'%' IDENTIFIED BY 'dbUserPWD';
GRANT SELECT, INSERT, UPDATE, DELETE ON testDB.* TO 'dbUser'@'%';
После этого не забудьте выполнить:
FLUSH PRIVILEGES;
3. Права пользователя на уровне операционной системы
Убедитесь, что у вашего пользователя Linux есть права на выполнение вашего Java-приложения и доступ к библиотекам MySQL. Используйте команду ls -l
для проверки прав на ваш JAR файл. Если требуется, измените права с помощью chmod
.
4. Использование правильного JDBC драйвера
Убедитесь, что ваш проект использует правильный JDBC драйвер для MySQL. В частности, в вашем файле pom.xml
должно быть указано:
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.x</version> <!-- Замените на нужную версию -->
</dependency>
5. Обходные проблемы с localhost
Иногда может возникнуть проблема из-за разницы между localhost
и 127.0.0.1
. Попробуйте изменить строку подключения на:
private static final String DB_CONNECTION = "jdbc:mysql://localhost:3306/@DB?zeroDateTimeBehavior=CONVERT_TO_NULL&serverTimezone=UTC&useSSL=false&allowPublicKeyRetrieval=true";
6. Логи и отладка
Если проблемы сохраняются, включите логирование в MySQL, чтобы отслеживать все запросы и проверки подключения:
-
Откройте файл конфигурации MySQL и добавьте следующее:
general_log = 1 general_log_file = /var/log/mysql/mysql.log
-
Не забудьте перезапустить MySQL:
sudo systemctl restart mysql
Проверьте логи, чтобы увидеть любые ошибки подключения или другие сообщения, которые могут указать на источник проблемы.
Заключение
Вы уже проделали важную работу по определению проблемы, создав небольшой тестовый JAR. Убедитесь, что настройка прав доступа к базе данных правильная, проверьте конфигурацию MySQL и используйте правильные параметры подключения. Выполнив вышеуказанные шаги, вы должны решить проблему подключения. Если же проблема всё еще остается, рассмотрите возможность проверки сетевых настроек или конфигураций безопасности (например, UFW или iptables), которые могут блокировать ваш доступ к базе данных.