1. Понимание JDBC
JDBC
используется вJava
Подключение к базе данных в языковом программированииAPI
.JDBC
это спецификация, предоставляющая набор интерфейсов, обеспечивающих переносимый доступ к базовой базе данных.API
. использоватьJDBC驱动程序
для доступа к базе данных и для хранения данных в базе данных.
Объясните две приведенные выше картинки:
Приложение Java сначала подключается к драйверу JDBC через JDBC API.Эти драйверы JDBC предоставляются основными производителями баз данных для JDBC.Мы можем загрузить пакет jar в Интернете для использования, а затем подключиться к нашей базе данных через драйвер JDBC.
Первый шаг — добавить драйвер
1.在项目当中创建一个文件夹为lib
2.把Mysql驱动包复制到该文件夹下
3.builder path 编译路径
Второй шаг — подключение к базе данных
package con.meils.jdbc.conn;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
public class ConnectionClass {
public static void main(String[] args) throws ClassNotFoundException, SQLException {
// TODO Auto-generated method stub
// 1、加载驱动
// 把com.mysql.jdbc.Driver这份字节码加载进JVM
// 当一份字节码加载进JVM的时候,就会执行字节码文件中的静态代码块
// 这里加载该字节码之后会实例化一个驱动器
Class.forName("com.mysql.jdbc.Driver");
// 2、连接
String url = "jdbc:mysql://localhost:3306/mytest";
String username = "root";
String password = "zjj19970517";
Connection connection = DriverManager.getConnection(url, username, password);
// 3、验证连接
System.out.println(connection); // 如果有输出,表明连接成功
}
}
Третий шаг - работа с базой данных для создания таблицы
package con.meils.jdbc.ddl;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.Statement;
public class CreateTable {
public static void main(String[] args) throws Exception {
// TODO Auto-generated method stub
// 1\加载驱动
// 把com.mysql.jdbc.Driver这份字节码加载进JVM
// 当一份字节码加载进JVM的时候,就会执行字节码文件中的静态代码块
// 这里加载该字节码之后会实例化一个驱动器
Class.forName("com.mysql.jdbc.Driver");
String url = "jdbc:mysql://localhost:3306/jdbc_db";
String username = "root";
String password = "zjj19970517";
// 2\ 连接数据库
Connection connection = DriverManager.getConnection(url, username, password);
// 3\创建sql语句
String sql = "create table stu (id int , name varchar(20), age int)";
// 4\执行sql语句
Statement st = connection.createStatement();
int row = st.executeUpdate(sql);
// 5\释放
st.close();
connection.close();
}
}
Зачем освобождать ресурсы?
Шаг 4 Вставьте данные
package con.meils.jdbc.dml;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.Statement;
public class InsertClass {
public static void main(String[] args) {
// TODO Auto-generated method stub
// ================ 插入数据 ================
Connection conn = null;
Statement st = null;
try {
// 1、加载驱动
Class.forName("com.mysql.jdbc.Driver");
// 2、创建连接
String url = "jdbc:mysql://localhost:3306/mytest";
String user = "root";
String password = "zjj19970517";
conn = DriverManager.getConnection(url, user, password);
// 3、创建sql语句
String sql = "insert into stu values(1, 'zjj', 20)";
st = conn.createStatement();
// 4、执行语句
int row = st.executeUpdate(sql);
System.out.println(row);
}catch (Exception e) {
e.printStackTrace();
} finally {
// 5、释放
if(st!=null) {
try {
st.close();
}catch (Exception e) {
e.printStackTrace();
}
}
if(conn!=null) {
try {
conn.close();
}catch (Exception e) {
e.printStackTrace();
}
}
}
}
}
Шаг 5 Операция запроса
package con.meils.jdbc.dql;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
public class QueryClass {
public static void main(String[] args) throws SQLException, ClassNotFoundException {
// TODO Auto-generated method stub
// ================ 查询数据 ================
// 1\加载驱动
// 把com.mysql.jdbc.Driver这份字节码加载进JVM
// 当一份字节码加载进JVM的时候,就会执行字节码文件中的静态代码块
// 这里加载该字节码之后会实例化一个驱动器
Class.forName("com.mysql.jdbc.Driver");
String url = "jdbc:mysql://localhost:3306/mytest";
String username = "root";
String password = "zjj19970517";
// 2\ 连接数据库
Connection connection = DriverManager.getConnection(url, username, password);
// 3\创建sql语句
String sql = "select count(*) as total from stu"; // 查询一共有几行数据
// 4\执行sql语句
Statement st = connection.createStatement();
ResultSet rs = st.executeQuery(sql);
if(rs.next()) {
int count = rs.getInt("total");
System.out.println(count); // 1
}
// 5\释放
st.close();
connection.close();
}
}
Таблица сравнения типов данных:
В основном мы научились работать с базой данных выше, но в этом использовании есть много недостатков, таких как: каждый шаг операции требует подключения к базе данных, что приводит к потерям, поэтому нам нужно использовать идею DAO, чтобы справиться с этим. на практике.
2. Дизайн ДАО
1. Что такое ДАО
Объект хранения данных DAO (объект доступа к данным) между уровнем бизнес-логики и уровнем сохраняемости реализует постоянный доступ к данным.
Когда DAO не используется:
Использование ДАО:
3. Отношение отображения ORM
4. Домен
1. Знайте домен
2. Класс домена
3. Сохраните данные
4. Получить данные
5. Спецификация дизайна DAO
кейс
Мы можем написать интерфейс DAO, который определяет общие методы работы с базой данных. В это время мы будем подключаться к нескольким базам данных одновременно, таким как mysql и oracle. Мы можем реализовать два класса, oracleDao и mysqlDao соответственно. Разные классы определяют разные баз данных операций Код, реализующий функцию, действительно тот же самый.
Так что интерфейсно-ориентированное программирование — очень важный и хороший способ.
1. Соглашение об именах пакетов
2. Соглашение об именах классов
3. Этапы разработки
Каталог выглядит следующим образом
Реализация контента:
Конкретное содержимое класса реализации интерфейса:
package com.meils.jdbc.dao.impl;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;
import com.meils.jdbc.dao.IStudentDao;
import com.meils.jdbc.domain.Student;
import com.meils.jdbc.utils.JdbcUtil;
/**
* 实现DAO接口的类
* @author apple
*
*/
public class StudentDaoImpl implements IStudentDao{
@Override
/**
* 存储学生
* @param stu
*/
public void save(Student stu) {
// TODO Auto-generated method stub
Connection conn = null;
PreparedStatement ps = null;
try {
// 连接数据库
conn = JdbcUtil.getConnection();
String sql = "insert into student (name, age) values (? , ?)";
// 创建预编译
ps = conn.prepareStatement(sql);
ps.setString(1, stu.getName());
ps.setInt(2, stu.getAge());
// 执行更新
ps.executeUpdate();
} catch (Exception e) {
e.printStackTrace();
} finally {
JdbcUtil.close(conn, ps, null);
}
}
@Override
public void delete(int id) {
Connection conn = null;
PreparedStatement ps = null;
try {
// 连接数据库
conn = JdbcUtil.getConnection();
String sql = "delete from student where id = ?";
// 创建预编译
ps = conn.prepareStatement(sql);
ps.setInt(1, id);
// 执行更新
ps.executeUpdate();
} catch (Exception e) {
e.printStackTrace();
} finally {
JdbcUtil.close(conn, ps, null);
}
}
@Override
public void update(int id, Student stu) {
Connection conn = null;
PreparedStatement ps = null;
try {
conn = JdbcUtil.getConnection();
String sql = "update student set name=?, age=? where id = ? ";
ps = conn.prepareStatement(sql);
ps.setString(1, stu.getName());
ps.setInt(2, stu.getAge());
ps.setInt(3, id);
// 执行
ps.executeUpdate();
} catch (Exception e) {
e.printStackTrace();
} finally {
JdbcUtil.close(conn, ps, null);
}
}
@Override
public Student findOne(int id) {
Connection conn = null;
PreparedStatement ps = null;
ResultSet rs = null;
try {
conn = JdbcUtil.getConnection();
// sql语句
String sql = "select * from student where id = ?";
ps = conn.prepareStatement(sql);
ps.setInt(1, id);
// 执行
rs = ps.executeQuery();
if (rs.next()) {
// 保存数据
Student stu = new Student();
stu.setName(rs.getString("name"));
stu.setAge(rs.getInt("age"));
stu.setId(rs.getInt("id"));
return stu;
}
} catch (Exception e) {
e.printStackTrace();
} finally {
// 销毁
JdbcUtil.close(conn, ps, rs);
}
return null;
}
@Override
public List<Student> findAll() {
Connection conn = null;
Statement st = null;
ResultSet rs = null;
try {
conn = JdbcUtil.getConnection();
st = conn.createStatement();
String sql = "select * from student ";
rs = st.executeQuery(sql);
List<Student> list = new ArrayList<Student>();
while (rs.next()) {
Student stu = new Student();
stu.setName(rs.getString("name"));
stu.setAge(rs.getInt("age"));
stu.setId(rs.getInt("id"));
list.add(stu);
}
return list;
} catch (Exception e) {
e.printStackTrace();
} finally {
JdbcUtil.close(conn, st, rs);
}
return null;
}
}
Напишите тестовый класс:
package com.meils.jdbc.dao.test;
import java.util.List;
import org.junit.Test;
import com.meils.jdbc.dao.IStudentDao;
import com.meils.jdbc.dao.impl.StudentDaoImpl;
import com.meils.jdbc.domain.Student;
/**
* StudentDao测试类
* @author apple
*/
public class StudentDaoTest {
public static void main(String[] args) {
// TODO Auto-generated method stub
}
@Test
public void save() {
Student stu = new Student();
stu.setName("张伟");
stu.setAge(21);
IStudentDao dao = new StudentDaoImpl();
dao.save(stu);
}
@Test
public void delete() {
IStudentDao dao = new StudentDaoImpl();
dao.delete(4);
}
@Test
public void update () {
Student stu = new Student();
stu.setName("mmmmm");
stu.setAge(16);
IStudentDao dao = new StudentDaoImpl();
dao.update(5, stu);
}
@Test
public void findOne() {
IStudentDao dao = new StudentDaoImpl();
Student stu = dao.findOne(5);
System.out.println(stu);
}
@Test
public void findAll() {
IStudentDao dao = new StudentDaoImpl();
List<Student> allStu = dao.findAll();
System.out.println(allStu);
}
}
Класс инструментов JDBC:
package com.meils.jdbc.utils;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
/**
* JDBC 工具类
* @author apple
*
*/
public class JdbcUtil {
// 配置信息
public static String driverName = "com.mysql.jdbc.Driver";
public static String url = "jdbc:mysql://localhost:3306/mytest";
public static String userName = "root";
public static String password = "zjj19970517";
static {
try {
// 加载驱动,因为是在static块中,所以只会加载一次
Class.forName(JdbcUtil.driverName);
}catch (Exception e) {
e.printStackTrace();
}
}
/**
* 连接数据库
* @return 返回连接对象
*/
public static Connection getConnection() {
try {
return DriverManager.getConnection(JdbcUtil.url, JdbcUtil.userName, JdbcUtil.password);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**
* 关闭连接,并释放资源
* @param conn
* @param st
* @param rs
*/
public static void close(Connection conn, Statement st, ResultSet rs) {
if(conn!=null) {
try {
conn.close();
}catch(Exception e) {
e.printStackTrace();
}
}
if(st!=null) {
try {
st.close();
}catch(Exception e) {
e.printStackTrace();
}
}
if(rs!=null) {
try {
rs.close();
}catch(Exception e) {
e.printStackTrace();
}
}
}
}
3. Рефакторинг кода DAO
4. Интерфейс выписки
1 Statement 是父接口,PreparedStatement 和 CallableStatement 是子接口。
2 Statement 用于java应用程序与数据库之间的传送数据,比如传送sql语句过去,到数据库执行操作。
3 Statement 用于通用的访问,使用静态sql,其实并不好,容易SQL注入
4 PreparedStatement 用于预编译模版SQL语句,可以在运行的时候传入参数
5 CallableStatement 访问存储过程的时候使用
5. Предварительно скомпилированные операторы
Предотвратить SQL-инъекцию:
Руководство по инкапсуляции Java JDBC DAO
6. Управляйте базой данных через класс DB
Другой способ обернуть JDBC:
package com.meils.jdbc.db;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
public class MysqlDB {
Connection conn = null; // 创建连接对象
Statement st = null; // 创建编译语句对象
PreparedStatement ps = null; // 创建预编译语句对象
ResultSet rs1 = null; // 结果集
// 配置信息
// 驱动名称
private static final String driverName = "com.mysql.jdbc.Driver";
// 数据库的地址
private static final String URL = "jdbc:mysql://localhost:3306/mytest";
// 数据库登录用户名
private static final String userName = "root";
// 数据库登录密码
private static final String pwd = "zjj19970517";
/**
* 连接数据库
* @return
*/
public Connection getConnection() {
try {
Class.forName(driverName);
this.conn = DriverManager.getConnection(URL, userName, pwd);
System.out.println("连接成功");
return conn;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
// 构造函数
public MysqlDB() {
this.getConnection();
}
/**
* 查询
* @param sql sql语句,完整的语句,查询一般比较安全
* @return
*/
public ResultSet query(String sql) {
try {
this.st = this.conn.createStatement();
this.rs1 = this.st.executeQuery(sql);
return rs1;
} catch (SQLException e) {
e.printStackTrace();
}
return null;
}
/**
* 更新
* @param sql // 预编译sql语句
* @param args // 参数数组
*/
public void update(String sql, String [] args) {
try {
this.ps = this.conn.prepareStatement(sql);
for (int i = 0 ; i < args.length ; i++) {
this.ps.setString(i+1, args[i]);
}
this.ps.executeUpdate();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
this.close();
}
}
/**
* 删除
* @param sql
* @return
*/
public int delete(String sql){
try {
this.st = this.conn.createStatement();
int num = this.st.executeUpdate(sql);
return num;
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
this.close();
}
return 0;
}
/**
* 释放资源
*/
public void close () {
try {
if(rs1!=null) {
rs1.close();
}
if(st!=null) {
st.close();
}
if(ps!=null) {
ps.close();
}
if(conn!=null) {
conn.close();
}
} catch (SQLException e) {
// TODO: handle exception
e.printStackTrace();
}
}
}
Проверьте следующее:
package com.meils.jdbc.db;
import java.sql.ResultSet;
import java.sql.SQLException;
public class Test {
public static void main(String[] args) {
// TODO Auto-generated method stub
// Conn();
delete();
}
// 测试连接
public static void Conn() {
MysqlDB m = new MysqlDB();
}
// 测试查询
public static void queryTest() {
MysqlDB m = new MysqlDB();
String sql = "select * from student";
ResultSet result = m.query(sql);
System.out.println(result);
try {
while (result.next()) {
System.out.println(result.getString("name"));
}
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
m.close();
}
}
// 更新
public static void update() {
MysqlDB m = new MysqlDB();
String sql = "update student set name = ? where id = ?";
String [] args = {"梅子111", "7"};
m.update(sql, args);
}
// 删除
public static void delete() {
MysqlDB m = new MysqlDB();
String sql = "delete from student where id = 8";
System.out.println(m.delete(sql));
}
}
7. Вызов хранимой процедуры
Во-первых, давайте ознакомиться с сохраненными процедурами
// 新建存储过程
DELIMITER //
create PROCEDURE getStudent1(in n varchar(20))
BEGIN
select * from student where name = n;
END //
DELIMITER ;
// 执行
call getStudent1('张锦杰');
Протестировать: (очень стыдно, кажется, что результата нет, и об ошибке не сообщается. Не знаю почему~~)
package com.meils.jdbc.dao.test;
import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Types;
import com.meils.jdbc.domain.Student;
import com.meils.jdbc.utils.JdbcUtil;
public class ProductTest {
public static void main(String[] args) {
CallableStatement cstmt = null;
try {
//1.连接
Connection conn = JdbcUtil.getConnection();
//2.
CallableStatement cs = conn.prepareCall("{ call getStu(?)}");
//3.设置参数
cs.setString(1, "张锦杰");
//4.执行
ResultSet rs = cs.executeQuery();
if(rs.next()) {
Student stu = new Student();
stu.setId(rs.getInt("id"));
stu.setName(rs.getString("name"));
stu.setAge(rs.getInt("age"));
System.out.println(stu);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
Хранимая процедура с параметрами и выводом
// 带有参数和输出的存储过程
DELIMITER //
CREATE PROCEDURE getName ( IN i INT, OUT n VARCHAR ( 50 ) ) BEGIN
SELECT NAME INTO
n
FROM
student
WHERE
id = i;
END // DELIMITER;
call getName(1, @name);
select @name;
есть тест:
package com.meils.jdbc.dao.test;
import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Types;
import com.meils.jdbc.domain.Student;
import com.meils.jdbc.utils.JdbcUtil;
public class ProductTest {
public static void main(String[] args) {
CallableStatement cstmt = null;
try {
//1.创建连接
Connection conn = JdbcUtil.getConnection();
//2.创建预编译语句
CallableStatement cs = conn.prepareCall("{ call getName(?,?)}");
//3.设置参数
cs.setInt(1, 1);
//4.设置输出参数
cs.registerOutParameter(2, Types.VARCHAR);
//5.执行
cs.execute();
//6.获取到输出的参数
String name = cs.getString(2);
System.out.println(name); // 张锦杰
} catch (Exception e) {
e.printStackTrace();
}
}
}
8. Вещи
Пример:Во-первых, закройте транзакцию с автоматической фиксацией перед уменьшением денег.В течение этого периода может быть выполнено несколько операций.В это время фиксация транзакции должна выполняться вручную, и вам нужно использоватьconn.commit();
.如果在中间发生了异常,那么就进行回滚,释放资源。
9. Пакетная обработка
Обычно, если мы хотим выполнить несколько операторов SQL одновременно, мы выполняем один, а затем выполняем следующий.Когда мы используем пакетную обработку, мы можем выполнять несколько операторов одновременно, и событие оплаты вызовов будет значительно сокращено. .
10. Сохраните файл в базе данных
Обычно мы этого не делаем, потому что место в базе данных очень дорого, файл большой, занимаемое место тоже большое, а стоимость высокая.Если нам нужно сохранить файл, то мы должны выбрать блоб тип, который доступен в двоичной форме и может хранить видео, изображения и другую мультимедийную информацию.
首先需要设置数据库中的字段类型为blob。
Сохраните файл в базе данных:
Извлеките файлы из базы данных:
11. Получите автоматически сгенерированный идентификатор первичного ключа
Анализ спроса:
Мы можем столкнуться с такой ситуацией.Сначала регистрируем информацию,заполняем логин и пароль и регистрация прошла успешно.В это время автоматически добавляется id в базу данных,а потом давайте улучшать свою информацию.Это Нам нужен идентификатор, который мы только что создали, так как же нам вернуть идентификатор для нашего следующего использования?
Есть два способа получить его:
1:
2: