jdbc我们首先先看百度百科对jdbc的定义:
JDBC(Java DataBase Connectivity,java数据库连接)是一种用于执行SQL语句的Java API,可以为多种关系数据库提供统一访问,它由一组用**Java语言编写的类和接口组成。**JDBC提供了一种基准,据此可以构建更高级的工具和接口,使数据库开发人员能够编写数据库应用程序,同时,JDBC也是个商标名。
简单的来说JDBC就是java连接数据库,获取数据库对象的一种技术,JDBC技术是数据库与应用程序之间的桥梁,是数据库与应用程序的中间件。但是JDBC所有的操作部分几乎都是固定的,需要掌握这莫的几个类和接口来帮助我们进一步了解JDBC:
1、DriverManager : 驱动管理对象 - - ->>类
1、功能:注册驱动
Static void registerDriver ( Driver driver ); == = =Class.forName( “com.mysql.jdbc.Driver” );
a注:MySql5之后的jar包可以省略注册驱动这一步
装载MySql驱动:Class.forName(“com.mysql.jdbc.Driver”);
装载Oracle驱动:Class.forName(“oracle.jdbc.driver.OracleDriver”);
2、获取数据库连接
方法:public static Connection getConnection( String url , String user, String password );
url:指定连接的路径。(ip,端口)
MySQL:jdbc:mysql://ip地址(域名):端口号/数据库名称---->一般如过不写ip和端口默认是本机和3306端口
Oracle: oracle.jdbc.driver.OracleDriver
user:用户
password:密码
2、Connection : 数据库连接对象
获取执行Sql的对象。 public Statement stmt = coon.createStatement();
public preparedStatement preparedStatement (String sql);
管理事务:
开启事务:void setAutoComment(boolean b );//将该方法的事务设为False,即为开启事务
提交事务:void commit();
回滚事务:void rollback();
3、Statement : 执行SQL的对象---->接口interface—执行静态SQL
1、执行sql:boolean execte(String sql);
2、 int executeUpdate(String sql) :执行DML(insert \ update\ delete)语句、DDL语句(Create\alter、drop)
返回的值为影响的行数。
3、 ResultSet executeQuery(String sql) 执行给定的 SQL 语句,该语句返回单个 ResultSet 对象。
返回的结果集对象,语句表查询(select)
4、 addBatch(String sql) :把多条sql语句放到一个批处理中。
5、 executeBatch():向数据库发送一批sql语句执行。
3.1、PreparedStatement : —>属于接口(执行动态SQL对象)
1、sql注入问题 输入的用户随便 select * from user_test where username = ‘随便’ and password = ‘a’ or ‘a’ = ‘a’;
字符串拼接存在sql的关键字问题
解决:PreparedStatement 对象解决 —>预编译sql,参数使用?为占位符
这里获取sql方法就变成PreparedStatement Connection.preparedStatement( sql );
这里需要注意为?赋值:
方法:setXxx( 参数1,参数2 )
参数1: ? 的位置编号从1 开始 也是问号的值
参数2:?的值
这里在执行sql的时候不需要传递Sql已经传过了
4、ResultSet : 结果集对象 — 封装查询结果
boolean next();//方法 指针向下移动
Xxx getXxx( 参数 );//获取数据 Xxx表数据类型
1. getString(int index)、getString(String columnName):获得在数据库里是varchar、char等类型的数据对象。
2. getFloat(int index)、getFloat(String columnName):获得在数据库里是Float类型的数据对象。
3. getDate(int index)、getDate(String columnName):获得在数据库里是Date类型的数据。
4. getBoolean(int index)、getBoolean(String columnName):获得在数据库里是Boolean类型的数据。
5. getObject(int index)、getObject(String columnName):获取在数据库里任意类型的数据。
参数的情况:
1、int :代表列的编号,( 这里注意是编号,从1开始 )
2、String : 代表列的名称
注:使用后依次关闭对象及连接:ResultSet → Statement → Connection
上面说到JDBC一般的流程都是固定的,一般为:
1、注册驱动=Class.forName( “com.mysql.jdbc.Driver” )
Oracle: oracle.jdbc.driver.OracleDriver
2、获取数据库连接对象 public Statement stmt = coon.createStatement();
3、设置sql语句,执行SQL的对象,PreparedStatement
4、ResultSet集合 : 结果集对象 — 封装查询结果**
紧接着我们先简短的看一个程序:
import java.sql.*;
import com.mysql.jdbc.Statement;
/**
*
* Title:Dome02.java
* Description:JDBC练习
* @author 会飞的鱼
* 注:这里的资源操作应该会有异常抛出,用try catch finally
* 可以再finally中加入关闭流的操作
*/
public class Dome02 {
//这里需要定义全局变量,方便关闭它
private static Connection conn = null;
private static Statement stat = null;
/*
* user表的添加操作 insert
*/
public static void main(String[] args) {
try {
//1、注册驱动
String dbdriver = "com.mysql.jdbc.Driver";
//String dbdriver = "oracle.jdbc.driver.OracleDriver";
Class.forName(dbdriver);//表注册驱动
//连接的url----》最后为端口号/数据库名称
String dburl = "jdbc:mysql://localhost:3306/mydate";
//3306为数据库的默认连接端口
//mydtae 为数据库的名称
//String dburl = "jdbc:oracle:thin:@localhost:1521:mydate";
String user = "root";
String password = "yl981120";
conn = DriverManager.getConnection(dburl, user, password);//connection对象是用来连接数据库对象的
//定义Sql
String sql = "insert into user values(null,'anyu','女','161031','10111601','123','123456')";
stat = (Statement) conn.createStatement();
int n = stat.executeUpdate(sql);
if(n > 0){
System.out.println("影响的行数"+n);
System.out.println("添加成功");
}else{
System.out.println("操作失败");
}
} catch (SQLException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
} catch (ClassNotFoundException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
}finally{
//这里可能会出现空指针异常
if(stat!=null){
try {
stat.close();
} catch (SQLException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
}
}
if(conn!=null){
try {
conn.close();
} catch (SQLException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
}
}
}
}
}
这里需要注意使用的是什么数据库,就需要用什么来注册驱动,一定要对症下药
装载MySql驱动:Class.forName(“com.mysql.jdbc.Driver”);
装载Oracle驱动:Class.forName(“oracle.jdbc.driver.OracleDriver”);
以及获取url都需要自己来写
连接MySql数据库:Connection conn = DriverManager.getConnection(“jdbc:mysql://host:port/database”, “user”, “password”);
连接Oracle数据库:Connection conn = DriverManager.getConnection(“jdbc:oracle:thin:@host:port:database”, “user”, “password”);
连接SqlServer数据库:Connection conn = DriverManager.getConnection(“jdbc:microsoft:sqlserver://host:port; DatabaseName=database”, “user”, “password”);
在学习完这些之后,当然会自己也写一个JDBC的工具类,用来方便自己以后的使用
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.net.URL;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Properties;
import com.mysql.jdbc.Connection;
import com.mysql.jdbc.Statement;
public class jdbcUtils {
private static String url ;
private static String user ;
private static String password ;
private static String dbDriver ;
//千万记住,如果资源操作仅访问一次,别忘记了static代码块
static{
try {
//文件的读取
Properties pro = new Properties();
//加载文件
//这里有获取src路径下文件的方式=======ClassLoader-->类加载器
ClassLoader cl = jdbcUtils.class.getClassLoader();
URL res = cl.getResource("jdbc.properties");//url对象表示统一资源标识符
String path = res.getPath();
// pro.load(new FileInputStream("src/jdbc.properties"));
//System.out.println(path);
pro.load(new FileInputStream(path));
//获取值
url = pro.getProperty("url");
user = pro.getProperty("user");
password = pro.getProperty("password");
dbDriver = pro.getProperty("driver");
//注册驱动
Class.forName(dbDriver);
} catch (FileNotFoundException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
} catch (IOException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
} catch (ClassNotFoundException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
}
}
/**
* 获取连接
* @return
* @throws SQLException
*/
public static Connection getConnection() throws SQLException{
return (Connection) DriverManager.getConnection(url, user, password);
}
/**
* 如果是查(select)用这个
*/
public static void close(ResultSet rs,Connection conn,Statement stat){
if(rs != null){
try {
rs.close();
} catch (SQLException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
}
}
close(conn,stat);
}
/**
* 如果是sql的操作增删改用这个抛异常
* @param conn
* @param stat
*/
//先写异常加载<如果是增删改>
public static void close(java.sql.Connection conn,Statement stat){
if(stat!=null){
try {
stat.close();
} catch (SQLException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
}
}
if(conn!=null){
try {
conn.close();
} catch (SQLException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
}
}
}
}
上述就是一个简单的javaJDBC的工具包
接下来刚才提到了事务(回滚,提交,开启)的相关东西,一起来看下把事务了解一下
事务:不是一个实实在在存在的东西,如果一个包含多个业务的操作,被事务管理,这些事务要么同时成功,要么同时失败。
提交事务,失败后回滚,提交事务。
操作:1、开启事务:start transaction;======>事务就相当于上锁
2、回滚:rollback
3、提交:commit
SELECT @@autocommit ; 查看事务----1:代表自动提交 2:手动提交
一个DML(是默认自动提交)
而Oracle数据库就是手动提交的
事务一旦开启,就需要手动提交S
set @@autocommit = 0 ; —就修改了事务的默认提交方法
不提交事务,就不会有事务的永久性commit;
事务的四大特征:
1、原子性:是不可分割的最小操作单位。要么同时成功,要么同时失败
2、持久性:当事务提交或者回滚后,数据库会持久性的保存数据。
3、隔离性:多个事务之间相互独立,
4、一致性:表示事务操作前后,总数不改变。
二:事务的隔离性级别:----相当于并发的操作
概念:多个事务之间,相互独立。但是多个事务操作同一批数据,则会发生一些问题
设置不同的隔离级别,就会解决这些问题
问题:
1、脏读;(读脏数据),一个事务,读取到另一个事务没有提交的事务
2、不可重复度(虚读):在一同种事务中,两个读取到的数据不一样,
3、幻读:一个事务操作(DML)数据表中的所有记录,另一个事务添加一条数据,则第一个事务查询不到自己的修改
隔离级别:
1、read uncommitted:读未提交
产生的问题,脏读,不可重复读、幻读
2、read commited : 读以提交 (Oracle数据库默认)
产生的问题:不可重复读、幻读
3、repeatable read : 可重复度 (MYSQL数据库默认的)
产生的问题:幻读
4、serializable : 串行化 —可解决所有的问题
。注意:隔离级别从小到大安全性越来越高,但是效率越来越低
数据库设置级别:
selsect @@tx_isolation—查询
set global transaction isolation level (级别);-----修改
也就是说你在进行jdbc操作的时候,特别是类似于存取钱的场景,如果在取钱的过程中,事务中间发生异常中断,事务没有回滚,那你的钱岂不是不翼而飞了?所以在一般情况下都会加上事务的开启,回滚,提交的动作
这样才能保证事务执行的安全性。
**三:**还有就是数据库连接池的操作,简化JDBC的操作
Spring : jdbc —>技术:jdbc Template
概念:其实就是一个容器(集合),存放数据库连接的容器
系统中初始化好后,容器被创建,容器中会申请一些连接对象,当用户来访问数据库时,从容器中获取连接对象,用户
访问完后,归还给容器
好处:节约资源,用户访问高效
DataSource(interface接口) :获取连接:getConnection( );
归还连接池:如果连接对象Connection是从连接池中获取的,那么
close();方法不会再关闭连接,而时归还
由数据库厂商实现:
1、c3p0 : 数据库连接池CombooledDataSource
2、Druid : 数据库连接池(阿里巴巴)
这里以Druid为例— 需要导入Druid的jar包
书写配置文件Druid.properties,内容包括最大连接数,最大线程数等待
driverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql://127.0.0.1:3306/mydate
username=root
password=yl981120
initialSize=5 //初始化连接数
maxActive=10 //最大对象数
maxWait=3000 //最长等待时间(ms)
以及一个工具类
import java.io.IOException;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;
import javax.sql.DataSource;
import com.alibaba.druid.pool.DruidDataSourceFactory;
//数据库连接池工具类----阿里Druid
public class jdbc_Utils {
private static DataSource ds;
static{
try {
//加载配置文件 -- 书写配置文件
//包括url,
Properties pro = new Properties();
pro.load(jdbc_Utils.class.getClassLoader().getResourceAsStream("druid.properties"));
//2 获取dataSource
ds = DruidDataSourceFactory.createDataSource(pro);
} catch (IOException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
} catch (Exception e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
}
}
/*
* 获取连接池对象
*/
public static Connection getConnection() throws SQLException{
return ds.getConnection();
}
//单例化设计,提供对外的静态获取对象方法
public static DataSource getDataSource(){
return ds;
}
/*
* 关闭流,sql执行对象,和链接对象
*/
public static void close(Statement stat ,Connection conn ){
if(stat != null){
try {
stat.close();
} catch (SQLException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
}
}
if(conn != null){
try {
conn.close();
} catch (SQLException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
}
}
}
//关闭资源
public static void close(ResultSet res,Statement stat ,Connection conn ){
if(res != null){
try {
res.close();
} catch (SQLException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
}
}
close(stat,conn);
}
}
对比于上述的代码,现在的代码两就少了好多,来一个测试类
import org.springframework.jdbc.core.JdbcTemplate;
import TEXT01.jdbc_Utils;
/**
*
* Title:初见Spring.java
* Description:duijdbc的进一步简化
* @author 會飛的魚
*
*/
public class Dome01 {
public static void main(String[] args) {
//首先先导入jar包
//创建jdbcTemplate---前提是接受DataSource
JdbcTemplate template = new JdbcTemplate(jdbc_Utils.getDataSource());
//调用方法:
String sql = "update user_test set count = ? where id = ?";
int n = template.update(sql,5000,2);//这里方法简洁,可直接获取
System.out.println(n);
//这个方法内部封装有归还连接池对像的操作
}
}
我对jdbc的理解有限,欢迎指教!