import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
/**
* 创建一张学生表
*/
public class Demo4DDL {
public static void main(String[] args) {
//1. 创建连接
Connection conn = null;
Statement statement = null;
try {
conn = DriverManager.getConnection("jdbc:mysql:///db3", "root", "root");
//2. 通过连接对象得到语句对象
statement = conn.createStatement();
//3. 通过语句对象发送 SQL 语句给服务器
//4. 执行 SQL
statement.executeUpdate("create table student (id int PRIMARY key auto_increment, " +
"name varchar(20) not null, gender boolean, birthday date)");
//5. 返回影响行数(DDL 没有返回值)
System.out.println("创建表成功");
} catch (SQLException e) {
e.printStackTrace();
}
//6. 释放资源
finally {
//关闭之前要先判断
if (statement != null) {
try {
statement.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (conn != null) {
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
} 4.6-执行DML需求 向学生表中添加 4 条记录,主键是自动增长 步骤 - 创建连接对象
- 创建 Statement 语句对象
- 执行 SQL 语句:executeUpdate(sql)
- 返回影响的行数
- 释放资源
代码 import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
/**
* 向学生表中添加 4 条记录,主键是自动增长
*/
public class Demo5DML {
public static void main(String[] args) throws SQLException {
// 1) 创建连接对象
Connection connection = DriverManager.getConnection("jdbc:mysql:///day24", "root",
"root");
// 2) 创建 Statement 语句对象
Statement statement = connection.createStatement();
// 3) 执行 SQL 语句:executeUpdate(sql)
int count = 0;
// 4) 返回影响的行数
count += statement.executeUpdate("insert into student values(null, '孙悟空', 1, '1993-03-
24')");
count += statement.executeUpdate("insert into student values(null, '白骨精', 0, '1995-03-
24')");
count += statement.executeUpdate("insert into student values(null, '猪八戒', 1, '1903-03-
24')");
count += statement.executeUpdate("insert into student values(null, '嫦娥', 0, '1993-03-
11')");
System.out.println("插入了" + count + "条记录");
// 5) 释放资源
statement.close();
connection.close();
}
} 4.7-执行DQLResultSet 接口 作用:封装数据库查询的结果集,对结果集进行遍历,取出每一条记录。 接口中的方法: 其他方法 常用的数据类型转换表 java.sql.Date、Time、Timestamp(时间戳),三个共同父类是:java.util.Date 需求 确保数据库中有 3 条以上的记录,查询所有的学员信息 步骤 - 得到连接对象
- 得到语句对象
- 执行 SQL 语句得到结果集 ResultSet 对象
- 循环遍历取出每一条记录
- 输出的控制台上
- 释放资源
代码 import java.sql.*;
/**
* 查询所有的学生信息
*/
public class Demo6DQL {
public static void main(String[] args) throws SQLException {
//1) 得到连接对象
Connection connection =
DriverManager.getConnection("jdbc:mysql://localhost:3306/day24","root","root");
//2) 得到语句对象
Statement statement = connection.createStatement();
//3) 执行 SQL 语句得到结果集 ResultSet 对象
ResultSet rs = statement.executeQuery("select * from student");
//4) 循环遍历取出每一条记录
while(rs.next()) {
int id = rs.getInt("id");
String name = rs.getString("name");
boolean gender = rs.getBoolean("gender");
Date birthday = rs.getDate("birthday");
//5) 输出的控制台上
System.out.println("编号:" + id + ", 姓名:" + name + ", 性别:" + gender + ", 生日:" +
birthday);
}
//6) 释放资源
rs.close();
statement.close();
connection.close();
}
} 结果 ResultSet使用注意事项 - 如果光标在第一行之前,使用 rs.getXX()获取列值,报错:Before start of result set
- 如果光标在最后一行之后,使用 rs.getXX()获取列值,报错:After end of result set
- 使用完毕以后要关闭结果集 ResultSet,再关闭 Statement,再关闭 Connection
第五章:数据库工具类 JdbcUtils如果一个功能经常要用到,我们建议把这个功能做成一个工具类,可以在不同的地方重用。 需求 上面写的代码中出现了很多重复的代码,可以把这些公共代码抽取出来 代码实现 - 可以把几个字符串定义成常量:用户名,密码,URL,驱动类
- 得到数据库的连接:getConnection()
- 关闭所有打开的资源:
import java.sql.*;
/**
* 访问数据库的工具类
*/
public class JdbcUtils {
//可以把几个字符串定义成常量:用户名,密码,URL,驱动类
private static final String USER = "root";
private static final String PWD = "root";
private static final String URL = "jdbc:mysql://localhost:3306/day24";
private static final String DRIVER= "com.mysql.jdbc.Driver";
/**
* 注册驱动
*/
static {
try {
Class.forName(DRIVER);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
/**
* 得到数据库的连接
*/
public static Connection getConnection() throws SQLException {
return DriverManager.getConnection(URL,USER,PWD);
}
/**
* 关闭所有打开的资源
*/
public static void close(Connection conn, Statement stmt) {
if (stmt!=null) {
try {
stmt.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (conn!=null) {
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
/**
* 关闭所有打开的资源
*/
public static void close(Connection conn, Statement stmt, ResultSet rs) {
if (rs!=null) {
try {
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
close(conn, stmt);
}
} 第六章:用户登录案例6.1-需求- 有一张用户表
- 添加几条用户记录
- 使用 Statement 字符串拼接的方式实现用户的登录, 用户在控制台上输入用户名和密码。
create table user (
id int primary key auto_increment,
name varchar(20),
password varchar(20)
)
insert into user values (null,'jack','123'),(null,'rose','456');
-- 登录, SQL 中大小写不敏感
select * from user where name='JACK' and password='123';
-- 登录失败
select * from user where name='JACK' and password='333'; 6.2-步骤- 得到用户从控制台上输入的用户名和密码来查询数据库
写一个登录的方法 - 通过工具类得到连接
- 创建语句对象,使用拼接字符串的方式生成 SQL 语句
- 查询数据库,如果有记录则表示登录成功,否则登录失败
- 释放资源
import com.it.utils.JdbcUtils;
import javax.xml.transform.Result;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Scanner;
public class Demo7Login {
//从控制台上输入的用户名和密码
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.println("请输入用户名:");
String name = sc.nextLine();
System.out.println("请输入密码:");
String password = sc.nextLine();
login(name, password);
}
/**
* 登录的方法
*/
public static void login(String name, String password) {
//a) 通过工具类得到连接
Connection connection = null;
Statement statement = null;
ResultSet rs = null;
try {
connection = JdbcUtils.getConnection();
//b) 创建语句对象,使用拼接字符串的方式生成 SQL 语句
statement = connection.createStatement();
//c) 查询数据库,如果有记录则表示登录成功,否则登录失败
String sql = "select * from user where name='" + name + "' and password='" + password
+ "'";
System.out.println(sql);
rs = statement.executeQuery(sql);
if (rs.next()) {
System.out.println("登录成功,欢迎您:" + name);
} else {
System.out.println("登录失败");
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
//d) 释放资源
JdbcUtils.close(connection, statement, rs);
}
}
} 6.3-SQL 注入问题现象 当我们输入以下密码,我们发现我们账号和密码都不对竟然登录成功了 select * from user where name='newboy' and password='a' or '1'='1'
-- name='newboy' and password='a' 为假
-- '1'='1' 真
-- 相当于
select * from user where true; -- 查询了所有记录 我们让用户输入的密码和 SQL 语句进行字符串拼接。用户输入的内容作为了 SQL 语句语法的一部分,改变了 原有 SQL 真正的意义,以上问题称为 SQL 注入。要解决 SQL 注入就不能让用户输入的密码和我们的 SQL 语句进 行简单的字符串拼接。 第七章:PreparedStatement 接口7.1-继承结构与作用PreparedStatement 是 Statement 接口的子接口,继承于父接口中所有的方法。它是一个预编译的 SQL 语句 7.2-PreparedSatement 的执行原理- 因为有预先编译的功能,提高 SQL 的执行效率。
- 可以有效的防止 SQL 注入的问题,安全性更高。
7.3-PreparedStatement 对象创建 常用方法 作用 - prepareStatement()会先将 SQL 语句发送给数据库预编译。PreparedStatement 会引用着预编译后的结果。 可以多次传入不同的参数给 PreparedStatement 对象并执行。减少 SQL 编译次数,提高效率。
- 安全性更高,没有 SQL 注入的隐患。
- 提高了程序的可读性
7.4-使用 PreparedStatement 的步骤- 编写 SQL 语句,未知内容使用?占位:
import com.it.utils.JdbcUtils;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Scanner;
/**
* 使用 PreparedStatement
*/
public class Demo8Login {
//从控制台上输入的用户名和密码
public static void main(String[] args) throws SQLException {
Scanner sc = new Scanner(System.in);
System.out.println("请输入用户名:");
String name = sc.nextLine();
System.out.println("请输入密码:");
String password = sc.nextLine();
login(name, password);
}
/**
* 登录的方法
* @param name
* @param password
*/
private static void login(String name, String password) throws SQLException {
Connection connection = JdbcUtils.getConnection();
//写成登录 SQL 语句,没有单引号
String sql = "select * from user where name=? and password=?";
//得到语句对象
PreparedStatement ps = connection.prepareStatement(sql);
//设置参数
ps.setString(1, name);
ps.setString(2,password);
ResultSet resultSet = ps.executeQuery();
if (resultSet.next()) {
System.out.println("登录成功:" + name);
}
else {
System.out.println("登录失败");
}
//释放资源,子接口直接给父接口
JdbcUtils.close(connection,ps,resultSet);
}
} 7.5-表与类的关系案例:使用 PreparedStatement 查询一条数据,封装成一个学生 Student 对象 import com.it.entity.Student;
import com.it.utils.JdbcUtils;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
public class Demo9Student {
public static void main(String[] args) throws SQLException {
//创建学生对象
Student student = new Student();
Connection connection = JdbcUtils.getConnection();
PreparedStatement ps = connection.prepareStatement("select * from student where id=?");
//设置参数
ps.setInt(1,2);
ResultSet resultSet = ps.executeQuery();
if (resultSet.next()) {
//封装成一个学生对象
student.setId(resultSet.getInt("id"));
student.setName(resultSet.getString("name"));
student.setGender(resultSet.getBoolean("gender"));
student.setBirthday(resultSet.getDate("birthday"));
}
//释放资源
JdbcUtils.close(connection,ps,resultSet);
//可以数据
System.out.println(student);
}
} 案例:将多条记录封装成集合 List,集合中每个元素是一个 JavaBean 实体类 需求: 查询所有的学生类,封装成 import com.it.entity.Student;
import com.it.utils.JdbcUtils;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
public class Demo10List {
public static void main(String[] args) throws SQLException {
//创建一个集合
List students = new ArrayList();
Connection connection = JdbcUtils.getConnection();
PreparedStatement ps = connection.prepareStatement("select * from student");
//没有参数替换
ResultSet resultSet = ps.executeQuery();
while(resultSet.next()) {
//每次循环是一个学生对象
Student student = new Student();
//封装成一个学生对象
student.setId(resultSet.getInt("id"));
student.setName(resultSet.getString("name"));
student.setGender(resultSet.getBoolean("gender"));
student.setBirthday(resultSet.getDate("birthday"));
//把数据放到集合中
students.add(student);
}
//关闭连接
JdbcUtils.close(connection,ps,resultSet);
//使用数据
for (Student stu: students) {
System.out.println(stu);
}
}
} 7.6-PreparedStatement 执行 DML 操作import com.it.utils.JdbcUtils;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
public class Demo11DML {
public static void main(String[] args) throws SQLException {
//insert();
//update();
delete();
}
//插入记录
private static void insert() throws SQLException {
Connection connection = JdbcUtils.getConnection();
PreparedStatement ps = connection.prepareStatement("insert into student
values(null,?,?,?)");
ps.setString(1,"小白龙");
ps.setBoolean(2, true);
ps.setDate(3,java.sql.Date.valueOf("1999-11-11"));
int row = ps.executeUpdate();
System.out.println("插入了" + row + "条记录");
JdbcUtils.close(connection,ps);
}
//更新记录: 换名字和生日
private static void update() throws SQLException {
Connection connection = JdbcUtils.getConnection();
PreparedStatement ps = connection.prepareStatement("update student set name=?, birthday=?
where id=?");
ps.setString(1,"黑熊怪");
ps.setDate(2,java.sql.Date.valueOf("1999-03-23"));
ps.setInt(3,5);
int row = ps.executeUpdate();
System.out.println("更新" + row + "条记录");
JdbcUtils.close(connection,ps);
}
//删除记录: 删除第 5 条记录
private static void delete() throws SQLException {
Connection connection = JdbcUtils.getConnection();
PreparedStatement ps = connection.prepareStatement("delete from student where id=?");
ps.setInt(1,5);
int row = ps.executeUpdate();
System.out.println("删除了" + row + "条记录");
JdbcUtils.close(connection,ps);
}
} 第八章:JDBC处理事务之前我们是使用 MySQL 的命令来操作事务。接下来我们使用 JDBC 来操作银行转账的事务 8.1-准备数据CREATE TABLE account (
id INT PRIMARY KEY AUTO_INCREMENT,
NAME VARCHAR(10),
balance DOUBLE
);
-- 添加数据
INSERT INTO account (NAME, balance) VALUES ('Jack', 1000), ('Rose', 1000); 8.2-API介绍8.3-开发步骤- 获取连接
- 开启事务
- 获取到 PreparedStatement
- 使用 PreparedStatement 执行两次更新操作
- 正常情况下提交事务
- 出现异常回滚事务
- 最后关闭资源
import com.it.utils.JdbcUtils;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
public class Demo12Transaction {
//没有异常,提交事务,出现异常回滚事务
public static void main(String[] args) {
//1) 注册驱动
Connection connection = null;
PreparedStatement ps = null;
try {
//2) 获取连接
connection = JdbcUtils.getConnection();
//3) 开启事务
connection.setAutoCommit(false);
//4) 获取到 PreparedStatement
//从 jack 扣钱
ps = connection.prepareStatement("update account set balance = balance - ? where
name=?");
ps.setInt(1, 500);
ps.setString(2,"Jack");
ps.executeUpdate();
//出现异常
System.out.println(100 / 0);
//给 rose 加钱
ps = connection.prepareStatement("update account set balance = balance + ? where
name=?");
ps.setInt(1, 500);
ps.setString(2,"Rose");
ps.executeUpdate();
//提交事务
connection.commit();
System.out.println("转账成功");
} catch (Exception e) {
e.printStackTrace();
try {
//事务的回滚
connection.rollback();
} catch (SQLException e1) {
e1.printStackTrace();
}
System.out.println("转账失败");
}
finally {
//7) 关闭资源
JdbcUtils.close(connection,ps);
}
}
} 第九章:数据库连接池9.1-为什么要学习数据库连接池数据库连接是一种关键的、有限的、昂贵的资源,这一点在多用户的网页应用程序中体现得尤为突出。 一个数据库连接对象均对应一个物理数据库连接,每次操作都打开一个物理连接,使用完都关闭连接,这样造成系统的 性能低下。 数据库连接池的解决方案是在应用程序启动时建立足够的数据库连接,并将这些连接组成一个连接池(简单说:在一个“池”里放了好多数据库连接对象),由应用程序动态地对池中的连接进行申请、使用和释放。 对于多于连接池中连接数的并发请求,应该在请求队列中排队等待。并且应用程序可以根据池中连接的使用率,动态增加或减少池中的连接数。 连接池技术尽可能多地重用了消耗内存地资源,大大节省了内存,提高了服务器地服务效率,能够支持更多的客户服务。通过使用连接池,将大大提高程序运行效率,同时,我们可以通过其自身的管理机制来监视数据库连接的数量、使用情况等。 9.2-什么是数据库连接池数据库连接池负责分配、管理和释放数据库连接,它允许应用程序重复使用一个现有的数据库连接,而不是再重新建立一个;释放空闲时间超过最大空闲时间的数据库连接来避免因为没有释放数据库连接而引起的数据库连接遗漏。这项技术能明显提高对数据库操作的性能。 9.3-如何使用数据库连接池Java提供了数据库连接池接口: com.mysql.jdbc.Driverjdbc:mysql://localhost:3306/db2rootroot5103000com.mysql.jdbc.Driverjdbc:mysql://localhost:3306/day25rootroot581000 代码演示 public class Test01 {
public static void main(String[] args) throws SQLException {
// 创建数据库连接池对象
DataSource ds = new ComboPooledDataSource();
// 获取数据库连接对象
Connection con = ds.getConnection();
System.out.println(con);
}
} 9.5-Druid准备资料 下载 链接:https://pan.baidu.com/s/1nWIF... 提取码:f43e 使用步骤 # 数据库驱动
driverClassName=com.mysql.jdbc.Driver
# 数据库连接地址
url=jdbc:mysql://127.0.0.1:3306/db2
# 用户名
username=root
# 密码
password=root
# 初始化连接对象个数
initialSize=5
# 最大个数
maxActive=10
# 超时等待时长
maxWait=3000 代码 public class Test01 {
public static void main(String[] args) throws Exception {
Properties pro = new Properties();
InputStream is = Test01.class.getClassLoader().getResourceAsStream("druid.properties");
pro.load(is);
DataSource ds = DruidDataSourceFactory.createDataSource(pro);
Connection con = ds.getConnection();
System.out.println(con);
}
} 9.6-DruidUtilsDruidUtils package it.leilei.util;
import com.alibaba.druid.pool.DruidDataSourceFactory;
import javax.sql.DataSource;
import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;
public class DruidUtils {
private static DataSource ds;
private static InputStream is;
static {
Properties pro = new Properties();
try {
// 读取配置文件
is = DruidUtils.class.getClassLoader().getResourceAsStream("druid.properties");
pro.load(is);
// 创建数据库连接池对象
ds = DruidDataSourceFactory.createDataSource(pro);
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}finally {
if(is!=null){
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
// 获取Connection对象
public static Connection getConnection() throws SQLException {
return ds.getConnection();
}
// 释放资源
public static void close(Statement sta, Connection con, ResultSet rs) {
if(sta!=null){
try {
sta.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if(con!=null){
try {
con.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if(rs!=null){
try {
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
public static void close(Statement sta, Connection con){
close(sta,con,null);
}
// 获取连接池对象
public static DataSource getDataSource(){
return ds;
}
} 测试:向数据库db2中的表account中添加一条新的数据 package it.leilei.DruidDemo;
import it.leilei.util.DruidUtils;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
public class Test02 {
public static void main(String[] args) {
Connection con = null;
PreparedStatement ps = null;
try {
// 获取数据库连接对象
con = DruidUtils.getConnection();
// 定义SQL
String sql = "INSERT INTO account VALUES(NULL,?,?)";
// 创建执行SQL语句对象
ps = con.prepareStatement(sql);
// 给参数设置值
ps.setString(1,"小龙女");
ps.setDouble(2,8000);
// 执行sql
int count = ps.executeUpdate();
if(count>0){
System.out.println("添加成功");
}else {
System.out.println("添加失败");
}
} catch (SQLException e) {
e.printStackTrace();
}finally {
DruidUtils.close(ps,con);
}
}
} 第十章:Spring JDBC10.1-概述以上数据库连接池确实优化并简化了Java对SQL的操作,但是在针对增删改查操作时相对还是有些繁琐,在实际开发中,我们通常会使用框架中封装好的JDBC来操作数据库,可以更加简化Java对SQL的操作,提高开发效率。 Spring框架对JDBC的简单封装。提供了一个JDBCTemplate对象简化JDBC的开发。 10.2-使用Spring JDBC准备资料 下载 链接:https://pan.baidu.com/s/1JLru... 提取码:73vt 使用步骤 导入jar包(lib目录下所有jar包) - commons-logging-1.2.jar
- spring-beans-5.0.0.RELEASE.jar
- spring-core-5.0.0.RELEASE.jar
- spring-jdbc-5.0.0.RELEASE.jar
- spring-tx-5.0.0.RELEASE.jar
- 创建
package it.leilei.JDBCTemplateDemo;
import it.leilei.domain.Emp;
import it.leilei.util.DruidUtils;
import org.junit.Test;
import org.springframework.dao.DataAccessException;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.ResultSetExtractor;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;
import java.util.Map;
public class Test01 {
// 创建JdbcTemplate对象
private JdbcTemplate jt = new JdbcTemplate(DruidUtils.getDataSource());
/*
添加一条新的数据
*/
@Test
public void test01(){
// 定义SQL
String sql = "INSERT INTO emp(NAME,gender,salary)VALUES(?,?,?)";
// 执行
int i = jt.update(sql,"张三丰","男",90000);
System.out.println(i);
}
/*
更新一条数据
*/
@Test
public void test02(){
String sql = "update emp set salary=? where id=1";
int i = jt.update(sql,10000);
System.out.println(i);
}
/*
删除一条数据
*/
@Test
public void test03(){
String sql = "delete from emp where id=?";
int i = jt.update(sql,8);
System.out.println(i);
}
/*
* 查询一条数据返回map集合
* */
@Test
public void test04(){
String sql = "select * from emp where id=?";
Map map = jt.queryForMap(sql,1);
System.out.println(map);
}
/*
* 查询多条数据返回List集合
* */
@Test
public void test05(){
String sql = "select * from emp where id=? or id=?";
List 终于介绍完啦!小伙伴们,这篇关于《MySQL第04篇:JDBC》的介绍应该让你收获多多了吧!欢迎大家收藏或分享给更多需要学习的朋友吧~golang学习网公众号也会发布数据库相关知识,快来关注吧!
|