Лекция 13. Разное

Работа с СУБД

Рассмотрим работу программы на примере СУБД MySQL

Разработаем два класса:

  1. MysqlConnect - обслуживание соединения
  2. DBTest - демонстрационная программа

Схема работы с СУБД:

_images/jdbc1.png

В системе должны быть установлены драйвера коннектора jdbc-mysql, которые можно скачать по адресу:

http://dev.mysql.com/downloads/connector/j/

Описание класса MysqlConnect:

Пакеты в заголовке:

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.Properties;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
class MysqlConnect {
    // данные для работы с СУБД
    // название драйвера СУБД
    private static final String DATABASE_DRIVER =
         "com.mysql.jdbc.Driver";
    // адрес MySQL с указанием имени базы
    private static final String DATABASE_URL =
         "jdbc:mysql://localhost:3306/test_java?useSSL=false";
    // имя пользователя MySQL
    private static final String USERNAME = "root";
    // пароль для доступа к базе
    private static final String PASSWORD = "123456";
    // макс. количество соединений
    private static final String MAX_POOL = "250";
..
..
   // объект "соединение"
    private Connection connection;
    // объект "свойства соединения"
    private Properties properties;

    // метод для формирования записи свойств
    private Properties getProperties() {
        if (properties == null) {
            properties = new Properties();
            properties.setProperty("user", USERNAME);
            properties.setProperty("password", PASSWORD);
            properties.setProperty("MaxPooledStatements", MAX_POOL);
        }
        return properties;
    }
 ..

Установка соединения:

// connect database
public Connection connect() {
  if (connection == null) {
     try {
       Class.forName(DATABASE_DRIVER);
       connection =
         DriverManager.getConnection(DATABASE_URL, getProperties());
     } catch (ClassNotFoundException | SQLException e) {
       e.printStackTrace();
     }
   }
   return connection;
}

Разрыв соединения с СУБД:

    // disconnect database
    public void disconnect() {
        if (connection != null) {
            try {
                connection.close();
                connection = null;
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }
} // конец описания класса

В главном классе программы создаем соединение и скачиваем записи из таблицы months:

public class DBTest
{
  public static void main(String[] args) {
    MysqlConnect mysqlConnect = new MysqlConnect();
    String sql = "SELECT * FROM `months`";
    try {
      PreparedStatement statement =
          mysqlConnect.connect().prepareStatement(sql);
      ResultSet rs = statement.executeQuery();
      ..
                       while (rs.next()) {
                               String num = rs.getString("num");
                               String name = rs.getString("name");
                               System.out.println("num : " + num);
                               System.out.println("name : " + name);
                       }
       } catch (SQLException e) {
          e.printStackTrace();
       } finally {
          mysqlConnect.disconnect();
       }
       }
}

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

java -cp mysql-connector-java-5.1.39-bin.jar:. DBTest

Элементы ФП

Функциональная парадигма - это подход к программированию, в центре которого

находится понятие функции (в математическом смысле), а сама программа -

процесс вычисления некоторой функции.

Принципы ФП:

  • Объекты неизменяемы (можно создать новый объект, но нельзя изменить старый).
  • Функции не имеют побочных эффектов (нет указателей, ссылок на глобальные переменные).
  • Функции - параметры.
  • Широко применяются безымянные лямбда-функции.
  • Используется выведение типов компилятором.

Поддержка ФП была введена в Java 8. Пример с кнопкой:

// обработчик нажатия на кнопку (стиль ООП)
button.addActionListener(new ActionListener() {
  public void actionPerformed(ActionEvent event) {
     System.out.println("button clicked");
 }
});
// функциональный стиль
button.addActionListener(event -> System.out.println("button clicked"));

Различные стили записи лямбда-функций:

// функция без аргументов
Runnable noArguments = () -> System.out.println("Hello World");
// функция с одним аргументом
ActionListener oneArgument =
   event -> System.out.println("button clicked");
// функция с блоком кода
Runnable multiStatement = () -> {
       System.out.print("Hello");
    System.out.println(" World");
};
// функция с двумя аргументами
BinaryOperator<Long> add = (x, y) -> x + y;
// явное указание типов аргументов
BinaryOperator<Long> addExplicit = (Long x, Long y) -> x + y;

Пример с обработкой коллекции:

import java.util.*;

public class Example1
{
  public static void main(String[] args) {
         List<String> colors =
      Arrays.asList("Red", "Orange", "Blue", "White", "Black", "Yellow");

    // опасный цикл
       for(int i=0;i<colors.size();i++)
               System.out.println(colors.get(i));

    // перебор коллекции
       for(String color: colors)
               System.out.println(color);
  }
}

Вариант перебора:

// перебор с лямбда-функцией
colors.forEach((String color) -> System.out.println(color));

// перебор с лямбда-функцией (сокращенная версия)
colors.forEach(System.out::println);

Вариант с трансформацией списка:

import java.util.*;

public class Example2
{
  public static void main(String[] args) {
         List<String> colors =
      Arrays.asList("Red", "Orange", "Blue", "White", "Black", "Yellow");
      List<String> uppercaseColors = new ArrayList<String>();
      colors.forEach(color -> uppercaseColors.add(color.toUpperCase()));
      System.out.println(uppercaseColors);
  }
}
$ java Example2
[RED, ORANGE, BLUE, WHITE, BLACK, YELLOW]

Другой вариант:

import java.util.*;

public class Example3
{
  public static void main(String[] args) {
       List<String> colors =
    Arrays.asList("Red", "Orange", "Blue", "White", "Black", "Yellow");
    List<String> uppercaseColors = new ArrayList<String>();

    colors.stream()
          .map(color -> color.toUpperCase())
          .forEach(color -> System.out.print(color + " "));

      System.out.println();
  }
}

Варианты функций, возвращаемые stream():

  • .filter() - отбирает элементы, для которых лямбда-функция возвращает true
  • .map() - применяет лямбда-функцию к каждому элементу коллекции
  • .reduce() - пытается обработать два параметра и отобрать один, затем передать по коллекции дальше
  • .collect() - накопление результата при движении по коллекции

Подсчет строк, начинающихся на B:

import java.util.*;

public class Example5
{
  public static void main(String[] args) {
       List<String> colors =
    Arrays.asList("Red", "Orange", "Blue", "White", "Black", "Yellow");
    List<String> uppercaseColors = new ArrayList<String>();

    long count=
      colors.stream()
            .filter(color -> color.startsWith("B"))
            .count();
    System.out.println(count);
  }
}
import java.util.*;

public class Example6
{
  public static void main(String[] args) {
       List<String> colors =
    Arrays.asList("Red", "Orange", "Blue", "White", "Black", "Yellow");
    List<String> uppercaseColors = new ArrayList<String>();
    colors.stream()
          .map(color -> color.length())
          .forEach(color -> System.out.println(color));
    System.out.println();
  }
}

Программа выводит длины слов

Регулярные выражения

Одним из важнейших механизмов поиска и обработки данных

являются регулярные выражения

Для работы подключат пакеты:

import java.util.regex.Matcher;
import java.util.regex.Pattern;

Пример использования:

import java.util.regex.Matcher;
import java.util.regex.Pattern;

class RegexDemo
{
   public static void main(String[] args)
   {
      Pattern p=Pattern.compile(".*(\\d)+ab.*");
      Matcher m=p.matcher("qq5abbb");
      System.out.println(m.matches());
      System.out.println(m.group(1));
   }
}

Взаимодействие с С++

Java и CPP

Для взаимодействия Java-программ с функциями, написанными на С++, используется

интерфейс JNI

Алгоритм построения совместной программы:

  1. Пишем код Java-класса
  2. Компилируем Java-программу
  3. Создаем заголовочный файл для С++
  4. Пишем C++файл
  5. Компилируем C++ файл и получаем динамическую библиотеку
  6. Запускаем Java-программу

Java-класс:

public class Hello {
       // функция С++
       public native void hello();
       public static void main(String[] args) {
       Hello h=new Hello();
       h.hello();
       }
       static {
               System.loadLibrary("hello");
       }
}

Компиляция Java-программы:

javac Hello.java

Создание заголовочного файла:

javah -jni Hello

Создаем файл hello.c с определением функции hello():

JNIEXPORT void JNICALL Java_Hello_hello(JNIEnv *e, jobject o)
{
       printf("Hello from C!");
}

Имя вызываемой функции берем из h-файла. Компилируем С-файл и получаем библиотеку:

g++ -dynamiclib
    -o libhello.jnilib
    -I/opt/local/lib/gcc47/gcc/x86_64-apple-darwin13/4.7.4/include
    hello.c

Здесь в параметре -I указан путь к заголовочному файлу jni.h

Запускаем Java-программу:

java Hello

Вопросы для самоконтроля