[toc]
索引
MySQL官方对索引的定义为:索引(index)是帮助MySQL高效获取数据的的数据结构,提取句子主干,就可以得到作用的本质,索引是数据结构。
索引的分类
- 主键索引:PRIMARY KEY唯一的标识,主键不可重复,只能由一个列作为索引
- 避免重复的列出现,唯一索引可以重复,多个列都可以标识为唯一索引
- 默认的,index,key关键字设置
- 在特定的数据库引擎下才有
基础语法
--索引的使用--在创建表的时候给字段增加索引 或创建完表后增加USE schoolSHOW INDEX FROM student1--增加索引ALTER TABLE `student1` ADD FULLTEXT INDEX `studentname`(`studentname`)--EXPLAIN 分析sql执行的状况EXPLAIN SELECT * FROM `student1` --非全文索引EXPLAIN SELECT * FROM student1 WHERE MATCH(studentname) AGAINST(\'韩\')
测试索引
--测试索引CREATE TABLE `app_user`(`id` INT(4) UNSIGNED NOT NULL AUTO_INCREMENT,`name` VARCHAR(20) DEFAULT\'\' COMMENT\'用户姓名\',`email` VARCHAR(20) NOT NULL COMMENT\'用户邮箱\',`phone` VARCHAR(20) DEFAULT\'\' COMMENT\'用户电话\',`gender` TINYINT(4) UNSIGNED DEFAULT\'0\' COMMENT\'性别(1是男,2是女)\',`password` VARCHAR(50) NOT NULL COMMENT \'密码\',`age` INT(3) DEFAULT\'0\' COMMENT\'年龄\',`create_time` DATETIME DEFAULT CURRENT_TIMESTAMP,`update_name` TIMESTAMP NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,PRIMARY KEY(`id`))ENGINE INNODB DEFAULT CHARSET=utf8mb4 COMMENT\'app用户表\'--插入100万条数据--写函数之前必须写 标志DELIMITER $$CREATE FUNCTION mock_dat() #创建一个函数RETURNS INTBEGINDECLARE num INT DEFAULT 1000000;DECLARE i INT DEFAULT 0;WHILE i<num DOINSERT INTO `app_user`(name,email,phone,gender,password,age)VALUES(CONCAT(\'用户\',i),\'813794474@qq.com\',CONCAT(\'18\',FLOOR(RAND()*((999999999-1000000000)+1000000000))),FLOOR((RAND()*2)+1),UUID(),FLOOR(RAND()*100));SET i=i+1;END WHILE;RETURN i;END;--SELECT mock_dat();SELECT * FROM app_user WHERE name = \'用户9999\';EXPLAIN SELECT * FROM app_user WHERE name = \'用户9999\';EXPLAIN SELECT * FROM app_user WHERE name = \'用户1\';--创建索引 id_表名_字段名 on 表(字段)CREATE INDEX id_app_user_name ON app_user(`name`);SELECT * FROM app_user WHERE name = \'用户9999\';EXPLAIN SELECT * FROM app_user WHERE name = \'用户9999\';
索引在小数据的时候用处不大,在大数据的时候,区别十分明显。
索引原则
- 索引不是越多越好
- 不要对经常变动的数据加索引
- 小数据量的表不需要加索引
- 索引一般加在常用来查询的字段上
索引的数据结构
Hash 类型的索引
Btree:innodb默认的数据结构
权限管理和备份
点击用户进去可以选择新增用户,在服务器权限中可以给用户设置不同的权限。
也可以使用SQL赋予每个用户权限
--创建用户CREATE USER zhou IDENTIFIED BY \'123456\'--修改当前用户密码SET PASSWORD = PASSWORD(\'111111\')--修改指定用户密码SET PASSWORD FOR zhou = password(\'111111\')--重命名RENAME USER zhou TO zzzz--用户授权 授予全部的权限--ALL PRIVILEGES除了给别人授权都可以GRANT ALL PRIVILEGES ON *.* TO zzzz--查看指定用户权限SHOW GRANTS FOR zzzz--查看管理员权限SHOW GRANTS FOR root@localhost--root用户权限 GRANT ALL PRIVILEGES ON *.* TO \'root\'@\'localhost\' WITH GRANT OPTION--撤销权限REVOKE ALL PRIVILEGES *.* FROM zzzz--删除用户DROP zzzz
备份
为什么备份:
- 保证重要的数据不丢失
- 数据转移
MySQL数据库备份的方式
-
直接拷贝物理文件
-
在可视化工具中手动导出数据库
在想要导出的表或者库中,右键选择转储sql文件
使用命令行导出 mysqldump 命令行使用
--mysqldump -h主机 -u用户名 -p密码 数据库 表名 >物理磁盘位置/文件名mysqldump -hlocalhost -uroot -p123456 school student1 > D:/a.sql--mysqldump -h主机 -u用户名 -p密码 数据库 表名1 表名2 >物理磁盘位置/文件名mysqldump -hlocalhost -uroot -p123456 school student1 subject > D:/b.sql--mysqldump -h主机 -u用户名 -p密码 数据库 >物理磁盘位置/文件名mysqldump -hlocalhost -uroot -p123456 school > D:/c.sql--导入表--登录mysql -uroot -p123456use school;sourse d/a.sql或mysql -u用户名 -p密码 库名 表名<文件路径
规范数据库设计
当数据库比较复杂的时候,需要按规范设计。
糟糕的数据库设计:
- 数据冗余,浪费空间
- 数据插入和删除都麻烦【阿里巴巴开发手册 屏蔽使用外键】
- 系统的性能差
良好的数据库设计:
- 节省内存空间
- 保证数据库的完整性
- 性能好,便于开发
软件开发中关于数据库的设计
- 分析需求:分析业务和需要处理的数据库的需求
- 概要设计:设计关系图E-R图
设计数据库的步骤:(个人博客)
- 收集信息,分析需求用户表(用户登录注册,个人信息,写博客,创建分类)
- 分类表(文章分类,博客作者)
- 文章表(文章信息)
- 友链表(友链信息)
- 评论表 (评论信息)
- 自定义表(可选) (存储其他信息)
- 写博客:user–>blog
三大范式
第一范式(1NF):原子性,要求数据库表的每一列都是不可分割的原子数据项。
第二范式(2NF):满足第一范式,非码属性必须完全依赖于候选码,确保数据库表中的每一列都和主键相关,而不能只与主键的某一部分相关。即每张表只描述一件事情。
第三范式(3NF):满足第一第二范式,任何非主属性不依赖于其它非主属性(即消除传递依赖),第三范式需要确保数据表中每一列数据都与主键直接相关,而不能间接相关。
规范性和性能问题:(关联查询的表不得超过三张表 阿里规约)
- 考虑商业化需求和目标(成本,用户体验),数据库的性能更加重要
- 在规范性能需求的时候,需要适当考虑一下规范性
- 在有些情况下,故意给表增加一些冗余字段(多表查询变为单表查询),提高效率
- 故意增加一些计算列(从大数据量降为小数据量的一些查询)
JDBC
数据库驱动:应用程序和数据库之间需要有驱动来进行连接。
SUN公司为了简化开发人员的(对数据库的统一)操作,提供了一个(Java操作数据库)规范,俗称JDBC。
这些规范的具体实现由数据库厂商去做。
对于开发人员来说只需掌握JDBC接口的操作即可。
java.sql javac.sql
JDBC程序
创建lib目录,在lib下放入mysql-connector-java-5.1.47.jar,右击lib,add as library。
- 加载驱动
- 连接数据库 DriverManager
- 获得执行sql的对象 statement
- 获得返回的结果值
- 释放连接
package com.zr.lesson01;import java.sql.*;public class JdbcDemo01 {public static void main(String[] args) throws ClassNotFoundException, SQLException {//加载驱动Class.forName("com.mysql.jdbc.Driver");//用户信息和UrlString url = "jdbc:mysql://localhost:3306/jdbcStudy?useUnicode=true&characterEncoding=utf8&useSSL=false";String username = "root";String password = "123456";//连接成功 数据库对象 DriverManager驱动管理Connection connection = DriverManager.getConnection(url, username, password);//执行sql的对象Statement statement = connection.createStatement();//执行sqlString sql = "select * from users";ResultSet resultSet = statement.executeQuery(sql); //返回的结果集while (resultSet.next()){System.out.println("id="+resultSet.getObject("id"));System.out.println("name="+resultSet.getObject("name"));System.out.println("pwd="+resultSet.getObject("password"));System.out.println("email="+resultSet.getObject("email"));System.out.println("birthday="+resultSet.getObject("birthday"));System.out.println("======================================");}//释放连接 耗资源 用完就关掉resultSet.close();statement.close();connection.close();}}//MySQL默认端口号3306//Oracle ---1521//jdbc:oracle:thin:@localhost:1521:sid
connection.commit(); //事务提交connection.rollback(); //事务回滚connection.setAutoCommit(true); //开启事务提交statement.executeQuery(); //查询操作返回 resultsetstatement.executeUpdate(); //更新,插入,删除都用这个,返回一个受影响的行数statement.execute(); //执行任何sqlresultset 查询的结果集,封装了所有的查询结果集resultSet.getObject();//在不知道列类型的情况下使用//知道列的指定类型resultSet.getString();resultSet.getInt();resultSet.getDate();resultSet.beforeFirst();//移动到最前面resultSet.afterLast();//移动到最后面resultSet.next();//移动到下一个resultSet.previous();//移动到前一个resultSet.absolute(row);//移动到指定行
Statement对象
jdbc中的statement对象用于向数据库发送sql语句,想完成对数据库的增删改查只需发送相应的sql语句即可。
executeUpdate执行完后,返回一个整数(即sql语句导致几行数据发生了变化)。
executeQuery执行完后,返回代表查询结果的resultset对象。
CRUD操作:create,使用Statement(sql)方法完成对数据库的添加操作,示例如下:
Statement st = connection.createStatement;String sql = "insert into user(...) values(...) "int num = st.executeUpdate(sql);if(num>0){System.out.println("插入成功!")}
CRUD操作:delete,使用Statement(sql)方法完成对数据库的删除操作,示例如下:
Statement st = connection.createStatement;String sql = "delete from user wherte id=1"int num = st.executeUpdate(sql);if(num>0){System.out.println("删除成功!")}
CRUD操作:update,使用Statement(sql)方法完成对数据库的修改操作,示例如下:
statement st = connection.Statement;String sql = "update user set name=`` where id=1"int num = st.executeUpdate;if(num>0){System.out.println("修改成功!");}
CRUD操作:read,使用Statement(sql)方法完成对数据库的查询操作,示例如下:
Statement st = connection.createStatement;String sql = "select * from user "Resultset rs = st.executeQuery(sql);if(rs.next()){//根据获取的数据类型,分别调用rs的相应方法映射到Java对象中}
工具类实现
先创建一个jdbcStudy数据库,再创建一个users用户表,表中的字段为id,name,password,emain,birthday
配置MySQL数据库文件,创建工具类
配置文件
driver=com.mysql.jdbc.Driverurl=jdbc:mysql://localhost:3306/jdbcStudy?useunicode=true&characterEncoding=utf8&useSSL=falseusername=rootpassword=123456
工具类
package com.zr.lesson02.utils;//工具类import java.io.IOException;import java.io.InputStream;import java.sql.*;import java.util.Properties;public class JdbcUtils {private static String driver = null;private static String url = null;private static String username = null;private static String password = null;static {try {//读取资源InputStream in = JdbcUtils.class.getClassLoader().getResourceAsStream("db.properties");Properties properties = new Properties();properties.load(in);driver = properties.getProperty("driver");url = properties.getProperty("url");username = properties.getProperty("username");password = properties.getProperty("password");//驱动只用加载一次Class.forName(driver);} catch (Exception e) {e.printStackTrace();}}//获取连接public static Connection getConnection() throws SQLException {return DriverManager.getConnection(url,username,password);}//释放连接public static void release(Connection con, Statement st, ResultSet rs) throws SQLException {if (rs!=null){rs.close();}if (st!=null){st.close();}if (con!=null){con.commit();}}}
增加数据
package com.zr.lesson02.utils;import java.sql.Connection;import java.sql.ResultSet;import java.sql.SQLException;import java.sql.Statement;//插入数据public class TestInsert {public static void main(String[] args) throws Exception {Connection con = null;Statement st = null;ResultSet rs = null;try {con = JdbcUtils.getConnection(); //获取数据库连接st = con.createStatement();//创建执行sql的对象String sql = "insert into users values(5,\'赵云\',\'111111\',\'111@qq.com\',\'2020-01-01\')";int i = st.executeUpdate(sql);//执行sqlif (i>0){System.out.println("插入成功!");}} catch (SQLException throwables) {throwables.printStackTrace();}finally {JdbcUtils.release(con,st,rs);}}}
删除数据
package com.zr.lesson02.utils;import java.sql.Connection;import java.sql.ResultSet;import java.sql.SQLException;import java.sql.Statement;//删除数据public class TestDelete {public static void main(String[] args) throws SQLException {Connection con = null;Statement st = null;ResultSet rs = null;try {con = JdbcUtils.getConnection();//获取数据库连接st = con.createStatement();//创建执行sql的对象String sql = "delete from users where id=5";int i = st.executeUpdate(sql);if (i>0){System.out.println("删除创建!");}} catch (SQLException throwables) {throwables.printStackTrace();}finally {JdbcUtils.release(con,st,rs);}}}
修改数据
package com.zr.lesson02.utils;import java.sql.Connection;import java.sql.ResultSet;import java.sql.SQLException;import java.sql.Statement;//修改数据public class TestUpdate {public static void main(String[] args) throws SQLException {Connection con = null;Statement st = null;ResultSet rs = null;try {con = JdbcUtils.getConnection();//获取数据库连接st = con.createStatement();//创建执行sql的对象String sql = "update users set name=\'韩信\' where id=4";int i = st.executeUpdate(sql);if (i>0){System.out.println("更新成功!");}} catch (SQLException throwables) {throwables.printStackTrace();}finally {JdbcUtils.release(con,st,rs);}}}
添加数据
package com.zr.lesson02.utils;import java.sql.Connection;import java.sql.ResultSet;import java.sql.SQLException;import java.sql.Statement;//查询数据public class TestSelect {public static void main(String[] args) throws SQLException {Connection con = null;Statement st = null;ResultSet rs = null;try {con = JdbcUtils.getConnection();//获取数据库连接st = con.createStatement();//创建执行sql的对象String sql = "select * from users";rs = st.executeQuery(sql);//if只能查出一条数据 这里查询所有用户信息使用whilewhile (rs.next()){System.out.println("id="+rs.getInt("id"));System.out.println("name="+rs.getString("name"));System.out.println("password="+rs.getString("password"));System.out.println("email="+rs.getString("email"));System.out.println("birthday="+rs.getDate("birthday"));System.out.println("==========================");}System.out.println("查询成功!");} catch (SQLException throwables) {throwables.printStackTrace();}finally {JdbcUtils.release(con,st,rs);}}}
sql注入
sql存在漏洞,会被攻击导致数据泄露,sql会被拼接。
package com.zr.lesson02.utils;import java.sql.Connection;import java.sql.ResultSet;import java.sql.SQLException;import java.sql.Statement;//sql注入public class SqlInjection {public static void main(String[] args) throws SQLException {//正常登录 数据库中有的用户和密码//login("韩信","111111");//sql注入 会输出所有密码为123456的人的信息login("\'or\'1=1","123456");//sql注入 会查询所有信息//login("\'or\'1=1","\'or=\'1=1");}//登录业务public static void login(String username,String password) throws SQLException {Connection con = null;Statement st = null;ResultSet rs = null;try {con = JdbcUtils.getConnection();//获取数据库连接st = con.createStatement();//创建执行sql的对象//select * from users where name=\'\'or\'1=1\' and password=\'123456\'//select * from users where name=\'\'or\'1=1\' and password=\'\'or\'1=1\'String sql = "select * from users where name=\'"+username+"\' and password=\'"+password+"\'";rs = st.executeQuery(sql);//if只能查出一条数据 这里查询所有用户信息使用whilewhile (rs.next()){System.out.println("id="+rs.getInt("id"));System.out.println("name="+rs.getString("name"));System.out.println("password="+rs.getString("password"));System.out.println("email="+rs.getString("email"));System.out.println("birthday="+rs.getDate("birthday"));System.out.println("==========================");}} catch (SQLException throwables) {throwables.printStackTrace();}finally {JdbcUtils.release(con,st,rs);}}}
PreparedStatement对象
PreparedStatement可以防止sql注入,而且效率更高。实例如下:
增加数据:
package com.zr.lesson03;import com.zr.lesson02.JdbcUtils;import java.util.Date;import java.sql.*;//PreparedStatement 插入public class TestInsert {public static void main(String[] args) throws SQLException {Connection con = null;PreparedStatement ps = null;ResultSet rs = null;try {con = JdbcUtils.getConnection();//区别String sql = "insert into users values(?,?,?,?,?)";//使用?占位符 代替参数ps = con.prepareStatement(sql);//预编译 先写sql 然后不执行//手动给参数赋值ps.setInt(1,5);ps.setString(2,"李白");ps.setString(3,"123333");ps.setString(4,"813794474@qq.com");//sql.Date 数据库 java.sql.date()//util.Date Java new date().gettime() 获得时间戳ps.setDate(5,new java.sql.Date(new Date().getTime()));//执行int i = ps.executeUpdate();if (i>0){System.out.println("插入成功!");}} catch (SQLException throwables) {throwables.printStackTrace();}finally {JdbcUtils.release(con,ps,rs);}}}
删除数据:
package com.zr.lesson03;import com.zr.lesson02.JdbcUtils;import java.sql.Connection;import java.sql.PreparedStatement;import java.sql.ResultSet;import java.sql.SQLException;import java.util.Date;//PreparedStatement 删除public class TestDelete {public static void main(String[] args) throws SQLException {Connection con = null;PreparedStatement ps = null;ResultSet rs = null;try {con = JdbcUtils.getConnection();//区别String sql = "delete from users where id=?";//使用?占位符 代替参数ps = con.prepareStatement(sql);//预编译 先写sql 然后不执行//手动给参数赋值ps.setInt(1,5);//执行int i = ps.executeUpdate();if (i>0){System.out.println("删除成功!");}} catch (SQLException throwables) {throwables.printStackTrace();}finally {JdbcUtils.release(con,ps,rs);}}}
修改数据:
package com.zr.lesson03;import com.zr.lesson02.JdbcUtils;import java.sql.Connection;import java.sql.PreparedStatement;import java.sql.ResultSet;import java.sql.SQLException;//PreparedStatement 修改public class TestUpdate {public static void main(String[] args) throws SQLException {Connection con = null;PreparedStatement ps = null;ResultSet rs = null;try {con = JdbcUtils.getConnection();//区别String sql = "update users set name = ? where id = ?;";//使用?占位符 代替参数ps = con.prepareStatement(sql);//预编译 先写sql 然后不执行//手动给参数赋值ps.setString(1,"关羽");ps.setInt(2,3);//执行int i = ps.executeUpdate();if (i>0){System.out.println("修改成功!");}} catch (SQLException throwables) {throwables.printStackTrace();}finally {JdbcUtils.release(con,ps,rs);}}}
查询数据:
package com.zr.lesson03;import com.zr.lesson02.JdbcUtils;import java.sql.Connection;import java.sql.PreparedStatement;import java.sql.ResultSet;import java.sql.SQLException;//查询public class TestSelect {public static void main(String[] args) throws SQLException {Connection con = null;PreparedStatement ps = null;ResultSet rs = null;try {con = JdbcUtils.getConnection();String sql = "select * from users where id=?";ps = con.prepareStatement(sql);ps.setInt(1,3);rs = ps.executeQuery();if (rs.next()){System.out.println("name="+rs.getString("name"));System.out.println("password="+rs.getString("password"));}} catch (SQLException throwables) {throwables.printStackTrace();}finally {JdbcUtils.release(con,ps,rs);}}}
事务
要么都成功,要么都失败。
ACID原则:原子性(要么都成功,要么都失败),一致性(保持最终结果的一致性),持久性(一旦提交不可逆,持久到数据库),隔离性(多个进程互不干扰)。
隔离性的问题:
- 脏读:一个事务读取了另一个没有提交的事务
- 虚读(幻读):在一个事务内读取到了别人插入的数据,导致前后读出来的数据不一致
- 不可重复读:在同一个事务内,重复读取了表中的数据,表数据发生了改变
package com.zr.lesson04;import com.zr.lesson02.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) throws SQLException {Connection con = null;PreparedStatement st = null;ResultSet rs = null;try {con = JdbcUtils.getConnection();//关闭数据库的自动提交功能,自动开启事务con.setAutoCommit(false);//执行业务String sql1 ="update account set money = money-100 where name = \'libai\'";st = con.prepareStatement(sql1);st.executeUpdate();String sql2 ="update account set money = money+100 where name = \'hanxin\'";st = con.prepareStatement(sql2);st.executeUpdate();//业务完毕 提交事务con.commit();System.out.println("成功!");} catch (SQLException throwables) {try {con.rollback(); //失败就回滚事务} catch (SQLException e) {e.printStackTrace();}throwables.printStackTrace();}finally {JdbcUtils.release(con,st,rs);}}}
模拟转账失败
package com.zr.lesson04;import com.zr.lesson02.JdbcUtils;import java.sql.Connection;import java.sql.PreparedStatement;import java.sql.ResultSet;import java.sql.SQLException;//模拟转账失败public class TestTransaction02 {public static void main(String[] args) throws SQLException {Connection con = null;PreparedStatement st = null;ResultSet rs = null;try {con = JdbcUtils.getConnection();//关闭数据库的自动提交功能,自动开启事务con.setAutoCommit(false);//执行业务String sql1 ="update account set money = money-100 where name = \'libai\'";st = con.prepareStatement(sql1);st.executeUpdate();int x=1/0;//报错String sql2 ="update account set money = money+100 where name = \'hanxin\'";st = con.prepareStatement(sql2);st.executeUpdate();//业务执行完毕 提交事务con.commit();System.out.println("成功!");} catch (Exception e) {//默认会自动回滚 也可以显式定义/* try {con.rollback(); //失败就回滚事务} catch (SQLException e2) {e2.printStackTrace();}*/e.printStackTrace();}finally {JdbcUtils.release(con,st,rs);}}}
数据库连接池
数据库连接—执行完毕—释放 连接释放是十分浪费系统资源的。
池化技术:准备一些预先的资源,过来连接已经准备好的。
编写连接池,实现一个接口DataSource。
开源数据源实现:
- DBCP
- C3P0
- Durid(阿里巴巴)
DBCP
使用这些数据库连接池之后,我们在项目开发中就不需要编写数据库连接的代码了。
DBCP:lib下导入 commens-dbcp-1.4.jar和commens-pool-1.6.jar
创建dbconfig.properties文件
#连接设置driverClassname=com.mysql.jdbc.Driverurl=jdbc:mysql://localhost:3306/jdbcStudy?useunicode=true&characterEncoding=utf8&useSSL=falseusername=rootpassword=123456#初始化连接initialSize=10#最大连接数量maxActive=50#最大空闲连接maxIdle=20#超时等待时间 毫秒maxWait=60000connectionProperties=useUnicode=true;characterEncoding=utf8defaultAutoCommit=truedefaultReadOnly=defaultTransactionIsolation=READ_UNCOMMITTED
创建DBCP工具类
package com.zr.lesson05;import org.apache.commons.dbcp.BasicDataSource;import org.apache.commons.dbcp.BasicDataSourceFactory;import javax.sql.DataSource;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 JdbcUtils_DBCP {private static DataSource dataSource = null;static{try{InputStream in = JdbcUtils_DBCP.class.getClassLoader().getResourceAsStream("dbconfig.properties");Properties properties = new Properties();properties.load(in);//创建数据源 工厂模式dataSource = BasicDataSourceFactory.createDataSource(properties);}catch (Exception e){e.printStackTrace();}}public static Connection getConnection() throws SQLException {return dataSource.getConnection(); //从数据源中获取连接}public static void release(Connection con, Statement st, ResultSet rs){if (con!=null){try {con.close();} catch (SQLException throwables) {throwables.printStackTrace();}}if (st!=null){try {con.close();} catch (SQLException throwables) {throwables.printStackTrace();}}if (rs!=null){try {con.close();} catch (SQLException throwables) {throwables.printStackTrace();}}}}
测试插入数据
package com.zr.lesson05;import com.zr.lesson02.JdbcUtils;import java.sql.Connection;import java.sql.PreparedStatement;import java.sql.ResultSet;import java.sql.SQLException;import java.util.Date;public class TestDBCP {public static void main(String[] args) throws SQLException {Connection con = null;PreparedStatement ps = null;ResultSet rs = null;try {con = JdbcUtils_DBCP.getConnection();//区别String sql = "insert into users values(?,?,?,?,?)";//使用?占位符 代替参数ps = con.prepareStatement(sql);//预编译 先写sql 然后不执行//手动给参数赋值ps.setInt(1, 5);ps.setString(2, "李白");ps.setString(3, "123333");ps.setString(4, "813794474@qq.com");//sql.Date 数据库 java.sql.date()//util.Date Java new date().gettime() 获得时间戳ps.setDate(5, new java.sql.Date(new Date().getTime()));//执行int i = ps.executeUpdate();if (i > 0) {System.out.println("插入成功!");}} catch (SQLException throwables) {throwables.printStackTrace();} finally {JdbcUtils_DBCP.release(con, ps, rs);}}}
C3P0
C3P0:lib下导入c3p0-0.9.5.5.jar和mchange-commens-java-0.2.19.jar
先创建c3p0-config.xml文件,再创建JdbcUtils_C3P0工具类
<?xml version="1.0" encoding="UTF-8"?><c3p0-config><!-- 默认配置,如果没有指定则使用这个配置 --><default-config><property name="driverClass">com.mysql.jdbc.Driver</property><property name="jdbcUrl">jdbc:mysql://localhost:3306/jdbcStudy</property><property name="user">root</property><property name="password">123456</property><property name="acquirIncrement">5</property>><property name="initialPoolSize">10</property><property name="maxPoolSize">20</property><property name="minPoolSize">5</property></default-config><!-- 命名的配置,可以通过方法调用实现 --><named-config name="Mysql"><property name="driverClass">com.mysql.jdbc.Driver</property><property name="jdbcUrl">jdbc:mysql://localhost:3306/jdbcStudy</property><property name="user">root</property><property name="password">123456</property><!-- 如果池中数据连接不够时一次增长多少个 --><property name="acquireIncrement">5</property><!-- 初始化数据库连接池时连接的数量 --><property name="initialPoolSize">10</property><!-- 数据库连接池中的最大的数据库连接数 --><property name="maxPoolSize">25</property><!-- 数据库连接池中的最小的数据库连接数 --><property name="minPoolSize">5</property></named-config></c3p0-config>
创建C3P0工具类
package com.zr.lesson05;import com.mchange.v2.c3p0.ComboPooledDataSource;import org.apache.commons.dbcp.BasicDataSourceFactory;import javax.sql.DataSource;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 JdbcUtils_C3P0 {private static ComboPooledDataSource dataSource = null;static{try{/*//代码配置dataSource = new ComboPooledDataSource();dataSource.setDriverClass();dataSource.setUser();dataSource.setPassword();dataSource.setJdbcUrl();dataSource.setMaxPoolSize();dataSource.setMinPoolSize();*/dataSource = new ComboPooledDataSource("Mysql");//配置文件写法//创建数据源 工厂模式}catch (Exception e){e.printStackTrace();}}public static Connection getConnection() throws SQLException {return dataSource.getConnection(); //从数据源中获取连接}public static void release(Connection con, Statement st, ResultSet rs){if (con!=null){try {con.close();} catch (SQLException throwables) {throwables.printStackTrace();}}if (st!=null){try {con.close();} catch (SQLException throwables) {throwables.printStackTrace();}}if (rs!=null){try {con.close();} catch (SQLException throwables) {throwables.printStackTrace();}}}}
测试插入代码
package com.zr.lesson05;import java.sql.Connection;import java.sql.PreparedStatement;import java.sql.ResultSet;import java.sql.SQLException;import java.util.Date;public class TestC3P0 {public static void main(String[] args) throws SQLException {Connection con = null;PreparedStatement ps = null;ResultSet rs = null;try {con = JdbcUtils_C3P0.getConnection();//区别String sql = "insert into users values(?,?,?,?,?)";//使用?占位符 代替参数ps = con.prepareStatement(sql);//预编译 先写sql 然后不执行//手动给参数赋值ps.setInt(1, 6);ps.setString(2, "李白");ps.setString(3, "123333");ps.setString(4, "813794474@qq.com");//sql.Date 数据库 java.sql.date()//util.Date Java new date().gettime() 获得时间戳ps.setDate(5, new java.sql.Date(new Date().getTime()));//执行int i = ps.executeUpdate();if (i > 0) {System.out.println("插入成功!");}} catch (SQLException throwables) {throwables.printStackTrace();} finally {JdbcUtils_C3P0.release(con, ps, rs);}}}
结论:无论使用什么数据源,本质还是一样的,DataSource不变,方法就不会变。