介绍jdbc
1.为访问不同的数据库提供了统一的接口,为使用者屏蔽了细节问题。
2.jdbc是java提供一套用于数据库操作的接口API,java程序员只需要向这套接口编程即可,不同的数据库厂商需要针对这套接口提供不同实现。
3.jdbc API是一系列的接口,它统一和规范了应用程序与数据库的连接,执行SQL语句,并得到返回结果等各类操作,相关类和接口。在java.sql与javax.sql包中。
jdbc程序编写步骤
首先加入相关jar包
1.注册驱动——加载Driver类
Driver driver = new Driver;//创建driver对象
2.获取连接——得到Connection
String url = "jdbc:mysql://主机或ip地址:端口号/数据库名";
//将用户名和密码放到properties对象
Properties properties = new Properties();
properties.setProperty("user", "root");//用户
properties.setProperty("password", "123456");//密码
Connection connect = driver.connect(url, properties);//网络连接
3.执行增删改查——发送sql给mysql执行,statement
String sql = "sql语句";
Statement statement = connect.createStatement();
//statement用于执行静态SQL语句并返回其生成的结果的对象
int rows = statement.executeUpdate(sql);
//如果是dml语句,返回的就是影响行数。
4.释放资源——关闭相关连接
statement.close();
connect.close();
获取数据库连接5种方式
方式一
Driver driver = new Driver;//创建driver对象
String url = "jdbc:mysql://主机或ip地址:端口号/数据库名";
//将用户名和密码放到properties对象
Properties properties = new Properties();
properties.setProperty("user", "root");//用户
properties.setProperty("password", "123456");//密码
Connection connect = driver.connect(url, properties);//网络连接
方式二
//使用反射加载Driver类,动态加载,更加灵活,减少依赖
Class<?> aClass = Class.forName("com.mysql.jdbc.Driver");
Driver driver = (Driver)aClass.newInstance();
String url = "";
Properties properties = new Propertied();
properties.setProperty("user" , " ");
properties.setProperty("password" , " ");
Connect connect = driver.connect(url, properties);
方式三
//DriverManager替代Driver,DriverManager用于管理一组JDBC驱动程序的基本服务
Class<?> aClass = Class.forName(" ");
Driver driver = (Driver)aClass.newInstance();
String url = " ";
String user = " ";
String password = " ";
DriverManager.registerDdriver(driver);//注册Driver驱动
Connection connection = DriverManager.getConnection(url, user,password);
方式四
//使用Class.forName自动完成注册驱动,简化代码
Class.forName(" ");
String url = " ";
String user = " ";
String password = " ";
Connection connection = DriverManager.getConnection(url, user,password);
1.mysql驱动5.1.6可以无需Class.forName(" ");
2.从jdk1.5以后使用了jdbc4不在需要显示调用class.forName()
注册驱动是自动调用驱动jar包下META-INF\services\java.sql.Driver文本中的类名称去注册
3.建议还是写上class.forName(" ");
方式五
在方式四上改进,增加配置文件,让连接mysql更加灵活
Properties properties = new Properties();
properties.load(new FileInputStream(" ");
String user = properties.getProperty("user");
String url = properties.getProperty("url");
String driver = properties.getProperty("driver");
String password = properties.getProperty("password");
Class.forName(driver);
Connection connection = DriverManager.getConnection(url, user,password);
ResultSet 结果集
1.表示数据库结果集的数据表,通常通过执行查询数据库的语句生成。
2.ResultSet对象保持一个光标指向当前的数据行的第一行之前。
3.next方法将光标移动到下一行,并且由于ResultSet对象中没有更多行时返回false,因此,可以在while循环中使用循环来遍历结果集,用完需要关闭。
连接好后
Statement statement = connection.createStatement();
String sql = "select id, name ... from actor";
ResultSet resultSet = statement.executeQuery(sql);
while(resultSet.next()){
int id = resultSet.getInt(1);//获取第1列
...(2);
}
Statement
1.用于执行静态sql语句并返回其生成的结果的对象
2.在连接建立后,需要对数据库进行访问,执行sql语句可以通过
Statement (存在sql注入)
PreparedStatement(预处理)
CallableStatement (存储过程)
3.sql注入是利用某些系统没有对用户输入的数据进行充分的检查,而在用户输入数据中注入非法的sql语句段或者命令,恶意攻击数据库。
4.要防范sql注入,只要用PreparedStatement(从Statement扩展而来),取代Statement就可以了。
PreparedStatement
1.PreparedStatement执行的sql语句中的参数用(?)来表示,调用PreparedStatement对象的setxxx()方法来设置这些参数,setxxx()方法有两个参数,第一个参数是要设置的sql语句中的参数的索引(从1开始),第二个是设置的sql语句中的参数的值
2.调用executeQuery(),返回ResultSet对象
3.调用executeUpdate(),执行更新,包括增删修改。
好处:
1.不再使用+拼接sql语句,减少语法错误
2.有效的解决了sql注入问题
3.大大减少了编译次数,效率较高
jdbc API | DriverManager 驱动管理类 | getConnect(url, user, pwd) 获取连接 |
Connection接口 | createStatement 创建statement | |
preparedStatement(sql) 生成预处理对象 | ||
Statement接口 | executeUpdate(sql)执行sql,返回影响的行数 | |
executeQuery(sql)执行查询,返回ResultSet对象 | ||
execute(sql)执行任意的sql返回布尔值 | ||
PrepareStatement | executeUpdate(sql)执行sql,返回影响的行数 | |
executeQuery(sql)执行查询,返回ResultSet对象 | ||
execute(sql)执行任意的sql返回布尔值 | ||
setxxx(索引, 值) | ||
setObject(占位符索引, 占位符) | ||
ResultSet结果集 | next()向下移动一行,下一行无数据返回false | |
previous()向上移动 | ||
getxxx(列的索引 | 列名) 返回列的值 | ||
getObject(列的索引 | 列名)返回对应列的值,接受类型为Object |
封装JDBCUtils
在jdbc操作中,获取连接和释放资源是经常使用到的,可以将其封装JDBC连接的工具类JDBCUtils
public class JDBCUtils{
//定义相关的属性(4个),因为只需要一份,因此做出static
private static String user;
private static String password;
private static String url;
private static String driver;
//在static代码块去初始化
static{
try{
Properties properties = new Properties();
properties.load(new FileInputStream("src\\musql.properties"));
//读取相关属性值
user = properties.getProperty("user");
password = properties.getProperty("password");
url = properties.getProperty("url");
driver = properties.getProperty("driver");
} catch (IOException e) {
//在实际开发中,我们可以这样处理
//1.将编译异常转成运行异常
//2.调用者可以选择捕获异常,也可以选择默认处理该异常,比较方便
throw new RuntimeExceptionce;
}
}
public static Connection getConnection() {
try{
return DriverManager.getConnection(url, user, password);
}catch (SQLExeception e){
//1.将编译异常转成运行异常
//2.调用者可以选择捕获该异常,也可以选择默认处理该异常,比较方便
throw new RuntimeException(e)
}
}
//关闭相关资源
public static void close(ResultSet set, Statement statement, Connection connection){
try{
if(set != null){
set.close();
}
if(statement != null){
statement.close();
}
if(connection != null){
connection.close();
}
}catch (SQLExeception e){
throw new RuntimeException(e)
}
}
}
事务
1.JDBC程序中当一个Connection对象创建时,默认情况下是自动提交事务,每次执行一个sql语句时,如果执行成功,就会向数据库自动提交,而不能回滚。
2.JDBC程序中为了让多个SQL语句作为一个整体执行,需要使用事务。
3.调用Connection的setAutoCommit(false)可以取消自动提交事务。
4.在所有的SQL语句都成功执行时,调用Connection的commit()方法提交事务。
5.在其中某个操作失败或出现异常时,调用rollback()方法回滚事务。
批处理
1.当需要成批插入或者更新记录时,可以采用Java的批量更新机制,这一机制允许多条语句一次性提交给数据库批量处理,通常情况下比单独提交处理更有效果。
2.JDBC的批量处理语句包括下面方法:
addBatch():添加需要批量处理的SQL语句或参数。
executeBach():执行批量处理语句。
clearBatch():清空批处理包的语句。
3.JDBC连接mysql时,如果要使用批处理功能,请在url中加参数rewriteBatchedStatements =true
4.批处理往往和PreparedStatement一起搭配使用,可以既减少编译次数,又减少运行次数,效率大大提高。
数据库连接池
来源
1.传统的JDBC数据库连接使用DriverManager来获取,每次向数据库建立连接的时候都将Connection加载到内存中,再验证IP地址,用户名和密码。需要数据库连接的时候,就向数据库要求一个频繁的进行数据库连接操作,将占用很多的系统资源,容易造成服务器崩溃。
2.每一次数据库连接,使用完后都得断开,如果程序出现异常而未能关闭,将导致数据库内存泄漏,最终将导致重启数据库。
3.传统的获取的方式,不能控制创建的连接数量,如果连接过多,也可能导致内存泄漏,Mysql崩溃。
4.解决传统开发中的数据库连接问题,可以采用数据库连接池技术。
数据库连接池基本介绍
1.预先在缓冲器池中放入一定量的连接,当需要建立数据库连接时,只需从“缓冲池”中取出一个,使用完毕之后再放回去。
2.数据库连接池负责分配,管理和释放数据库,它允许应用程序重复使用一个现有的数据库连接,而不是重新建立一个。
3.当应用程序向连接池请求的连接超过最大连接数量时,这些请求被加入等待队列中。
数据库连接池种类
1.JBDC的数据库连接池使用javax.sql.DataSource来表示,DataSource只是一个接口,该接口通常由第三方提供实现。
2.C3P0数据库连接池,速度相对较慢,稳定性不错。
3.DBcp数据库连接池,速度相对c3p0较快,但不稳定。
4.Proxool数据库连接池,有监控连接池的状态的功能,稳定性较c3p0差一点。
5.BoneCP数据库连接池速度快
6.Druid(德鲁伊)是阿里提供的数据库连接池,集DBcp,C3P0,ProXool优点于一身的数据库连接池。
C3P0
public class C3P0_{
//方式1:相关参数,在程序中指定user,url,password等
public void testC3P0_01() throws Exception{
CombopooledDataSource comblpooledDataSource = new CombopooledDataSource();
Properties properties = new Properties();
properties.load(new FileInputStream(" "));
String user = properties.getProperty("user");
String password = properties.getProperty("password");
String url = properties.getProperty("url");
String driver = properties.getProperty("driver");
//给数据源CombopooledDataSource设置相关的参数
CombopooledDataSource.setDriverClass(driver);
CombopooledDataSource.setJdbcUrl(url);
CombopooledDataSource.setPassword(password);
//设置初始化连接数
CombopooledDataSource.setInitialPoolSize(10);
//最大连接数
CombopooledDataSource.setMaxPoolSize(10);
Connnection connection = CombopooledDataSource.getConnection();
System.out.println("连接成功");
connection.close();
}
}
//第二种方式 使用配置文件模板来完成
//1.将c3p0提供的c3p0,config,xml拷贝到src目录下
//2.该文件指定了连接数据库和连接池的相关参数
public void testC3P0_02(){
CombopooledDataSource combopooledDataSource = new CombopooledDataSource(" ");
Connection connection = combopooledDataSource.getConnection();
System.out.println("连接成功");
connection.close();
}
Druid
public void testDruid() throws Exeception{
//1.加入Druid jar包
//2.加入配置文件druid.properties,将该文件拷贝项目的src目录
//3.创建Properties对象,读取配置文件
Properties properties = new Properties();
properties.load(new FileInputStream(" "));
//4.创建一个指定参数的数据库连接池
DataSource dataSource = DruidDataSourceFactory.createDataSource(properties);
Connection connection = dataSource.getConnection();
System.out.println("连接成功");
connection.close();
}
基于Druid 数据库连接池的工具类
public class JDBCUtilsByDruid{
private static DataSource ds;
static {
Properties properties = new Properties();
try{
properties.load(new File.InputStream(" "));
ds = DruidDataSourceFactory.createDataSource(properties);
} catch(Exeception){
e.printStackTrace();
}
}
public static Connection getConnection() {
return ds.getConnection();
}
public static void close (ResultSet resultSet, Statement statement, Connection connection) {
try{
if(resultSet != null) {
resultSet.close();
}
if(statement != null) {
statement.close();
}
if(connection != null) {
connection.close();
}
} catch(SQLException e){
throw new RuntimeException(e);
}
}
}
Apache-DBUtils
问题:
1.结果集合connection是关联的,如果关闭连接,就不能使用结果集。
2.结果集不利于数据管理(只能用一次)。
3.使用返回信息也不方便(set.getString("name")...)
基本介绍
1.Commons-dbutils是Apache组织提供的一个开源JDBC工具类库,他是对JDBC的封装,使用dbutils能极大简化jdbc编码的工作量。
2.使用QueryRunner类实现查询
3.ResultSetHandle接口:该接口用于处理java.sql.ResultSet。将数据按要求转换为另一种形式
使用Apache-DBUtils工具类+druid完成对表的crud操作
//1.得到连接
Connectoin connection = JDBCUtilsByDruid.getConnection();
//2.使用DBUtils类和接口,先引入DBUtils相关的jar
//3.创建QUeryRunner
QueryRunner queryRunner = new QueryRunner();
//4.就可以执行相关的方法返回Arraylist
String sql = "select * from actor where id >= ?";
List<Actor> list = queryRunner.query(connection, sql, new BeanListHandle<>(Actor.class),1);
/*
1.query方法就是执行sql语句,得到resultset封装到ArrayList集合中
2.返回集合
3.connection:连接
4.sql:执行的sql语句
5.new BeanListHandler<>(Actor.class);再将resultset->Actor对象 ->封装到ArrayList,底层使用反射机制去获取Actor类的属性,然后进行封装
6.1就是给sql语句中的?赋值,可以有多个值,因为是可变参数。
7.底层得到resultset会在query关闭,关闭PreparedStatement
*/
for (Actor actor:list){
System.out.println(actor);
}
JBDCUtilsByDruid.close(null, null, connection);
Apache-dbutils + druid 完成返回的结果是单行记录(单个对象)
//1.得到连接
Connectoin connection = JDBCUtilsByDruid.getConnection();
//2.使用DBUtils类和接口,先引入DBUtils相关的jar
//3.创建QUeryRunner
QueryRunner queryRunner = new QueryRunner();
//4.就可以执行相关的方法返回单个对象
String sql = "select * from actor where id = ?";
Actor actor = queryRunner.query(connection, sql, new BeanHandle<>(Actor.class), 1);
System.out.println(actor);
JBDCUtilsByDruid.close(null, null, connection);
Apche-dbutils + druid 完成查询结果是单行单列,返回的就是object
//1.得到连接
Connectoin connection = JDBCUtilsByDruid.getConnection();
//2.使用DBUtils类和接口,先引入DBUtils相关的jar
//3.创建QUeryRunner
QueryRunner queryRunner = new QueryRunner();
//4.就可以执行相关的方法返回单行单列
String sql = "select name from actor where id = ?";
Object obj = queryRunner.query(connection, sql, new ScalarHandler(), 1);
System.out.println(obj);
JBDCUtilsByDruid.close(null, null, connection);
Apche-dbutils + druid 组织sql语句完成update,insert,delete
//1.得到连接
Connectoin connection = JDBCUtilsByDruid.getConnection();
//2.使用DBUtils类和接口,先引入DBUtils相关的jar
//3.创建QUeryRunner
QueryRunner queryRunner = new QueryRunner();
//4.就可以执行相关的方法返回单行单列
String sql = "update actor set name = ? where id = ?";
int affectedRow = queryRunner.update(connection, sql, "张三丰", 1);
//执行dml操作是queryRunner.update()
//返回的值是受影响的行数
System.out.println(affectedRow > 0 ? "操作成功" : "对表没影响" ;
JBDCUtilsByDruid.close(null, null, connection);
Dao和增删改查通用方法-BasicDao
Dao:data access object 数据访问对象
apache-dbutils + Druid 简化了JDBC开发,但还有不足
1.SQL语句数固定的,不能通过参数传入,通用性不好,需要进行改进,更方便执行增删改查。
2.对于select操作,如果有返回值,返回类型不能固定需要使用泛型。
3.将来的表很多,业务需求复杂,不可能只靠一个java类完成
基本说明
1.这样的通用类,称为BasicDao,是专门和数据库交互的,即完成对数据库(表)的crud操作。
2.在BasicDao的基础上,实现一张表,对应一个Dao,更好的完成功能。