Android java jdbc mysql

Android. Работаем с MS SQL без посредников

Предупреждение:
Вообще говоря, информация из статьи применима только для некоторых специфических случаев. Например, когда приложение работает внутри какого-то сегмента изолированной сети. А в общем случае посредник, коим является http-сервер, всё-таки нужен. Хотя бы потому, что при описанном методе логин/пароль доступа к базе зашиты в приложении и передаются по сети.

Статья является продолжением работы, о которой писал в своём предыдущем посте. Изначально эту часть писать не хотелось (см. предупреждение), но на хабре данная тема ещё не освещена, и в целом в сети меньше информации.
Поэтому, если Вам интересно, как можно из под Android напрямую работать с MS SQL (логично предположить, что и с другими БД, но на практике я этого не делал), добро пожаловать под кат.

В Java (и Android соответственно) соединение с удалёнными БД происходит при помощи JDBC-драйверов. В моём конкретном случае сервер майкрософтовский, и для него существует два драйвера: от Microsoft и открытая альтернатива JTDS. Причём последний, по заверениям разработчиков, работает быстрее и стабильней официального. Вот его и будем использовать.

Грабли: Актуальная версия JTDS на дату написания поста — 1.3.1. Но начиная с версии 1.3.0 драйвер переписан для совместимости с Java 7, и в сети встречаются сообщения о проблеме работы этих версий в Android. Поэтому необходимо использовать последнюю стабильную версию ветки 1.2.* (1.2.8), которая для Java 6.

На SQL-сервере должна быть настроена работа через TCP/IP.

Получение данных

Данные запросов драйвер возвращает в интерфейсе ResultSet который похож на андроидный Cursor, но быстрого способа приведения ResultSet к курсору я не нашёл. Поэтому поступим по-другому, данные из ResultSet будут конвертироваться в массив JSONArray и возвращаться в основную логику приложения, откуда с ними можно будет делать что угодно.

Весь обмен данными, как потенциально продолжительную операцию, будем делать асинхронно. В итоге получается примерно такой симпатичный класс для запросов к MS SQL:

EDIT: Переписал закрытие Connection, Statement и ResultSet в примерах в соответствии с основами.

На вход классу подаётся запрос, на выходе — готовый JSONArray, как если бы мы получали данные от веб-сервера. В отдельном потоке AsyncTask соединяется с сервером, получает данные в ResultSet и формирует из них JSON. Думаю, в целом код примитивен и в пояснениях не нуждается.

Для построения систем, работающих по подобному принципу, лучше передавать на вход не чистые select-запросы, а написать на сервере готовые T-SQL функции, передавая параметры к которым, можно получать нужные выборки.

Insert и Update. Передача данных на сервер

К сожалению, тут я не придумал ничего лучше, просто выполнение Insert-ов в транзакции. В прочем, метод отлично работает, вставка нескольких сотен записей занимает приемлемое время (около секунды на 100 строк, полей в реальном проекте больше, чем в приведённом примере).

EDIT: по совету eyeless_watcher использую метод addBatch() при заполнении PreparedStatement. Вот теперь вставка данных выполняется на самом деле быстро, в одной транзакции. Пример изменил.

Для вставки нужных значений используется PreparedStatement. Нумерация полей в нём почему-то начинается с единицы (см. документацию). А в остальном — всё должно быть понятно. update можно реализовать схожим образом, аналогично используя executeUpdate.

Приведённый подход был использован мной в «боевом» приложении первый раз.
На практике оказалось, что он стабильно работает. Время соединения с БД иногда может занимать несколько секунд (подключаюсь по wi-fi, сервер общий на всё предприятие), но сами транзакции выполняются быстро.

Источник

Как использовать базу данных MySQL в Java

Авторизуйтесь

Как использовать базу данных MySQL в Java

В этой статье мы научимся подключаться к базе данных MySQL из Java-кода и выполнять простые запросы для получения и обновления данных. Для того, чтобы получить доступ к базе данных, мы будем использовать JDBC (Java Database Connectivity) API, который входит в стандартную библиотеку Java. JDBC позволяет подключиться к любой базе данных: Postgres, MySQL, SQL Server, Oracle и т. д. — при наличии соответствующей реализации драйвера, необходимого для подключения. Для базы данных MySQL мы будем использовать драйвер Type 4 JDBC из пакета mysql-connector-java-5.1.23-bin.jar . Он написан на чистой Java, а значит, нам не понадобятся какие-либо нативные библиотеки или ODBC-мост. Все, что нам надо будет сделать — это положить JAR-файл в директорию, содержащуюся в CLASSPATH. JAR-файл содержит класс com.mysql.jdbc.Driver , необходимый для подключения к MySQL. Если его не окажется в CLASSPATH, во время выполнения программы выбросится исключение java.lang.ClassNotFoundException , поэтому убедитесь, что вы правильно настроили пути.

Кстати, если вы ищете хорошую книгу по использованию JDBC, обратите внимание на Practical Database Programming with Java (Ying Bai). Это относительно новая книга, и в ней рассматриваются две самые популярные базы данных: Oracle и SQL Server 2008. В книге используется IDE NetBeans для примеров и описываются все инструменты, необходимые для работы с базами данных в Java. Это отличная книга для начинающих и опытных программистов.

Подключаем базу данных MySQL с помощью JDBC

Для того, чтобы подключить базу данных MySQL, нам потребуется четыре вещи:

  1. Строка подключения JDBC (например:
    jdbc:mysql://localhost:3306/test).
  2. Имя пользователя (root).
  3. Пароль (root).
  4. База данных с некоторым количеством таблиц для примера (например, база данных книг).

Строка подключения для MySQL начинается с jdbc:mysql . Это название протокола соединения, за которым следуют хост и порт подключения, на которых запущена база данных. В нашем случае это localhost с портом по умолчанию 3306 (если вы его не поменяли при установке). Следующая часть — test — имя базы данных, которая уже существует в MySQL. Мы можем создать таблицу Books :

и наполнить её хорошими книгами:

Программа на Java, которая использует базу данных

Теперь давайте напишем программу на Java, которая будет подключаться к нашей базе данных, запущенной на localhost . Важно помнить о том, что необходимо закрывать соединение, запросы и результат выполнения после завершения работы с ними. Также важно закрывать их в finally-блоке, со своей try/catch оберткой, поскольку сам метод close() может кинуть исключение, что приведет к утечке ресурсов. За подробной информацией вы можете обратиться к этой статье. Кроме того, вы можете использовать обертку try-with-resource, которая появилась в Java 7. Более того, это стандартный способ работы с ресурсами в Java 1.7.

Читайте также:  Android apps security settings

При первом запуске у вас, возможно, будет ошибка No suitable driver found for jdbc:mysql , если драйвера MySQL нет в CLASSPATH:

Добавим нужный JAR-файл в путь и снова запустим программу. Другая частая ошибка — указать таблицу в строке соединения: jdbc:mysql://localhost:3306/test/book . В этом случае вылетит следущее исключение:

Успешный запуск программы выведет на экран следующее:

Результат верный, поскольку у нас в таблице только две книги: «Effective Java» и «Java Concurrency in Practice».

Кстати, если у вас был драйвер при компиляции, но отсутствует при запуске, вы получите исключение java.lang.ClassNotFoundException: com.mysql.jdbc.Driver . О том, как исправить эту ошибку, вы можете прочитать здесь.

Получаем данные с помощью SELECT-запроса в JDBC

Для получения данных из БД вы можете выполнить SELECT-запрос. В первом примере мы уже его использовали, но получили только количество строк. Теперь мы вернем сами строки. Большая часть программы останется без изменений, за исключением SQL-запроса и кода, возвращающего данные из объекта ResultSet :

Этот код выведет на экран следующее:

Тут есть пара моментов, на которые следует обратить внимание. Метод rs.getInt(1) используется для получения столбца с целочисленным типом, в нашем случае это столбец «id». Индексы в JDBC начинаются с единицы, поэтому rs.getInt(1) вернет значение первого столбца как целое число. В случае, если вы укажете неверный индекс (многие разработчики вызывают rs.getInt(0) для получения первого столбца), выбросится исключение InvalidColumnIndexException . Доступ к столбцам по индексу чреват ошибками, поэтому лучше использовать имя столбца, например, rs.getInt(«id») . Подробнее об этом вы можете прочитать в этой статье. Метод getString() используется для получения строковых значений из базы (например, VARCHAR ). Цикл будет выполняться, пока rs.next() не вернет false . Это значит, что строки закончились. В нашем случае в таблице две строки, поэтому цикл выполнится два раза, выводя информацию о книгах из таблицы на экран.

Добавляем данные с помощью INSERT-запроса в JDBC

Добавление данных мало отличается от их получения: мы просто используем INSERT-запрос вместо SELECT-запроса и метод executeUpdate() вместо executeQuery() . Этот метод используется для запросов INSERT, UPDATE и DELETE, а также для SQL DDL выражений, таких как CREATE, ALTER или DROP. Эти команды не возвращают результата, поэтому мы убираем все упоминания ResultSet ‘а в коде и изменяем запрос соответственно:

После запуска программы вы можете проверить таблицу в СУБД. На этот раз вы увидите три записи в таблице:

Теперь вы умеете подключаться к MySQL из Java-приложения и выполнять SELECT, INSERT, DELETE и UPDATE-запросы так же, как и в MySQL GUI. Для подключения мы используем объект Connection , для чтения результатов запроса — ResultSet . Убедитесь перед подключением, что сервер MySQL запущен и mysql-connector-java-5.1.17-bin.jar находится в CLASSPATH, чтобы избежать ClassNotFoundException .

4–5 декабря, Онлайн, Беcплатно

Когда разберетесь с подключением и простыми запросами, имеет смысл изучить, как использовать подготавливаемые запросы (Prepared Statement) в Java для избежания SQL-инъекции. В боевом коде всегда следует использовать подготавливаемые запросы и связывание переменных.

Если вам понравилось это руководство и не терпится узнать больше о подключении и работе с базой данных из Java-программ, обратите внимание на следующие статьи:

Источник

Android. Работаем с MS SQL без посредников

Предупреждение:
Вообще говоря, информация из статьи применима только для некоторых специфических случаев. Например, когда приложение работает внутри какого-то сегмента изолированной сети. А в общем случае посредник, коим является http-сервер, всё-таки нужен. Хотя бы потому, что при описанном методе логин/пароль доступа к базе зашиты в приложении и передаются по сети.

Статья является продолжением работы, о которой писал в своём предыдущем посте. Изначально эту часть писать не хотелось (см. предупреждение), но на хабре данная тема ещё не освещена, и в целом в сети меньше информации.
Поэтому, если Вам интересно, как можно из под Android напрямую работать с MS SQL (логично предположить, что и с другими БД, но на практике я этого не делал), добро пожаловать под кат.

В Java (и Android соответственно) соединение с удалёнными БД происходит при помощи JDBC-драйверов. В моём конкретном случае сервер майкрософтовский, и для него существует два драйвера: от Microsoft и открытая альтернатива JTDS. Причём последний, по заверениям разработчиков, работает быстрее и стабильней официального. Вот его и будем использовать.

Грабли: Актуальная версия JTDS на дату написания поста — 1.3.1. Но начиная с версии 1.3.0 драйвер переписан для совместимости с Java 7, и в сети встречаются сообщения о проблеме работы этих версий в Android. Поэтому необходимо использовать последнюю стабильную версию ветки 1.2.* (1.2.8), которая для Java 6.

На SQL-сервере должна быть настроена работа через TCP/IP.

Получение данных

Данные запросов драйвер возвращает в интерфейсе ResultSet который похож на андроидный Cursor, но быстрого способа приведения ResultSet к курсору я не нашёл. Поэтому поступим по-другому, данные из ResultSet будут конвертироваться в массив JSONArray и возвращаться в основную логику приложения, откуда с ними можно будет делать что угодно.

Весь обмен данными, как потенциально продолжительную операцию, будем делать асинхронно. В итоге получается примерно такой симпатичный класс для запросов к MS SQL:

EDIT: Переписал закрытие Connection, Statement и ResultSet в примерах в соответствии с основами.

На вход классу подаётся запрос, на выходе — готовый JSONArray, как если бы мы получали данные от веб-сервера. В отдельном потоке AsyncTask соединяется с сервером, получает данные в ResultSet и формирует из них JSON. Думаю, в целом код примитивен и в пояснениях не нуждается.

Для построения систем, работающих по подобному принципу, лучше передавать на вход не чистые select-запросы, а написать на сервере готовые T-SQL функции, передавая параметры к которым, можно получать нужные выборки.

Insert и Update. Передача данных на сервер

К сожалению, тут я не придумал ничего лучше, просто выполнение Insert-ов в транзакции. В прочем, метод отлично работает, вставка нескольких сотен записей занимает приемлемое время (около секунды на 100 строк, полей в реальном проекте больше, чем в приведённом примере).

Читайте также:  4pda duke nukem manhattan android

EDIT: по совету eyeless_watcher использую метод addBatch() при заполнении PreparedStatement. Вот теперь вставка данных выполняется на самом деле быстро, в одной транзакции. Пример изменил.

Для вставки нужных значений используется PreparedStatement. Нумерация полей в нём почему-то начинается с единицы (см. документацию). А в остальном — всё должно быть понятно. update можно реализовать схожим образом, аналогично используя executeUpdate.

Приведённый подход был использован мной в «боевом» приложении первый раз.
На практике оказалось, что он стабильно работает. Время соединения с БД иногда может занимать несколько секунд (подключаюсь по wi-fi, сервер общий на всё предприятие), но сами транзакции выполняются быстро.

Источник

Android java jdbc mysql

This is (as far as we are aware) the first and only native MySQL connector for Android. It connects directly to your database instead of relying on some sort of web service to act as a middleware between Android and the MySQL Server.

Using a webservice is still the recommended way of connecting to your database as it ensures only clients that are supposed to are connecting to your database and avoids the requirement of needing to expose your MySQL server to the Internet.

However, if you want, or have a need to connect directly to your database, then this is the library you need. This is a fairly basic MySQL connector compared to the official connectors that are available on other platforms. Therefore, below is a list of the known limitations of the library:

  • Doesn’t support compression, if the MySQL server reports that it supports compression, the connector will turn it off
  • Doesn’t support prepared statements
  • Only supports UTF8 or Latin 1 encodings
  • If authentication is required, then only mysql_native_password is supported

The library has been tested on the following MySQL Servers

We’ve so far only tested on the the highest minor version of each MySQL major version. You’ll notice that this doesn’t include MySQL 8.0. This is due to MySQL 8 changing the default authentication mechanism, this is something we plan on adding in the future. We haven’t yet tested with MariaDB however, the equivalent MeriaDB and MySQL version should be compatible and therefore should work in the same way.

Adding the library to your project couldn’t be simpler. Add the following to your apps build.gradle

The TAG above will be the tagged version number of the library.

Using the Library

Due to the way Android works, using the library is a little different compared to using the official connector on other platforms. This is due to to Android completely restricting any network activity on the main thread. Obviously you shouldn’t do any network activity on the main thread on any platform, but most platforms don’t stop you if you want to, however, Android will throw an exception if any network activity is done on the main thread. Therefore for each action you wish to take, such as connecting, switching databases, performing a query, the relevant method or constructor will take an interface which will get called once the action has completed which you can then handle.

Connecting to a MySQL Server

To connect to a MySQL server you first need to create the MySQL Connection object. You can do this as follows:

In the above example, is an optional parameter. By setting this, when the connection is established, the database name will be the default database used. The IConnectionInterface parameter handles connection specific events, such as successfully connected or exception handlers.

For example, when creating a new IConnectionInterface, you will need to provide the following methods: actionCompleted This means that the connection was successfully established and authenticated and the connection is ready for use

handleInvalidSQLException You shouldn’t really ever get this, but you might if you are connecting to a MySQL server that either is configured slightly differently as to what has bee tested or isn’t compatible with the connector, and has caused the connector to receive a network packet from the MySQL server that the connector wasn’t expecting.

handleMySQLException This will happen if a generic MySQL exception occurs within the connector

handleIOException This is used if an internal socket error occurs within the connector, for example, if server aborted the connection but the library didn’t realise and tried to perform an operation on the MySQL socket which is now closed

handleMySQLConnException This will be an exception related to a connection error, such as authentication failure

handleException This is a generic exception handler if any of the above doesn’t match the exception

That’s it, you have successfully connected, now we can execute some queries. Remember though, keep your connection object available in your class as this will be required in order to run queries on the DB.

You can change the default database to use in your established MySQL Connection. To do this, do not execute a standard USE DATABASE query as it won’t work.

You need to use your connection object and call the method switchDatabase(db, new IConnectionInterface()) . db being a String of your database name, and again, pass in the IConnectionInterface. If it switched successfully you will receive a call back to the actionCompleted method.

Execute Statement (Such as INSERT or UPDATE where no resultset is returned)

First of all you need to create a statement object from your connection object. You can do this using the following code snippet

Then in order to execute your statement you then do the following

query is your statement that you want to execute such as an INSERT or UPDATE statement. Again the second parameter is the IConnectionInterface and if the statement execute successfully, then actionCompleted will be called.

Execute Query (Such as SELECT)

Читайте также:  Как максимально почистить андроид

The execute query function allows you to execute a query such as SELECT or DESCRIBE, basically any query which return a result set. Same with executing a statement, you need to create the statement object from your connection object. This can be done using the following code snippet:

Then you need to call the executeQuery withn your statement object, but this time passing in a new IResultInterface as shown below:

The IResultInterface is pretty similar to the IConnectionInterface, you’ll have the same exception handlers, the main difference that if the query executes successfully, you’ll receive executionComplete which will have a parameter to the result set.

Processing a result set

When you execute a query such as SELECT or DESCRIBE, you will get a call back which will provide a result set object. This result set object contains all the information about what was returned such as the columns and the rows.

Get total number of rows returned

To get the total number of rows you can call resultset.getNumRows(); .

Get column definitions

The column definitions are stored in a List . You can get this using the following code snipper:

You can then loop over the list to get ColumnDefinition for each column returned in the result set. Within the column definition class, you can use the following methods: getDatabase The database name where the column was retrieved from

getTable The table name where the column was retrieved from

getColumnName The name of the column

getColumnType Returns an enum of type ColumnType

isPrimaryKey Returns a boolean as to whether or not the column is a primary key

Iterating through each row

You can iterate through each row, you first need to create an empty MySQLRow variable that can be used to be set within a while loop to get each row. You can call getNextRow() on the result set to get a MySQLRow. Once there are no rows left, null is returned. The following code snippet provides an example:

Once you have your MySQLRow you can then call the following methods to return the value of the field. Each of the following methods, take a String parameter which is the column name that should be retrieved.

  • getString(String column)
  • getInt(String column)
  • getFloat(String column)
  • getDouble(String column)
  • getBlob(String column) (Returns a byte[] array)

When sending dynamic paraters in your MySQL query, the string should be escaped to avoid SQL injection attacks. This can be done by using the following code snippet:

Currently the connection object can’t be passed between Android activities, so if you do need to create a new Activity and perform database action, you should close the DB connection in your current activity, pass the connection details to your new activity, and then create a new connection object in your new activity.

Also, to avoid leaving the DB connection open for no reason, in your activities onPause and onDestroy methods you should close the DB connection and then create a new instance to restablish the connection in the onCreate and/or onResume

You can close the DB by calling connection.close() .

Below you will find some examples on some of the common actions you might do with the MySQL Connector.

Each of the below examples creates a Connection object called mysqlConnection. This can be done using the following:

Switching Default Database

When you need to change the default database, (if a default database is set you do not need to prepend the database with the table name). You cannot use the the statement USE new_database , you have to use the method switchDatabase within the connection object as follows:

Executing statement (SQL statements that do not return a result set, e.g. INSERT, UPDATE, DELETE, TRUNCATE, CREATE, DROP ALTER)

Executing query (Statement which returns a MySQL Result Set, e.g. SELECT, SHOW, DESCRIBE)

Performing a query to return a result set is pretty much the same as above, the only difference is that instead of passing an IConnectionInterface , you instead pass an IResultInterface() and the executionComplete method provides you with a ResultSet object

Cannot Resolve Symbol Error

If you have added the library and the gradle sync works successfully but you are getting errors like cannot resolve symbol make sure that the imports at the top of the class file have been referenced.

This can be done in one of two ways:

  1. Put the cursor somewhere in the area of code which is showing red and hit Ctrl + Alt + Enter. Android Studio will provide tips on how to fix — one of them being to import the class. Select import and the error should go away.
  2. You can add the following two lines:

which will import all available classes from the library. However, this tends to be bad practice as only what’s needed from the library by your class should be imported. You can get round this by adding the two lines above, then when your class is finished, you can then do Ctrl + Alt + O which will organise your imports into what ones are required instead of a wildcard import.

javax.net.ssl.SSLHandshakeException: Handshake failed

If you see this error then connect to your DB via command line and run the following query:

If it shows TLSv1 then this won’t be supported by the Android MySQL Connector library. TLS 1.0 is a deprecated version of TLS and Java and/or Android no longer supports this TLS version.

If MySQL supports it, you can add tls_version=TLSv1.1 or tls_version=TLSv1.2 (Check your mysql version documentation to determine the supported TLS) to your /etc/main.cf file and restart MySQL. This needs to be added under the mysqld section of the config file.

If you are using Amazon RDS then you will need to use at least MySQL 5.7.16. Previous version of Amazon RDS for MySQL only support TLS 1.0 so the library won’t be able to connect.

Источник

Оцените статью