Прочитав эту статью, вы также сможете вручную написать часть исходного кода MyBatis (JDBC)

Java задняя часть MyBatis
Прочитав эту статью, вы также сможете вручную написать часть исходного кода MyBatis (JDBC)

«Эта статья участвовала в мероприятии Haowen Convocation Order, щелкните, чтобы просмотреть:Двойные заявки на внутреннюю и внешнюю стороны, призовой фонд в 20 000 юаней ждет вас, чтобы бросить вызов!"

1. Механизм сохранения

Постоянство: Сохраняйте данные на запоминающем устройстве с выключенным питанием для последующего использования. В большинстве случаев, особенно для приложений уровня предприятия, сохраняемость данных означает сохранение данных в памяти на жестком диске для «затвердевания», а процесс реализации сохраняемости в основном осуществляется через различные реляционные базы данных. Это для хранения данных в памяти в реляционной базе данных, конечно, они также могут храниться в файлах на диске и в файлах данных XML. В Java технология доступа к базе данных может получить доступ к базе данных только через JDBC.

Существует две основные формы доступа JDBC к базе данных:

  1. Напрямую используйте JDBC API для доступа к серверу базы данных (MySQL/Oracle).
  2. Косвенно используйте JDBC API для доступа к серверу базы данных и используйте сторонние инструменты O/R Mapping, такие как Hibernate, MyBatis и т. д. (Нижним уровнем по-прежнему является JDBC, JDBC является краеугольным камнем Java для доступа к базе данных, другие технологии являются инкапсуляцией JDBC)

2. Обзор JDBC

    JDBC (Java DataBase Connectivity)ЯвляетсяОбщий интерфейс для доступа и работы с универсальной базой данных SQL, не зависящей от конкретной системы управления базами данных.(набор API), которые определяют стандартную библиотеку классов Java, используемую для доступа к базе данных, (java.sql,javax.sql) с помощью этих библиотек можностандартныйспособ легко получить доступ к ресурсам базы данных. JDBC предоставляет унифицированный способ доступа к различным базам данных, скрывая некоторые детали от разработчиков. Цель JDBC — позволить программистам Java, использующим JDBC, подключаться к любомуПредоставляет реализацию JDBC (драйвер)система баз данных, которая Таким образом, программистам не нужно слишком хорошо разбираться в характеристиках конкретной системы баз данных, что значительно упрощает и ускоряет процесс разработки.

在这里插入图片描述

Проще говоря, сам JDBC является стандартом для Java для подключения к базе данных. Это уровень абстракции для подключения к базе данных. Он состоит из набора классов и интерфейсов, написанных на Java. Реализация интерфейса завершается каждой базой данных. производитель.

Шаги для написания JDBC следующие:

在这里插入图片描述

    ODBC(Open Database Connectivity, Open Database Connectivity), запущенный Microsoft под платформой Windows. Пользователю нужно только вызвать ODBC API в программе, а драйвер ODBC преобразует вызов в запрос вызова к определенной базе данных.

3. Получить соединение с базой данных

3.1 Загрузите зарегистрированный драйвер

Интерфейс java.sql.Driver — это интерфейс, который должны реализовать все драйверы JDBC. Этот интерфейс предоставляется поставщикам баз данных, и разные поставщики баз данных предоставляют разные реализации. В программе нет необходимости напрямую обращаться к классам, реализующим интерфейс Driver, но класс диспетчера драйверов (java.sql.DriverManager) вызывает эти реализации Driver.

  • Драйвер Оракула:oracle.jdbc.driver.OracleDriver
  • mySql-драйвер:com.mysql.jdbc.Driver

Загрузка драйвера: Чтобы загрузить драйвер JDBC, необходимо вызвать статический метод forName() класса Class и передать ему имя класса загружаемого драйвера JDBC.

  • Class.forName("com.mysql.jdbc.Driver");

3.2, принцип регистрации драйвера

Регистрация драйвера: класс DriverManager — это класс диспетчера драйверов, который отвечает за управление драйвером.

  • Используйте DriverManager.registerDriver(com.mysql.jdbc.Driver) для регистрации драйвера.

  • Обычно нет необходимости явно вызывать метод registerDriver() класса DriverManager для регистрации экземпляра класса драйвера, поскольку класс драйвера интерфейса DriverВсеСодержит блок статического кода, в котором вызывается метод DriverManager.registerDriver() для регистрации своего экземпляра. На следующем рисунке показан исходный код класса реализации драйвера MySQL:

在这里插入图片描述

Обычно он состоит из следующих двух шагов:

1. 把 com.mysql.jdbc.Driver 这一份字节码加载进 JVM。
2. 字节码被加载进JVM,就会执行其静态代码块.而其底层的静态代码块在完成注册驱动工作,将驱动注
 册到DriverManger 中。

3.3, получить объект соединения

Обычно мы используем метод getConnection DriverManager для создания объекта Connection.

Connection conn = DriverManager.getConnection(url,username,password);
// url=jdbc:mysql://localhost:3306/jdbcdemo
// 如果连接的是本机的 MySQL,并且端口是默认的 3306 ,则可以简写:
//  url=jdbc:mysql:///jdbcdemo
// username:当前访问数据库的用户名
// password:当前访问数据库的密码

3.3.1, детали URL

URL-адрес JDBC используется дляИдентифицирует зарегистрированного водителя, диспетчер драйверов использует этот URL-адрес, чтобы выбрать правильный драйвер для установления соединения с базой данных.

Стандартный URL-адрес JDBC состоит из трех частей (протокол: подпротокол: подимя), и каждая часть отделяется двоеточием.

  1. протокол: протокол в URL-адресе JDBC всегда jdbc (фиксированная запись).
  2. подпротокол: подпротокол, используемый для идентификации драйвера базы данных.
  3. подимя: метод идентификации базы данных. Под-имена могут различаться в зависимости от разных под-протоколов, цель использования под-имен состоит в том, чтобыНайдите базу данныхПредоставьте достаточно информации. ВключатьИмя процессора(соответствует ip адресу сервера), номер порта, имя базы данных.

在这里插入图片描述

  1. Обычное написание URL:
    • jdbc:mysql://hostname:номер порта службы mysql/имя базы данных?parameter=value¶meter=value
    • jdbc:mysql://localhost:3306/atguigu
    • jdbc:mysql://localhost:3306/atguigu**?useUnicode=true&characterEncoding=utf8** (Если программа JDBC несовместима с набором символов на стороне сервера, что приведет к искажению символов, вы можете указать набор символов на на стороне сервера через параметры)
    • jdbc:mysql://localhost:3306/atguigu?user=root&password=123456

3.4, метод подключения к базе данных

3.4.1 Метод 1

Мы можем напрямую получить драйвер регистрации и записать информацию о базе данных в коде.Эта проблема также очевидна, то есть проблема жесткого кодирования.Когда нам нужно изменить базу данных, нам нужно изменить исходный код Java напрямую.

	@Test
    public void testConnection4() {
        try {
            //1.数据库连接的4个基本要素:
            String url = "jdbc:mysql://localhost:3306/test";
            String user = "root";
            String password = "admin";
            String driverName = "com.mysql.jdbc.Driver";

            //2.加载驱动 (①实例化Driver ②注册驱动)
            Class.forName(driverName);

            //3.获取连接
            Connection conn = DriverManager.getConnection(url, user, password);
            System.out.println(conn);
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

3.4.2. Метод 2

Чтобы решить проблему жесткого кодирования в Mode 1, нам нужно поместить информацию о драйвере в файл конфигурации, а затем присвоить значения чтением.

	@Test
    public  void testConnection5() throws Exception {
    	//1.加载配置文件
        InputStream is = ConnectionTest.class.getClassLoader().getResourceAsStream("jdbc.properties");
        Properties pros = new Properties();
        pros.load(is);
        
        //2.读取配置信息
        String user = pros.getProperty("user");
        String password = pros.getProperty("password");
        String url = pros.getProperty("url");
        String driverClass = pros.getProperty("driverClass");

        //3.加载驱动
        Class.forName(driverClass);

        //4.获取连接
        Connection conn = DriverManager.getConnection(url,user,password);
        System.out.println(conn);

    }

Преимущества использования конфигурационных файлов:

  1. Реализовано разделение кода и данных, если вам нужно изменить конфигурационную информацию, вы можете изменить ее прямо в конфигурационном файле, не заходя в код.

  2. Если информация о конфигурации изменена, процесс перекомпиляции пропускается.

4. Идея ДАО

4.1. Нет ДАО

Когда нет DAO, в нашем коде много дублирования.

在这里插入图片描述

4.2. Введение в ДАО

    DAO (объект доступа к данным) Объект доступа к даннымЭто объектно-ориентированный интерфейс базы данных.Как следует из названия, он имеет дело с базой данных, зажатой между бизнес-логикой и ресурсами базы данных, и абстрактно инкапсулирует все операции доступа к источникам данных в общедоступном API. Написание программы заключается в создании интерфейса, определяющего все методы транзакций, которые будут использоваться в этом приложении. Основная операция в DAO: CRUD.

在这里插入图片描述

На приведенном выше рисунке DAO используется как компонент, и его основной целью является разработка метода На что следует обратить внимание при разработке метода?

  1. В функции сохранения вызывающая сторона должна передать несколько параметров, а затем сохранить данные в базе данных.
  2. В функции запроса каждая строка данных в результирующем наборе имеет несколько значений столбца, а затем возвращает эти данные вызывающему объекту.
  3. В процессе разработки, если необходимо передать несколько данных, обычно необходимо использовать JavaBean для их инкапсуляции.

4.3 Спецификация ДАО

DAO — это, по сути, повторно используемый компонент. Он включает в себя две спецификации:

  1. Спецификация субподряда (обратное доменное имя. имя модуля проекта. компонент)
   cn.util;    //存放工具类
   cn.domain; //装pss模块的domain类,模型对象.(Student)
   cn.dao; //装pss模块的dao接口.调用者将需要保存的数据封装到一个对象中,然后传递进来
    cn.dao.impl; //装dao接口的实现类.
   cn.test; //暂时存储DAO的测试类,以后的测试类不应该放这里.
  1. Соглашения об именах
    • Интерфейс DAO: указывает спецификацию операции CRUD модели, начиная с интерфейса I. Например: IStudentDAO
    • Класс реализации DAO: указывает реализацию интерфейса DAO, например: EmployeeDAOImpl.
    • Тестовый класс DAO: протестируйте все методы в компонентах DAO, например: EmployeeDAOTest.

Вызов предложения: интерфейсно-ориентированное программирование

  • Традиционный способ: EmployeeDAOImpl dao = new EmployeeDAOImpl();

  • Интерфейсно-ориентированное программирование: IEmployeeDAO dao = new EmployeeDAOImpl();

5. CRUD-операция JDBC

5.1, Объект оператора и его недостатки

5.1.1 Объект заявления

    Statementобъект используется для выполнения статического оператора SQL и возврата полученного результата.

在这里插入图片描述

  • Этот объект создается путем вызова метода createStatement() объекта Connection. Этот объект используется для выполнения статических операторов SQL и возврата результатов выполнения.
  • В интерфейсе оператора определены следующие методы для выполнения операторов SQL:
int excuteUpdate(String sql):执行更新操作INSERT、UPDATE、DELETE
ResultSet executeQuery(String sql):执行查询操作SELECT

5.1.2 Недостатки использования объектов Statement

Есть недостатки в использовании Statement для управления таблицами данных:

  1. Есть строковая операция, которая громоздка
  2. Есть проблема с SQL-инъекцией

SQL-инъекция — это использование некоторых систем, которые не полностью проверяют данные, вводимые пользователем, и внедряют недопустимые сегменты операторов SQL или команды во входные данные пользователя (например: SELECT user, password FROM user_table WHERE user='a' ИЛИ 1 = ' AND password = ' ИЛИ ​​'1' = '1') , тем самым используя механизм SQL системы для завершения вредоносного поведения.

public class StatementTest {

	// 使用Statement的弊端:需要拼写sql语句,并且存在SQL注入的问题
	@Test
	public void testLogin() {
		Scanner scan = new Scanner(System.in);

		System.out.print("用户名:");
		String userName = scan.nextLine();
		System.out.print("密   码:");
		String password = scan.nextLine();

		// SELECT user,password FROM user_table WHERE USER = '1' or ' AND PASSWORD = '='1' or '1' = '1';
		String sql = "SELECT user,password FROM user_table WHERE USER = '" + userName + "' AND PASSWORD = '" + password
				+ "'";//字符串拼接过于繁杂
		User user = get(sql, User.class);
		if (user != null) {
			System.out.println("登陆成功!");
		} else {
			System.out.println("用户名或密码错误!");
		}
	}

	// 使用Statement实现对数据表的查询操作
	public <T> T get(String sql, Class<T> clazz) {
		T t = null;

		Connection conn = null;
		Statement st = null;
		ResultSet rs = null;
		try {
			// 1.加载配置文件
			InputStream is = StatementTest.class.getClassLoader().getResourceAsStream("jdbc.properties");
			Properties pros = new Properties();
			pros.load(is);

			// 2.读取配置信息
			String user = pros.getProperty("user");
			String password = pros.getProperty("password");
			String url = pros.getProperty("url");
			String driverClass = pros.getProperty("driverClass");

			// 3.加载驱动
			Class.forName(driverClass);

			// 4.获取连接
			conn = DriverManager.getConnection(url, user, password);

			st = conn.createStatement();

			rs = st.executeQuery(sql);

			// 获取结果集的元数据
			ResultSetMetaData rsmd = rs.getMetaData();

			// 获取结果集的列数
			int columnCount = rsmd.getColumnCount();

			if (rs.next()) {

				t = clazz.newInstance();

				for (int i = 0; i < columnCount; i++) {
					// //1. 获取列的名称
					// String columnName = rsmd.getColumnName(i+1);

					// 1. 获取列的别名
					String columnName = rsmd.getColumnLabel(i + 1);

					// 2. 根据列名获取对应数据表中的数据
					Object columnVal = rs.getObject(columnName);

					// 3. 将数据表中得到的数据,封装进对象
					Field field = clazz.getDeclaredField(columnName);
					field.setAccessible(true);
					field.set(t, columnVal);
				}
				return t;
			}
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			// 关闭资源
			if (rs != null) {
				try {
					rs.close();
				} catch (SQLException e) {
					e.printStackTrace();
				}
			}
			if (st != null) {
				try {
					st.close();
				} catch (SQLException e) {
					e.printStackTrace();
				}
			}

			if (conn != null) {
				try {
					conn.close();
				} catch (SQLException e) {
					e.printStackTrace();
				}
			}
		}

		return null;
	}
}

在这里插入图片描述

5.2. Подготовленное заявление

Мы можем вызвать объект ConnectionpreparedStatement(String sql)способ получитьPreparedStatementобъект,Интерфейс PreparedStatement является подчиненным интерфейсом оператора, который представляет собой предварительно скомпилированный оператор SQL.

    PreparedStatementПараметры в операторе SQL, представленном объектом, представлены вопросительными знаками (?).PreparedStatementМетод setXxx() объекта для установки этих параметров.Метод setXxx() имеет два параметра, первый параметр — это индекс (начиная с 1) параметра в операторе SQL, который необходимо установить, а второй — SQL Оператор для установки значения параметра.

// 常用方法:
void setXxx(int parameterIndex,Xxx value); //设置第几个占位符的真正参数值.
// Xxx 表示数据类型,比如 String,int,long,Date等.
void setObject(int parameterIndex, Object x); //设置第几个占位符的真正参数值.
int executeUpdate(); //执行DDL/DML语句. 注意:没有参数
// 若当前 SQL是 DDL语句,则返回 0.
// 若当前 SQL是 DML语句,则返回受影响的行数.
ResultSet executeQuery(); //执行DQL语句,返回结果集.
close(); //释放资源

5.3 Сравнение подготовленного заявления и заявления

  1. PreparedStatementсоотношение объектовStatementЧитаемость и ремонтопригодность кода объекта.

  2. PreparedStatementчтобы максимизировать производительность.

    • DBServer будетпредварительно скомпилированоОператоры обеспечивают оптимизацию производительности. Поскольку предварительно скомпилированный оператор может вызываться неоднократно, код выполнения оператора после его компиляции компилятором DBServerкешировать это, то в следующий раз, когда вы его вызовете, если это тот же предварительно скомпилированный оператор, его не нужно компилировать, поскольку параметр напрямую передается в код выполнения скомпилированного оператора, он будет выполнен.
    • В операторе оператора, даже если это одна и та же операция, но из-за того, что содержимое данных разное, сам оператор не может совпадать, и нет смысла кэшировать оператор, Дело в том, что ни одна база данных не будет кэшировать скомпилированный код выполнения оператора. обычное заявление. Таким образом, входящий оператор компилируется один раз при каждом его выполнении.
  3. PreparedStatement предотвращает внедрение SQL.

5.4 Набор результатов

Запрос должен позвонитьPreparedStatementизexecuteQuery() метод, результатом запроса является объект ResultSet, объект ResultSet инкапсулирует набор результатов операции базы данных в виде логической таблицы, а интерфейс ResultSet предоставляется и реализуется производителем базы данных.

    То, что возвращает ResultSet, на самом деле является таблицей данных.. Имеется указатель на начало первой записи таблицы данных.

Объект ResultSet поддерживает указатель на текущую строку данных.курсор, изначально курсор находится перед первой строкой, вы можете передать объекту ResultSetnext()метод переходит на следующую строку. перечислитьnext()метод, чтобы проверить, является ли следующая строка допустимой. Если он действителен, метод возвращает значение true, и указатель перемещается вниз. Эквивалент объекта IteratorhasNext()а такжеnext()сочетание методов.

Когда указатель указывает на строку, к ней можно получить доступ, вызвавgetXxx(int index)илиgetXxx(int columnName)Получите значение каждого столбца. *Все индексы в соответствующих API-интерфейсах Java, участвующих во взаимодействии между Java и базой данных, начинаются с 1. *Например:

getInt(1), getString("name")

在这里插入图片描述

5.5, CRUD-операция

5.5.1 Класс пользователя

package domain;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

/**
 * @author Xiao_Lin
 * @date 2021/1/2 19:44
 */
@Data
@NoArgsConstructor
@AllArgsConstructor
public class User {
  //id
  private Integer id;
  //用户名
  private String username;
  //密码
  private String pwd;

  //构造方法的重载
  public User(String username, String pwd) {
    this.username = username;
    this.pwd = pwd;
  }
}

5.5.2 Я пользователь DAO

package dao;

import domain.User;
import java.util.List;

/**
 * @author Xiao_Lin
 * @date 2021/1/2 19:46
 */
public interface IUserDAO {
  public void insert(User user);

  public void delete(Integer id);

  public void update(User user);

  public List<User> selectAll();

  public User selectUserById(Integer id);
}

5.5.3. UserDAOImpl

package dao.impl;

import dao.IUserDAO;

import dao.utils.DaoUtils;
import domain.User;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

/**
 * @author Xiao_Lin
 * @date 2021/1/2 19:49
 */

public class UserDAOImpl implements IUserDAO {
  Connection connection = null;
  PreparedStatement ps = null;
  ResultSet rs = null;
  @Override
  public void insert(User user) {
    try {
      connection = DaoUtils.getConnection();
      String sql = "insert into user (username,pwd) values (?,?)";
       ps = connection.prepareStatement(sql);
      ps.setString(1,user.getUsername());
      ps.setString(2,user.getPwd());
      ps.executeUpdate();
      System.out.println("添加成功!!");
    } catch (SQLException e) {
      e.printStackTrace();
    }finally {
      DaoUtils.close(connection,ps,null);
    }
  }

  @Override
  public void delete(Integer id) {
    try {
      connection = DaoUtils.getConnection();
      ps = connection.prepareStatement("delete from user where id = ?");
      ps.setInt(1,id);
      ps.executeUpdate();
      System.out.println("删除成功!!");

    } catch (Exception e) {
      e.printStackTrace();
    }finally {
      DaoUtils.close(connection,ps,null);
    }
  }

  @Override
  public void update(User user) {
    try {
      connection = DaoUtils.getConnection();
       ps = connection.prepareStatement("update user set username = ? , pwd = ? where id = ?");
       ps.setString(1,user.getUsername());
       ps.setString(2,user.getPwd());
       ps.setInt(3,user.getId());
      ps.executeUpdate();
      System.out.println("修改成功");
    } catch (Exception e) {
      e.printStackTrace();
    }finally {
      DaoUtils.close(connection,ps,null);
    }

  }

  @Override
  public List<User> selectAll() {
    List<User> users = new ArrayList<>();
    try {
      connection = DaoUtils.getConnection();
      ps = connection.prepareStatement("select * from user");
      rs = ps.executeQuery();
      while (rs.next()){
        users.add(new User(rs.getInt("id"),rs.getString("username"),rs.getString("pwd")));
      }

    } catch (Exception e) {
      e.printStackTrace();
    }finally {
      DaoUtils.close(connection,ps,rs);
    }
    return users;
  }

  @Override
  public User selectUserById(Integer id) {
    User user = null;
    try {
      connection = DaoUtils.getConnection();
      ps = connection.prepareStatement("select * from user where id = ?");
      ps.setInt(1,id);
      rs = ps.executeQuery();
      while (rs.next()){
        user = new User(rs.getInt("id"),rs.getString("username"),rs.getString("pwd"));
      }

    } catch (Exception e) {
      e.printStackTrace();
    }finally {
      DaoUtils.close(connection,ps,rs);
    }
    return user;
  }
}

5.5.4. DaoUtils

package dao.utils;

import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.Driver;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Properties;

/**
 * @author Xiao_Lin
 * @date 2021/1/2 19:56
 */
public class DaoUtils {
  static Connection connection = null;
  static Properties properties = null;

  static {
    InputStream resourceAsStream = Thread.currentThread().getContextClassLoader()
        .getResourceAsStream("db.properties");
    properties = new Properties();
    try {
      properties.load(resourceAsStream);
      Class.forName(properties.getProperty("DriverClassName"));
    } catch (Exception e) {
      e.printStackTrace();
    }
  }

  public static Connection getConnection() throws SQLException {
   connection= DriverManager.getConnection(properties.getProperty("url"),properties.getProperty("username"),properties.getProperty("password"));
    return connection;
  }

  public  static void  close(Connection conn , PreparedStatement ps , ResultSet rs){

    try {
      if(rs!=null){
        rs.close();
      }
    } catch (SQLException e) {
      e.printStackTrace();
    }finally{
      try {
        if(ps!=null){
          ps.close();
        }
      } catch (SQLException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
      }finally{
        try {
          if(conn!=null){
            conn.close();
          }
        } catch (SQLException e) {
          // TODO Auto-generated catch block
          e.printStackTrace();
        }
      }

    }

  }

}

5.5.5 Класс испытаний

package dao.impl;


import dao.IUserDAO;
import dao.utils.DaoUtils;
import domain.User;
import java.sql.SQLException;
import java.util.List;
import org.junit.Test;

/**
 * @author Xiao_Lin
 * @date 2021/1/2 20:11
 */
public class UserDAOImplTest {
  IUserDAO userDAO = new UserDAOImpl();
  @Test
  public void insert() {
    userDAO.insert(new User("ghy","123"));

  }

  @Test
  public void delete() {
    userDAO.delete(14);
  }

  @Test
  public void update() {
    userDAO.update(new User(1,"张三","666"));
  }

  @Test
  public void selectAll() {
    List<User> users = userDAO.selectAll();
    users.forEach(System.out::print);
  }

  @Test
  public void selectUserById() {
    User user = userDAO.selectUserById(1);
    System.out.println(user);
  }
}

Шесть, работайте с полем типа BLOB

6.1 Введение в типы BLOB

В MySQL,BLOB — это большой двоичный объект., представляет собой контейнер, в котором может храниться большой объем данных, а также данные разных размеров. **Для вставки данных типа BLOB необходимо использовать PreparedStatement, поскольку данные типа BLOB нельзя записать с помощью конкатенации строк. ** MySQL имеет четыре типа BLOB, которые идентичны, за исключением максимального объема хранимой информации.

Если после указания соответствующего типа BLOB-объекта появляется сообщение об ошибке: xxx too big, то в каталоге установки mysql найдите файл my.ini и добавьте следующие параметры конфигурации:max_allowed_packet=16M. Также обратите внимание: после изменения файла my.ini вам необходимо перезапустить службу mysql.

在这里插入图片描述

6.2. Вставьте тип BLOB

//获取连接
Connection conn = JDBCUtils.getConnection();
		
String sql = "insert into customers(name,email,birth,photo)values(?,?,?,?)";
PreparedStatement ps = conn.prepareStatement(sql);

// 填充占位符
ps.setString(1, "张三");
ps.setString(2, "zs@126.com");
ps.setDate(3, new Date(new java.util.Date().getTime()));
// 操作Blob类型的变量
FileInputStream fis = new FileInputStream("zs.png");
ps.setBlob(4, fis);
//执行
ps.execute();
		
fis.close();
JDBCUtils.closeResource(conn, ps);

6.3. Изменить тип BLOB

Connection conn = JDBCUtils.getConnection();
String sql = "update customers set photo = ? where id = ?";
PreparedStatement ps = conn.prepareStatement(sql);

// 填充占位符
// 操作Blob类型的变量
FileInputStream fis = new FileInputStream("coffee.png");
ps.setBlob(1, fis);
ps.setInt(2, 25);

ps.execute();

fis.close();
JDBCUtils.closeResource(conn, ps);

6.4, прочитать тип БЛОГ из таблицы базы данных

String sql = "SELECT id, name, email, birth, photo FROM customer WHERE id = ?";
conn = getConnection();
ps = conn.prepareStatement(sql);
ps.setInt(1, 8);
rs = ps.executeQuery();
if(rs.next()){
	Integer id = rs.getInt(1);
    String name = rs.getString(2);
	String email = rs.getString(3);
    Date birth = rs.getDate(4);
	Customer cust = new Customer(id, name, email, birth);
    System.out.println(cust); 
    //读取Blob类型的字段
	Blob photo = rs.getBlob(5);//这里也可以通过列的索引来读取
	InputStream is = photo.getBinaryStream();
	OutputStream os = new FileOutputStream("c.jpg");
	byte [] buffer = new byte[1024];
	int len = 0;
	while((len = is.read(buffer)) != -1){
		os.write(buffer, 0, len);
	}
    JDBCUtils.closeResource(conn, ps, rs);
		
	if(is != null){
		is.close();
	}
		
	if(os !=  null){
		os.close();
	}
    
}

Семь, пакетная обработка

Восемь, транзакции базы данных

8.1 Выявленная проблема

Случай: Банковский перевод, перевод 1000 юаней Чжао Миню со счета Чжан Уцзи.

У нас есть учетная запись (счетная таблица). Затем начинаем передачу.

id name balance
1 Чжан Уцзи 20000
2 Чжао Минь 0

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

  1. Проверьте, больше ли баланс счета Чжан Уцзи или равен 1000. Если баланс меньше 1000, появится напоминание: Уважаемый, ваш баланс недостаточен. Если баланс больше или равен 1000 перевод.
SELECT * FROM account WHERE name = '张无忌' AND balance >= 1000;
  1. Уменьшите баланс счета Чжан Уцзи на 1000.
UPDATE account SET balance = balance - 1000 WHERE name = '张无忌';
  1. Добавьте 1000 к балансу счета Чжао Миня.
UPDATE account SET balance = balance + 1000 WHERE name = '赵敏';

В это время возникает проблема.Когда программа выполняется между шагами 2 и 3, внезапно возникает исключение.В это время это вызовет проблему несогласованности данных до и после передачи, что вызовет передачу, но там не так много денег на счету другой стороны. Основная причина этой проблемы заключается в том, что входящая и исходящая передачи — это две отдельные операции, сбой одной из которых не повлияет на выполнение другой. Но в трансферном бизнесе нам необходимо убедиться, что как входящие, так и исходящие операции либо завершаются успешно, либо терпят неудачу.

В настоящее время необходимо ввести понятие транзакции.

import org.junit.Test;

@Test
public void testTx() throws Exception {
// 贾琏欲执事
// 1 查询张无忌的账户余额是否大于等于1000
    Connection conn = JDBCUtil.getConnection();
    String sql = "SELECT * FROM account WHERE balance>=? AND name=?";
    PreparedStatement pst = conn.prepareStatement(sql);
// 给 ? 设置数据
    pst.setBigDecimal(1,new BigDecimal("1000"));
    pst.setString(2,"张无忌");
    ResultSet rs = pst.executeQuery();
    if(!rs.next()){
    System.out.println("余额不足");
    return;
    }
// 2 从张无忌的账户余额中减少1000.
    sql = "UPDATE account SET balance = balance-? WHERE name=?";
    pst = conn.prepareStatement(sql);
//设置? 的数据
    pst.setBigDecimal(1,new BigDecimal("1000"));
    pst.setString(2,"张无忌");
    pst.executeUpdate();
// 模拟出异常
    int a = 10/0;
// 3 在赵敏的账户余额中增加1000.
    sql = "UPDATE account SET balance = balance+? WHERE name=?";
    pst = conn.prepareStatement(sql);
//设置? 的数据
    pst.setBigDecimal(1,new BigDecimal("1000"));
    pst.setString(2,"赵敏");
    pst.executeUpdate();
// 释放资源
    JDBCUtil.close(conn,pst,rs);
    }

8.2. Транзакции

    Транзакция (Transaction, сокращенно tx): набор логических операций, которые заставляют данные изменяться из одного состояния в другое.

    Обработка транзакций (транзакционные операции):Все транзакции гарантированно выполняются как единица работы, даже если произойдет сбой, это выполнение нельзя будет изменить. При выполнении нескольких операций внутри транзакции либо все транзакцииотправлено (зафиксировано), то эти изменения сохраняются навсегда, либо система управления базами данных отменит все сделанные изменения, и вся транзакция будет отброшена к исходному состоянию.Откат можно рассматривать как операцию отмены.

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

8.3 ACID-свойства транзакций

  1. атомарностьАтомарность означает, что транзакция является неделимой единицей работы, и операции в транзакции выполняются либо все, либо ни одна из них.

  2. ПоследовательностьТранзакция должна вызывать переход базы данных из одного согласованного состояния в другое.

  3. ИзоляцияИзоляция транзакции означает, что выполнение транзакции не может быть нарушено другими транзакциями, то есть операции и данные, используемые в транзакции, изолированы от других параллельных транзакций, и одновременно выполняемые транзакции не могут мешать друг другу.

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

8.4, проблемы параллелизма базы данных

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

  1. грязное чтение: Для двух транзакций T1, T2, T1 чтения, которые были обновлены T2, но еще нене представленполе. После этого, если T2 откатится, содержимое, прочитанное T1, будет временным и недействительным.
  2. неповторяемое чтение: Для двух транзакций T1, T2, T1 чтение поля, затем T2возобновитьэто поле. После этого T1 снова считывает это же поле, но значение уже другое.
  3. галлюцинации: Для двух транзакций T1, T2, T1 читает поле из таблицы, затем T2 находится в этой таблице.вставлятьнесколько новых строк. После этого, если T1 снова прочитает ту же таблицу, будет еще несколько строк.

8.4.1, изоляция транзакций

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

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

8.4.2, уровень изоляции базы данных

База данных MySQL поддерживает 4 уровня изоляции транзакций. Уровень изоляции транзакций Mysql по умолчанию:ПОВТОРЯЕМОЕ ЧТЕНИЕ.

在这里插入图片描述

8.4.3 Установка уровня изоляции

Каждый раз, когда вы запускаете программу mysql, вы получаете отдельное соединение с базой данных.Каждое соединение с базой данных имеет глобальную переменную@@tx_isolation, указывающий текущий уровень изоляции транзакции.

8.4.3.1 Просмотр текущего уровня изоляции

SELECT @@tx_isolation;

8.4.3.2, установить текущий уровень изоляции mysql

set  transaction isolation level read committed;

8.4.3.3, установить глобальный уровень изоляции mysql

set global transaction isolation level read committed;

8.5. Операционные этапы транзакции

  1. Сначала определите начало транзакции, а затем измените данные.
  2. Во время выполнения, если нет проблем,提交(commit)Транзакция, изменения в это время будут сохранены навсегда.
  3. При возникновении проблемы (исключения) в процессе выполнения, отката транзакции (rollback), система управления базами данных отменит все сделанные модификации и вернется к Состояние, когда транзакция была запущена.
try{
	//取消事务的自动提交机制,设置为手动提交.
	connection对象.setAutoCommit(false);
	//操作1
	//操作2
	//异常
	//操作3
	//....
	//手动提交事务
	connection对象.commit();
}catch(Exception e){
	//处理异常
    //回滚事务
connection对象.rollback();
}

8.6, вопросы, требующие внимания

  1. По умолчанию транзакции автоматически фиксируются после выполнения операций DML.
  2. Транзакции, как правило, не требуются при выполнении операций запросов, но обычно мы также записываем транзакции в запросы.
  3. При написании кода, если код совершенно нормальный и исключения нет, но данные в базе не изменились, значит транзакция не была зафиксирована.
  4. В MySQL только механизм хранения InnoDB поддерживает транзакции и внешние ключи, а MyISAM не поддерживает транзакции.
  5. При последующей обработке транзакций она должна контролироваться на сервисном уровне.

Девять, пул соединений

9.1 Необходимость пула соединений с базой данных JDBC

При использовании и разработке веб-программ на основе баз данных традиционный режим в основном следует следующим шагам:

  1. Установите соединение с базой данных в основной программе.

  2. Выполнять sql-операции.

  3. Разорвите соединение с базой данных.

    У этой модели есть несколько существенных проблем:

  4. Обычные подключения к базе данных JDBC получаются с помощью DriverManager.Каждый раз, когда соединение с базой данных устанавливается, соединение должно быть загружено в память, а затем должны быть проверены имя пользователя и пароль (это занимает от 0,05 с до 1 с). Когда требуется соединение с базой данных, оно запрашивается из базы данных, и соединение разрывается после завершения выполнения. Этот метод потребует много ресурсов и времени. ** Ресурсы подключения к базе данных повторно не используются должным образом. **Если в сети одновременно находятся сотни или даже тысячи людей, частые операции подключения к базе данных будут занимать много системных ресурсов и даже вызывать сбои сервера.

  5. **Для каждого подключения к базе данных оно должно быть отключено после использования, **В противном случае, если программа не закроется из-за исключения, это вызовет утечку памяти в системе базы данных, что в конечном итоге приведет к перезапуску базы данных.

  6. Эта разработка не контролирует количество создаваемых объектов подключения., системные ресурсы будут распределяться без учета, например, слишком большого количества подключений, это также может привести к утечке памяти и сбоям сервера.

在这里插入图片描述

9.2, пул соединений с базой данных

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

    Основная идея пула соединений с базой данных: заключается в создании «буферного пула» для соединений с базой данных. Заранее поместите определенное количество соединений в буферный пул.Когда вам нужно установить соединение с базой данных, вам нужно только взять одно из «буферного пула» и вернуть его после использования.

    пул соединений с базой данныхОтвечает за выделение, управление и освобождение соединений с базой данных.Позволяет приложениям повторно использовать существующее соединение с базой данных вместо его повторного установления..

Пул соединений с базой данных создаст определенное количество соединений с базой данных в пуле соединений во время инициализации.Количество этих соединений с базой данных определяетсяМинимальное количество подключений к базе данных для установкииз. Независимо от того, используются ли эти соединения с базой данных, пул соединений всегда будет иметь как минимум это количество соединений. пул соединенийМаксимальное количество подключений к базе данныхОграничивает максимальное количество подключений, которые может занимать этот пул подключений.Когда количество подключений, запрошенных приложением к пулу подключений, превышает максимальное количество подключений, эти запросы будут добавлены в очередь ожидания.

在这里插入图片描述

9.2.1 Принципы и преимущества пула соединений с базой данных

在这里插入图片描述

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

  1. Повторное использование ресурсов

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

  2. Более высокая скорость отклика системы

    В процессе инициализации пула соединений с базой данных часто создается несколько соединений с базой данных, которые помещаются в резервный пул соединений. На этом инициализация соединения завершена. Для обработки бизнес-запросов напрямую используются существующие доступные соединения, что позволяет избежать дополнительных затрат времени на инициализацию и освобождение соединения с базой данных, тем самым сокращая время отклика системы.

  3. новые средства распределения ресурсов

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

  4. Унифицированное управление соединениями для предотвращения утечек соединения с базой данных

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

9.2.2, свойства пула соединений с базой данных

    Основные свойства: Пул соединений хранит объект соединения, а объект соединения зависит от четырех элементов, поэтому четыре элемента (имя класса драйвера, URL-адрес, имя пользователя, пароль) являются основными требованиями.

    другие свойства: Конфигурация для ограничения объекта подключения

​ 1. Инициализируйте количество подключений: заранее подготовьте инициализированный объект Connection в пуле подключений.

​ 2. Максимальное количество подключений: в пуле подключений находится не более определенного количества объектов Connection, а другие клиенты переходят в состояние ожидания.

​ 3. Минимальное количество подключений: в пуле подключений есть как минимум определенное количество объектов Connection.

​ 4. Максимальное время ожидания: используйте определенное время для подачи заявки на объект Connection.

сдаться.

​ 5. Максимальный тайм-аут: если вы не предпримете никаких действий в течение определенного периода времени, считается, что объект Connection автоматически отказывается.

9.3 Классификация пулов соединений с базой данных

Использование пула соединений с базой данных JDBCjavax.sql.DataSourceЧтобы указать, что DataSource — это просто интерфейс, который обычно реализуется сервером (Weblogic, WebSphere, Tomcat), а некоторые организации с открытым исходным кодом предоставляют реализации:

  1. DBCPЭто пул соединений с базой данных, предоставляемый Apache. Сервер tomcat поставляется с пулом соединений с базой данных dbcp.Скорость выше, чем у c3p0, но из-за собственной ошибки Hibernate3 больше не поддерживает его.
  2. C3P0Это пул соединений с базой данных, предоставляемый организацией с открытым исходным кодом, с относительно низкой скоростью и хорошей стабильностью. **hibernate официально рекомендуется для использования.
  3. ProxoolЭто пул соединений с базой данных проекта с открытым исходным кодом в sourceforge, который имеет функцию мониторинга состояния пула соединений.Менее стабилен, чем c3p0.
  4. BoneCPЭто пул соединений с базой данных, предоставляемый организацией с открытым исходным кодом с высокой скоростью.
  5. DruidЭто пул соединений с базой данных, предоставленный Ali.Говорят, что это пул соединений с базой данных, который сочетает в себе преимущества DBCP, C3P0 и Proxool, но скорость не уверена, быстрее ли BoneCP.

DataSource обычно называют источником данных, который включает в себя две части: пул соединений и управление пулом соединений.Принято называть DataSource пулом соединений.DataSource используется для замены DriverManager для получения соединения, которое является быстрым и может значительно повысить скорость доступа к базе данных.

Примечание:

  1. Источники данных отличаются от подключений к базе данных. Нет необходимости создавать несколько источников данных. Это фабрика, которая генерирует подключения к базе данных, поэтомуДля всего приложения требуется только один источник данных.
  2. Когда доступ к базе данных заканчивается, программа закрывает соединение с базой данных, как и раньше: conn.close(); но conn.close() не закрывает физическое соединение с базой данных, а только освобождает соединение с базой данных и возвращает его к соединению с базой данных. бассейн.

9.4, пул соединений DBCP

DBCP — это реализация пула соединений с открытым исходным кодом в рамках Apache Software Foundation, которая опирается на другую систему с открытым исходным кодом в рамках организации: Common-pool. Чтобы использовать эту реализацию пула соединений, необходимо добавить в систему следующие два файла jar:

  • Commons-dbcp.jar: Реализация пула соединений
  • Commons-pool.jar: библиотека зависимостей для реализации пула соединений.

** Пул соединений Tomcat реализован с использованием этого пула соединений. ** Пул соединений с базой данных может использоваться как интегрированным с сервером приложений, так и независимо приложением.

Источник данных отличается от подключения к базе данных. Нет необходимости создавать несколько источников данных. Это фабрика, которая создает подключения к базе данных, поэтому для всего приложения требуется только один источник данных.

Когда доступ к базе данных заканчивается, программа закрывает соединение с базой данных, как и раньше:conn.close(); Но приведенный выше код не закрывает физическое соединение с базой данных, он просто освобождает соединение с базой данных и возвращает его в пул соединений с базой данных.

9.4.1, Описание атрибута DBCP

Атрибуты По умолчанию иллюстрировать
initialSize 0 Количество начальных подключений, созданных при запуске пула подключений.
maxActive 8 Максимальное количество подключений, которые могут быть подключены одновременно в пуле подключений
maxIdle 8 Максимальное количество неактивных подключений в пуле подключений. Лишние простаивающие подключения будут освобождены. Если установлено отрицательное число, ограничений нет.
minIdle 0 Минимальное количество простаивающих соединений в пуле соединений, ниже которого будут создаваться новые соединения. Чем ближе этот параметр к maxIdle, тем выше производительность, так как создание и уничтожение соединений требуют ресурсов, но он не может быть слишком большим.
maxWait неограниченный Максимальное время ожидания. При отсутствии доступного соединения пул соединений будет ожидать максимальное время для освобождения соединения. Если лимит времени превышен, будет выдано исключение. Если установлено значение -1, это означает бесконечность ожидающий.
poolPreparedStatements false Подготовлено ли Заявление об открытом пуле
maxOpenPreparedStatements неограниченный Максимальное количество одновременных подключений после подготовки пула
minEvictableIdleTimeMillis Время, когда соединение в пуле соединений бездействовало в течение определенного периода времени и было удалено из пула соединений.
removeAbandonedTimeout 300 Повторно использовать неиспользуемые (заброшенные) соединения при превышении лимита времени
removeAbandoned false Следует ли перерабатывать бесполезные соединения (заброшенные) по истечении времени removeAbandonedTimeout.

9.4.2, способ подключения

//使用dbcp数据库连接池的配置文件方式,获取数据库的连接:推荐
// 创建一个DataSource对象
private static DataSource source = null;
static{
	try {
        //创建一个Properties,用于读取配置文件
		Properties pros = new Properties();
        //读取配置文件
		InputStream is = DBCPTest.class.getClassLoader().getResourceAsStream("db.properties");
		//加载配置文件
		pros.load(is);
		//根据提供的BasicDataSourceFactory创建对应的DataSource对象
		source = BasicDataSourceFactory.createDataSource(pros);
	} catch (Exception e) {
		e.printStackTrace();
	}
		
}
public static Connection getConnection4() throws Exception {
	Connection conn = source.getConnection();
	return conn;
}
driverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/test?rewriteBatchedStatements=true&useServerPrepStmts=false
username=root
password=123456

initialSize=10
#...

9.4.3, вопросы, требующие внимания

    Поскольку используется DBCP, ключ конфигурационного файла должен быть прописан в соответствии с его официальными требованиями.

9.5, пул соединений друидов (друидов)

Druid — это реализация пула соединений с базой данных на платформе с открытым исходным кодом Alibaba.Он сочетает в себе преимущества C3P0, DBCP, Proxool и других пулов БД, а также добавляет мониторинг журналов, который может очень хорошо отслеживать соединение с пулом БД и выполнение SQL. пул для мониторинга,Возможно, один из лучших пулов соединений.

9.5.1 Подробное объяснение параметров друида

настроить дефолт иллюстрировать
name Важность настройки этого свойства заключается в том, что при наличии нескольких источников данных их можно различать по имени при мониторинге. Если конфигурации нет, имя будет сгенерировано в формате: "DataSource-" + System.identityHashCode(this)
url URL-адрес для подключения к базе данных отличается для разных баз данных. Например: mysql: jdbc:mysql://10.20.153.104:3306/druid2 oracle: jdbc:oracle:thin:@10.20.149.85:1521:ocnauto
username Имя пользователя для подключения к базе данных
password Пароль для подключения к базе данных. Если вы не хотите, чтобы пароль записывался непосредственно в файл конфигурации, вы можете использовать ConfigFilter. Подробнее см. здесь:GitHub.com/alibaba/import…
driverClassName Автоматически определять по URL-адресу Этот элемент можно настроить или нет.Если druid не настроен, он автоматически определит dbType по URL-адресу, а затем выберет соответствующий driverClassName (рекомендуемая конфигурация)
initialSize 0 Количество физических подключений, установленных во время инициализации. Инициализация происходит при явном вызове метода init или при первом вызове getConnection.
maxActive 8 Максимальное количество пулов соединений
maxIdle 8 Он больше не используется, и конфигурация не действует.
minIdle Минимальное количество пулов соединений
maxWait Максимальное время ожидания при получении соединения в миллисекундах. После настройки maxWait справедливая блокировка включена по умолчанию, и эффективность параллелизма будет снижена.При необходимости вы можете использовать несправедливую блокировку, настроив для свойства useUnfairLock значение true.
poolPreparedStatements false Кэшировать ли подготовленныйStatement, который является PSCache. PSCache значительно повышает производительность баз данных, поддерживающих курсоры, таких как oracle. Рекомендуется закрывать под mysql.
maxOpenPreparedStatements -1 Чтобы включить PSCache, его значение должно быть больше 0. Если значение больше 0, poolPreparedStatements автоматически запускается и изменяется на true. В Druid нет проблем, что PSCache под Oracle занимает слишком много памяти, можно настроить это значение побольше, например 100
validationQuery SQL, используемый для определения того, действительно ли соединение, требует оператора запроса. Если validationQuery имеет значение null, testOnBorrow, testOnReturn и testWhileIdle не будут работать.
testOnBorrow true При подаче заявки на соединение выполните validationQuery, чтобы проверить, действительно ли соединение.Эта конфигурация снизит производительность.
testOnReturn false При возврате соединения выполните validationQuery, чтобы проверить, является ли соединение действительным.Эта конфигурация снизит производительность.
testWhileIdle false Рекомендуется настроить его на true, что не влияет на производительность и обеспечивает безопасность. Обнаружение при подаче заявки на соединение. Если время простоя больше, чем timeBetweenEvictionRunsMillis, выполните validationQuery, чтобы проверить, действительно ли соединение.
timeBetweenEvictionRunsMillis Есть два значения: 1) Поток Destroy обнаружит интервал подключения 2) Основание оценки testWhileIdle, подробности см. в описании свойства testWhileIdle.
numTestsPerEvictionRun Больше не используется, DruidDataSource поддерживает только один EvictionRun.
minEvictableIdleTimeMillis
connectionInitSqls SQL выполняется при инициализации физического соединения
exceptionSorter Автоматическая идентификация в соответствии с dbType Когда база данных выдает какое-то неисправимое исключение, отбрасывайте соединение
filters Тип атрибута — строка, а подключаемые модули расширения настраиваются с помощью псевдонимов.Обычно используемые подключаемые модули: filter для мониторинга статистики: filter for stat log filter: log4j для защиты от sql-инъекций filter: wall
proxyFilters Тип — список.Если фильтры и proxyFilters настроены одновременно, это отношение комбинации, а не отношение замены.

9.5.2, получить метод подключения

package com.utils;

import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.pool.DruidDataSourceFactory;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Properties;
import javax.sql.DataSource;

/**
 * @author Xiao_Lin
 * @date 2021/1/3 19:47
 */
public class DruidUtils {
  static DataSource ds = null;
  private DruidUtils(){

  }

  static {
    InputStream stream = Thread.currentThread().getContextClassLoader()
        .getResourceAsStream("db.properties");
    Properties properties = new Properties();
    try {
      properties.load(stream);
      ds = DruidDataSourceFactory.createDataSource(properties);
    } catch (Exception e) {
      e.printStackTrace();
    }
  }

  public static Connection getConnection(){
    try {
      return ds.getConnection();
    } catch (SQLException e) {
      e.printStackTrace();
    }
    return null;
  }
}

DriverClassName = com.mysql.jdbc.Driver
url = jdbc:mysql:///db?characterEncoding=utf-8&useSSL=false
username = root
password = 123456

9.5.3 Меры предосторожности

Ключ в файле конфигурации свойств должен совпадать с именем соответствующего свойства в DruidDataSource.

在这里插入图片描述

port java.io.IOException; import java.io.InputStream; import java.net.URL; import java.sql.Connection; import java.sql.SQLException; import java.util.Properties; import javax.sql.DataSource;

/**

  • @author Xiao_Lin
  • @date 2021/1/3 19:47

*/ public class DruidUtils { static DataSource ds = null; private DruidUtils(){

}

static { InputStream stream = Thread.currentThread().getContextClassLoader() .getResourceAsStream("db.properties"); Properties properties = new Properties(); try { properties.load(stream); ds = DruidDataSourceFactory.createDataSource(properties); } catch (Exception e) { e.printStackTrace(); } }

public static Connection getConnection(){ try { return ds.getConnection(); } catch (SQLException e) { e.printStackTrace(); } return null; } }


```properties
DriverClassName = com.mysql.jdbc.Driver
url = jdbc:mysql:///db?characterEncoding=utf-8&useSSL=false
username = root
password = 123456