JDBC(Java DataBase Connectivity):
概念: java连接数据库的接口,提供了对数据库一系列操作的实现类。
一,连接数据库
1.需要导入导入第三方jar包 mysql-connector-java.jar
2.加载驱动类:Driver
Class.forName(Driver类的全路径);
注: jar包版本为5:Driver类的路径为 com.mysql.jdbc.Driver
jar包版本为8:Driver类的路径为 com.mysql.cj.jdbc.Driver
3.连接数据库
1)连接数据库的要素 Localhost:127.0.0.1
①连接地址(url) 格式:jdbc:mysql://主机名:端口号/数据库名?[配置1]&[配置2]&[...]
②用户名(username) 默认是root
③密码(password)
2)通过三要素获取数据库的连接对象:Connection对象
通过Connection DriverManger.getConnection(url,username,password);获取连接对象
注:连接使用完毕后需要关闭close();
public class MySQLConnection {
public static void main(String[] args) {
//声明数据库连接三要素
String url = "jdbc:mysql://localhost:3306/230101_jdbc?characterEncoding=utf8";
String username = "root";
String password = "1234";
Connection conn = null;
try {
//1.加载数据库驱动
Class.forName("com.mysql.jdbc.Driver");
System.out.println("加载成功");
//2.获取数连接对象
conn = DriverManager.getConnection(url, username, password);
System.out.println("数据库连接成功!");
} catch (Exception e) {
e.printStackTrace();
//3.关闭连接
} finally {
try {
if (conn != null) {
conn.close();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
二、操作数据库
创建执行SQL语言的对象(Statement,PreStatement),将SQL语言发送到MySQL服务器操作数据库 MySQL
步骤:
①获取数据库连接的对象 Connection
②创建Statement对象 通过Connection中的create Statement()方法创建Statement对象
③编写SQL语言,发送到MySQL服务器
1)发送的是DML(增删改)语言:调用 int executeUpdate(sql),发送SQL,返回值就是影响行数
2)发送的是DQL(查询)语句:调用 executeQuery(sql),发送SQL,返回值是存储数据的Resultset
④关闭资源(Connection与Statement)
static String url = "jdbc:mysql://localhost:3306/230101_jdbc?characterEncoding=utf8";
static String username = "root";
static String password = "1234";
//1.往数据库表中插入一条数据
public static void InsertUser() {
String sql = "insert into user values(null,'张三','123456',now()),(null,'张三','123456',now());";
Connection conn = null;
Statement sta = null;
try {
//1.获取数据库连接 DriverManger.getConnection(url,username,password);
conn = DriverManager.getConnection(url, username, password);
//2.创建statement对象
sta = conn.createStatement();
//3.调用executeUpdate发送DML类型的SQL语言
int i = sta.executeUpdate(sql);
System.out.println("插入" + i + "条数据");
} catch (Exception e) {
e.printStackTrace();
//4.关闭连接
} finally {
try {
if (conn != null) {
conn.close();
}
if (sta != null) {
sta.close();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
//2.删除表中数据
public static void DeleteUser() {
String sql = "delete from user where name = '张三';";
Connection conn = null;
Statement sta = null;
try {
conn = DriverManager.getConnection(url, username, password);
sta = conn.createStatement();
int i = sta.executeUpdate(sql);
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (conn != null) {
conn.close();
}
if (sta != null) {
sta.close();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
//3.修改表中数据
public static void UpdateUser() {
String sql = "update user set name = '李四' where name = '张三'";
Connection conn = null;
Statement sta = null;
try {
conn = DriverManager.getConnection(url, username, password);
sta = conn.createStatement();
int i = sta.executeUpdate(sql);
System.out.println(i);
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (conn != null) {
conn.close();
}
if (sta != null) {
sta.close();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
//4.查询表中的数据
public static void SelectUser() throws Exception {
String sql = "select *from user";
//1.连接数据
Connection conn = DriverManager.getConnection(url, username, password);
//2.创建Statement对象
Statement sta = conn.createStatement();
//3.发送DQL类型的sql
ResultSet set = sta.executeQuery(sql);
//4.取出数据
//next() 判断集合中是否存在下一个元素
while (set.next()) {
//取出个字段对应的值 通过get字段类型()
System.out.println("id:" + set.getInt("id") + "\n" +
"name:" + set.getString("name") + "\n" +
"password:" + set.getString("password") + "\n" +
"create_time:" + set.getTimestamp("create_time"))
;
System.out.println("=================================");
}
conn.close();
sta.close();
}
SQL注入:
通过字符串拼接的方式去构造SQL条件判断值时,会造成SQL注入的问题,导致某些功能失效,极其不安全.
解决:使用PreparedStatement对象去发送SQL
PrepareStatement 是statement的子接口
特点:
使用:
(1)通过对连接对象调用PrepareStatement(String sql);创建PreparedStatement对象
(2)给SQL中的占位符?设置对应的值
(3)调用方法发送
//登录功能 (使用PrepareStatement的,防止SQL注入)
public static void login(String name, String pass) throws Exception {
//登录功能执行的SQL
String loginSQL = "select *from user where name = ? and password = ? ";
//1.获取数据库连接
Connection conn = JDBCUtils.getConnection();
//2.创建PrepareStatement对象
PreparedStatement psd = conn.prepareStatement(loginSQL);
//3.给SQL中的占位符'?'设置对应的值
psd.setString(1, name);//表示给第一个?设置name变量值
psd.setString(2, pass);//表示给第二个?设置pass变量值
System.out.println(loginSQL);
//4.发送SQL
ResultSet result = psd.executeQuery();
//判断是否登录成功:如果result.next()为true,则登录成功,反之失败
if (result.next()) {
System.out.println("登录成功");
} else {
System.out.println("登录失败");
}
//5.关闭资源
JDBCUtils.closeAll(conn, psd, result);
}
PrepareStatement与Statement的比较
(1)statement在进行输入插入的时候,都会发送一条SQL语句给数据库,数据库先编译SQL语句,然后执行,返回结果,如果有一万条插入的SQL语句,那么数据库就需要先编译一万次,这样就会导致效率低下:PreparedStatement在进行数据插入的时候,会先发送SQL语句预编译,PreparedStatement就会引用预编译的结果,如果多次插入的内容相同的话,就只需要预编译一次,只是每一次执行SQL语句的时候参数不一样。这样就提高了效率。
(2)PrepareStatement可以有效的防止SQL注入的问题,安全性更高。
连接数据库的工具类:JDBCUtils
(1)将数据库连接三要素(url,name,pass)以及Driver类的全路径编写在配置文件中.properties
(2)在工具类中获取配置文件中的值进而加载驱动,连接数据库
(3)希望在使用JDBCUtils时,Properties自动加载配置文件,并且加载驱动.将次操作编写在静态代码块中
(4)编写获取数据库连接的方法
(5)编写关闭资源的方法
public class JDBCUtils {
//静态代码块,此处代码随着类加载而执行
static Properties pro;
static {
try {
//Properties集合加载配置文件(.properties)内容
pro = new Properties();
//通过Load方法加载文件输入流
pro.load(new FileInputStream("jdbc.properties"));
//此时,Properties集合中以key-value的形式存储了配置文件中的内容
//根据key获取value
Class.forName(pro.getProperty("driver"));
} catch (Exception e) {
e.printStackTrace();
}
}
//获取数据库连接的方法
public static Connection getConnection() {
try {
return DriverManager.getConnection(
pro.getProperty("url"),
pro.getProperty("username"),
pro.getProperty("password"));
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
//关闭资源(connection,prepareStatement,resultSet)的方法
public static void closeAll(Connection conn, PreparedStatement pre, ResultSet set) {
try {
if (conn != null) {
conn.close();
}
if (pre != null) {
pre.close();
}
if (set != null) {
set.close();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
Druid连接池:DruidUtils
数据库连接池:
为了避免重复创建数据库连接,重复关闭导致内存消耗过大,性能开销过大等问题,因此使用数据连接池来降低
创建数据库连接时带来的开销。
原理:池就是一个容器(List,Set,Hashmap)(集合),数据库连接池就是存储了多个连接对象的容器。在系统初始化时,按照指定个 数创建连接对象,并存储到容器中去。当操作数据库时,直接从容器中获取连接对象,操作完后,将数据库连接归还,可以重复使用。系统关闭时,将所有连接进行统一关闭。
druid连接池
(1)导入jar包
(2)编写配置文件
(3)编写Druid获取数据库连接工具类
public class DruidUtils {
//静态代码块,此处代码随着类加载而执行
static Properties pro;
static {
try {
//Properties集合加载配置文件(.properties)内容
pro = new Properties();
//通过Load方法加载文件输入流
pro.load(new FileInputStream("druid.properties"));
//此时,Properties集合中以key-value的形式存储了配置文件中的内容
//根据key获取value
Class.forName(pro.getProperty("driverClassName"));
} catch (Exception e) {
e.printStackTrace();
}
}
//获取数据库连接的方法
public static Connection getConnection() {
try {
//1.创建数据资源DataSource对象
DataSource ds = DruidDataSourceFactory.createDataSource(pro);
//2.获取并返回连接
return ds.getConnection();
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
//关闭资源(connection,prepareStatement,resultSet)的方法
public static void closeAll(Connection conn, PreparedStatement pre, ResultSet set) {
try {
if (conn != null) {
conn.close();
}
if (pre != null) {
pre.close();
}
if (set != null) {
set.close();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}