这里写自定义目录标题
JDBC
以下示例皆以Mysql举例
JDBC的使用:
1.不使用配置文件进行连接
JDBC连接数据库:
Connection con = null;
try {
//进行类加载运行静态代码块
Class.forName("com.mysql.jdbc.Driver");
//获取connection链接,输入数据库链接,用户名,密码
String url ="jdbc:mysql://127.0.0.1:3306/test";
String user = "root";
String password = "1234";
con = DriverManager.getConnection("url","user","password");
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException throwables) {
throwables.printStackTrace();
} finally{
if (con != null) {
try {
//关闭连接
con.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
}
2.使用配置文件进行连接数据库
使用配置文件连接数据库会使程序更加灵活,以后连其他数据库直接修改配置文件就可以了,不需要再修改代码,如果直接将参数写入程序,这样就会把程序写死了,会使程序在后面使用中进行来回的更改,这样明显不符合开闭原则,所以推荐使用配置文件进行数据库的连接。
Connection con = null;
try {
Class.forName("com.mysql.jdbc.Driver");
//使用ResourceBundle读取配置文件,注意配置文件不要写后缀
ResourceBundle bundle = ResourceBundle.getBundle("jdbc");
String url = bundle.getString("url");
String user = bundle.getString("user");
String password= bundle.getString("password");
con = DriverManager.getConnection(url,user,password);
System.out.println(con);
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException throwables) {
throwables.printStackTrace();
}finally {
if (con != null) {
try {
con.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
}
配置文件编写
jdbc.properties
url = jdbc:mysql://127.0.0.1:3306/test
user = root
password = 1234
3.使用JDBC进行增删改操作
注:这里只列举了更新操作,删除和增加操作同理,都是executeUpdate()函数,将sql语句修改一下就行了。
Connection con = null;
PreparedStatement ps = null;
try {
Class.forName("com.mysql.jdbc.Driver");
ResourceBundle bundle = ResourceBundle.getBundle("jdbc");
String url = bundle.getString("url");
String user = bundle.getString("user");
String password= bundle.getString("password");
//获取数据库连接
con = DriverManager.getConnection(url,user,password);
String sql = "update user set user = ? where user = ?";
//获取preparStatement对象,对数据库进行操作,向里面传入sql语句进行预编译
ps = con.prepareStatement(sql);
String name = "张三";
String name2 ="zhangsan";
//向占位符传入参数
//注mysql中角标从1开始计数
ps.setString(1,name);
ps.setString(2,name2);
//使用excuteUpdate方法对数据库进行修改,返回值为int类型,表示受到影响的数据个数
int i = ps.executeUpdate();
System.out.println(i);
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException throwables) {
throwables.printStackTrace();
}finally {
//判断ps是否为空,不为空关闭,关闭时要注意顺序,应逐层关闭,从小到大
if (ps != null) {
try {
ps.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
if (con != null) {
try {
con.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
}
4.JDBC对数据进行查询操作
Connection con = null;
PreparedStatement ps = null;
//结果集接受对象
ResultSet rs =null;
try {
Class.forName("com.mysql.jdbc.Driver");
ResourceBundle bundle = ResourceBundle.getBundle("jdbc");
String url = bundle.getString("url");
String user = bundle.getString("user");
String password= bundle.getString("password");
con = DriverManager.getConnection(url,user,password);
String sql = "select user,password from user where user = ? ";
ps = con.prepareStatement(sql);
String name = "张三";
ps.setString(1,name);
//运行查询语句
rs = ps.executeQuery();
//判断下一条数据是否为空
while (rs.next()){
//将查询结果以字符串形式得到
String une = rs.getString("user");
String pwd = rs.getString("password");
System.out.println("用户名:"+une+",密码:"+pwd);
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException throwables) {
throwables.printStackTrace();
}finally {
//关闭rs的流
if (rs != null) {
try {
rs.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
if (con != null) {
try {
con.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
if (ps != null) {
try {
ps.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
}
5.关于JDBC的其他说明
1)JDBC中命令是逐行执行的也就是说有一个自动提交机制,这个机制在处理事务时会造成问题,比如说事务是多条语句要执行,如果使用自动提交机制会造成,有的命令执行了,有的命令没执行,这不符合事务的性质,所以我们使用时应将自动提交机制关闭,使用手动提交,并且设立回滚,这样才能保证我们数据的安全。
Connection con = null;
PreparedStatement ps = null;
ResultSet rs =null;
try {
Class.forName("com.mysql.jdbc.Driver");
ResourceBundle bundle = ResourceBundle.getBundle("jdbc");
String url = bundle.getString("url");
String user = bundle.getString("user");
String password= bundle.getString("password");
con = DriverManager.getConnection(url,user,password);
//将自动提交关闭
con.setAutoCommit(false);
String sql = "select user,password from user where user = ? ";
ps = con.prepareStatement(sql);
String name = "张三";
ps.setString(1,name);
rs = ps.executeQuery();
while (rs.next()){
String une = rs.getString("user");
String pwd = rs.getString("password");
System.out.println("用户名:"+une+",密码:"+pwd);
}
//进行手动提交
con.commit();
} catch (Exception e) {
try {
//如果出现异常回滚事务
con.rollback();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
e.printStackTrace();
}finally {
try {
//关闭流时将自动提交打开,供后面人使用
con.setAutoCommit(true);
} catch (SQLException throwables) {
throwables.printStackTrace();
}
if (rs != null) {
try {
rs.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
if (con != null) {
try {
con.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
if (ps != null) {
try {
ps.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
}
2)
Druid
Druid是一个JDBC组件,它包括三部分:
DruidDriver 代理Driver,能够提供基于Filter-Chain模式的插件体系。
DruidDataSource 高效可管理的数据库连接池。
SQLParser
我们使用德鲁伊对数据库连接池进行管理是因为,建立数据库连接耗时耗费资源,一个数据库服务器能够同时建立的连接数也是有限的,在大型的Web应用中,可能同时会有成百上千的访问数据库的请求,如果Web应用程序为每一个客户请求分配一个数据库连接,将导致性能的急剧下降。数据库连接池的意义在于,能够重复利用数据库连接(有点类似线程池的部分意义),提高对请求的响应时间和服务器的性能。连接池中提前预先建立了多个数据库连接对象,然后将连接对象保存到连接池中,当客户请求到来时,直接从池中取出一个连接对象为客户服务,当请求完成之后,客户程序调用close()方法,将连接对象放回池中
1.使用Druid建立数据库连接池
1)配置文件常用参数
#驱动加载
driverClassName=com.mysql.jdbc.Driver
#注册驱动
url=jdbc:mysql://127.0.0.1:3306/student?characterEncoding=utf-8
#连接数据库的用户名
username=root
#连接数据库的密码
password=password
#属性类型的字符串,通过别名的方式配置扩展插件, 监控统计用的stat 日志用log4j 防御sql注入:wall
filters=stat
#初始化时池中建立的物理连接个数。
initialSize=2
#最大的可活跃的连接池数量
maxActive=300
#获取连接时最大等待时间,单位毫秒,超过连接就会失效。配置了maxWait之后,缺省启用公平锁,并发效率会有所下降, 如果需要可以通过配置useUnfairLock属性为true使用非公平锁。
maxWait=60000
#连接回收器的运行周期时间,时间到了清理池中空闲的连接,testWhileIdle根据这个判断
timeBetweenEvictionRunsMillis=60000
minEvictableIdleTimeMillis=300000
#用来检测连接是否有效的sql,要求是一个查询语句。
validationQuery=SELECT 1
#建议配置为true,不影响性能,并且保证安全性。 申请连接的时候检测,如果空闲时间大于timeBetweenEvictionRunsMillis, 执行validationQuery检测连接是否有效。
testWhileIdle=true
#申请连接时执行validationQuery检测连接是否有效,做了这个配置会降低性能。设置为false
testOnBorrow=false
#归还连接时执行validationQuery检测连接是否有效,做了这个配置会降低性能,设置为flase
testOnReturn=false
#是否缓存preparedStatement,也就是PSCache。
poolPreparedStatements=false
#池中能够缓冲的preparedStatements语句数量
maxPoolPreparedStatementPerConnectionSize=200
2)使用配置文件,进行数据库连接池创建
//该类需要两个jar包,分别是JDBC的包和Druid的包
//这个类相当于是一个JDBC的工具类,主要作用是提供获取连接,和关闭连接,运用Druid进行获取和关闭
public class DruidTest {
//声明DataSource对象
private static DataSource dataSource;
static {
//声明Properties集合
Properties pr = new Properties();
try {
//使用pr.load()读取输入流
pr.load(new FileInputStream("Test/src/druid.properties"));
//读取配置文件
dataSource = DruidDataSourceFactory.createDataSource(pr);
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
//给外部提供的获取Connection方法
public static Connection getConnection(){
try {
return dataSource.getConnection();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
return null;
}
//关闭方法
public static void close(Connection con){
if (con != null) {
try {
con.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
}
}
dbUtils
该包是一个工具包,只是对常用的jdbc操作进行封装,让我们更加容易的调用
可以使我们更加简单的实现对数据库的增删改查
1.对数据库进行增删改查
dbUtils有三个比较重要的方法:
1)update() 负责对数据库的增删改查
1.update()方法
//获取QueryRunner对象
QueryRunner qr=new QueryRunner();
//调用update方法
/*
参数说明:
Connection con;数据库连接对象
String sql;要执行的sql语句
Object ... obj;可变长参数,需要传的参数
*/
int a = qr.update(Connection con ,String sql ,Object ... obj );
2)query() 负责对数据库进行查询
※※※接受数据的类型有以下几类:
ArrayHandler,将结果集的第一行存储到对象数组 Object[]
ArrayListHandler;将结果集每一行封装到对象数组,出现很多的对象数组;对象数组存储到List集合
BeanHandler;结果集,数据表第一行,封装到对象中,结果集第一行封装成类对象;
BeanListHanlder;将数据结果集的每一行封装成一个对象 ,多个对象封装到List集合
ColumnListHandler;结果集指定列的数据,存储到List集合
ScalarHandler;查询后只有一个结果的情况下使用 MapHandler;查询结果为一的情况下使用
MapListHandler;将结果集每一行存储到Map集合,键:列名, 值:数据 Map集合过多,存储到List 集合
2.query()方法
QueryRunner qr = new QueryRunner();
接受数据的类型 rs = qr.query(Connection con ,String sql,接受数据的类型,Object ... obj);
3)close() 负责关闭连接
关闭分为close()和closeQuietly()两种方法
1)close()这个方法需要对异常进行捕捉
Connection con = DruidTest.getConnection();
try {
DbUtils.close(con);
} catch (SQLException throwables) {
throwables.printStackTrace();
}
2)closeQuietly()这个方法已经对异常进行捕捉,可以直接使用
DbUtils.closeQuietly(con);