如果idea连接数据库失败存在时区问题 , 在url路径后面拼接一个参数?serverTimezone=GMT+8
使用
package com.starcpdk; import com.starcpdk.utils.JDBCUtils; import java.sql.Connection; import java.sql.SQLException; import java.sql.Statement; public class InsertTest { public static void main(String[] args) throws SQLException { Connection connection = null; Statement statement = null; try { connection = JDBCUtils.getConnection(); statement = connection.createStatement(); String sql = "insert into user(id , name , password)values(6 , 'zs' , '123456')"; int i = statement.executeUpdate(sql); if (i > 0){ System.out.println("插入成功"); } }catch (Exception e){ e.printStackTrace(); }finally { JDBCUtils.release(connection , statement , null); } } }sql注入 传入不合法的字符串 ,导致sql被拼接 , 导致数据库数据的泄露 , 因此不安全
防止sql注入的方式
package com.starcpdk; import com.starcpdk.utils.JDBCUtils; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; public class PreparedQuery { public static void main(String[] args) { Connection connection = null; PreparedStatement preparedStatement = null; ResultSet resultSet = null; try { connection = JDBCUtils.getConnection(); String sql = "select * from user where id = ?"; preparedStatement = connection.prepareStatement(sql); preparedStatement.setInt(1 , 3); resultSet = preparedStatement.executeQuery(); while (resultSet.next()){ System.out.println(resultSet.getString("name")); } } catch (SQLException e) { e.printStackTrace(); }finally { JDBCUtils.release(connection , preparedStatement , resultSet); } } }事务ACID原则 原子性:要么全部完成 , 要么都不完成 一致性:总数不变 隔离性:多个进程互不干扰 持久性:一单提交 , 不可逆 , 持久化到数据库
隔离性问题: 脏读:一个事务读取了另一个没有提交的事务 不可重复读:在同一个事务内 , 重复读取表中的数据 , 表数据发生了改变 幻读(虚读):在一个事务内 , 读取到了别人插入的数据 , 导致前后读出来的结果不一致
package com.starcpdk; import com.starcpdk.utils.JDBCUtils; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; public class testTransaction { public static void main(String[] args) { Connection connection = null; PreparedStatement statement = null; ResultSet rs = null; try { connection = JDBCUtils.getConnection(); // 关闭数据库的自动提交功能 , 自动开启事务 connection.setAutoCommit(false); // 写sql String sql1 = "update account set money = money-100 where name = 'A'"; statement = connection.prepareStatement(sql1); statement.executeUpdate(); String sql2 = "update account set money = money+100 where name = 'B'"; statement = connection.prepareStatement(sql2); statement.executeUpdate(); // 业务完毕 , 提交事务 connection.commit(); System.out.println("操作成功"); } catch (SQLException e) { try { connection.rollback(); // 如果失败则 , 回滚事务 } catch (SQLException ex) { ex.printStackTrace(); } e.printStackTrace(); }finally { JDBCUtils.release(connection , statement , rs); } } }数据库连接 — 执行完毕 — 释放资源
这个过程是非常浪费时间的
池化技术:预先准备一些资源 , 过来连接预先准备好的
DBCP工具类封装
package com.starcpdk.utils; import org.apache.commons.dbcp.BasicDataSource; import org.apache.commons.dbcp.BasicDataSourceFactory; import javax.sql.DataSource; import java.io.InputStream; import java.sql.*; import java.util.Properties; public class DBCPUtils { private static DataSource dataSource = null; static { try { InputStream is = com.starcpdk.utils.JDBCUtils.class.getClassLoader().getResourceAsStream("dbcpconfig.properties"); Properties properties = new Properties(); properties.load(is); // 创建数据源 工厂模式 -- 创建对象 dataSource = BasicDataSourceFactory.createDataSource(properties); } catch (Exception e) { e.printStackTrace(); } } // 2. 获取连接 public static Connection getConnection() throws SQLException { return dataSource.getConnection(); } // 3.释放连接资源 public static void release(Connection connection, Statement statement, ResultSet resultSet) { if (resultSet != null) { try { resultSet.close(); } catch (SQLException e) { e.printStackTrace(); } } if (statement != null) { try { statement.close(); } catch (SQLException e) { e.printStackTrace(); } } if (connection != null) { try { connection.close(); } catch (SQLException e) { e.printStackTrace(); } } } }dbcpconfig.properties配置文件内容
# 连接设置 driverClassName = com.mysql.jdbc.Driver url = jdbc:mysql://localhost:3306/jdbc?useUnicode=true&characterEncoding=utf8&useSSL=true&?serverTimezone=GMT+8 username = root password = root # 初始化连接 initialSize = 20 #最大连接数 maxActive=50 # 最大空闲连接数 maxIdle=20 # 最小空闲连接数 minIdle=5 # 超时等待时间 , 以毫秒数为单位 , maxWait=60000 #JDBC驱动建立连接时附带的连接属性属性的格式必须为这样:[属性名=property;] #注意:“user” 与 “password” 两个属性会被明确地传递,因此这里不需要包含他们。 connectionProperties=useUnicode=true;characterEncoding=utf8 #指定由连接池所创建的连接的自动提交(auto-commit)状态。 defaultAutoCommit=true #driver default 指定由连接池所创建的连接的事务级别(TransactionIsolation)。 #可用值为下列之一:(详情可见javadoc。)NONE,READ_UNCOMMITTED, READ_COMMITTED, REPEATABLE_READ, SERIALIZABLE defaultTransactionIsolation=READ_UNCOMMITTEDc3p0-config.xml配置文件
<?xml version="1.0" encoding="UTF-8"?> <c3p0-config> <default-config> <!-- 如果要研究某个xml中可以设置哪些属性。找相关类的 属性 或者setXxx()--> <property name="user">root</property> <property name="password">root</property> <property name="driverClass">com.mysql.jdbc.Driver</property> <property name="jdbcUrl">jdbc:mysql://localhost:3306/jdbc?serverTimezone=UTC</property> <property name="checkoutTimeout">30000</property> </default-config> <named-config name="MYSQL"> <property name="user">root</property> <property name="password">root</property> <property name="driverClass">com.mysql.jdbc.Driver</property> <property name="jdbcUrl">jdbc:mysql://localhost:3306/jdbc?serverTimezone=UTC</property> <property name="checkoutTimeout">20000</property> <property name="initialPoolSize">10</property> <property name="maxIdleTime">30</property> <property name="maxPoolSize">100</property> <property name="minPoolSize">10</property> </named-config> </c3p0-config>