概念
java DataBase Connectivity java 数据库连接 ,java语言操作数据库
JDBC本质:其实是官方(sum公司)定义的一套操作所有关系类型数据库的规则,即接口.
各个数据库厂商去实现这套接口,提供数据库驱动jar包,我们可以使用这套接口(JDBC)编程.
真正执行的代码是驱动jar包中的实现类
快速入门
public static void main(String[] args) throws ClassNotFoundException, SQLException {
// 1.导入驱动包 mysql-connector-java-5.1.37-bin.jar
// 复制mysql-connector-java-5.1.37-bin.jar到项目lib文件夹下(没有可以自己创建)
// 右键--> Add As Library
// 2.注册驱动
Class.forName("com.mysql.jdbc.Driver");
// 3.获取数据库连接对象
Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/db3", "root", "1234");
// 4.定义sql
String sql="update account set balance =500 where id=1;";
// 5.获取执行sql语句对象 Statemen
Statement stmt = conn.createStatement();
// 6.执行sql,接收返回结果
int count = stmt.executeUpdate(sql);
// 7.处理结果
System.out.println(count);
// 8.释放资源
stmt.close();
conn.close();
}
}
详解各个对象
DriverManager:
DriverManager: 英 /ˈdraɪvə(r)/ 英 /ˈmænɪdʒə(r)/ [拽我麦妮哲]
驱动管理对象
功能:
1.注册驱动:告诉程序该使用哪一个数据库驱动jar
static void registerDriver(Driver driver):注册与给定的驱动程序 DriverManager 。
写代码使用:class.forName("com.mysql.jdbc.Driver");
通过查看源码发现:在com.mysql.jdbc.Driver类中存在静态代码块
static {
try {
java.sql.DriverManager.registerDriver(new Driver());
}catch(SOLException E){
throw new RuntimeException("Can't register driver!");
}
}
注意:mysql5之后的驱动jar包可以省略注册驱动的步骤。
2.获取数据库连接:
方法:static connection.getconnection(string url, string user, string password)
参数:
url:指定连接的路径
语法:jdbc:mysql://ip地址(域名):端口号/数据库名称
例子:jdbc:mysql://localhost:3306/db3
细节:如果连接的是本机mysql服务器,并且mysql服务默认端口是3306,
则url可以简写为:jdbc:mysql:///数据库名称
user:用户名
password:密码
Connection:
数据库连接对象
Connection: 英 /kəˈnekʃn/ [科 耐克神]
功能:
1.获取执行sql对象
Statement createStatement()
PreparedStatement preparedStatement();
2.管理实务
开启事务:
setAutoCommit(boolean aotuCommit):调用该方法色后置参数为false,即开启事务
提交事务:
commit()
回滚事务:
rollback()
Statement:
执行sql的对象
Statement: 英 /ˈsteɪtmənt/ [斯戴特闷特]
1.执行:sql
1.boolean execute(String sql):可以执行任意的sql(了解即可)
2.int executeUpdate(String SQL):执行DML(insert/update/delete)语句,DDL(create/alter/drop)语句
返回值:影响的行数,可以通过这个影响的行数判断语句是否执行成功,返回值>0则成功,反之,则失败
3.Result executeQuery(String sql):执行DQL(select)语句
ResultSet:
结果集对象
ResultSet: 英 /rɪˈzʌlt/ [瑞饶特 赛特]
next():游标向下移动一行
getXxx(): 获取数据
Xxx:代表数据类型 如:int getInt() String getString()
参数:
1.int :代表列的编号,从1开始 比如:getString(1):获取第一列的值
注意:使用步骤
1.游标向下移动一行
2.判断是否有数据
3.获取数据
//执行sql语句
rs = stat.executeQuery(sql);
//循环判断游标是否是最后一行末尾
while (rs.next()){
int id = rs.getInt(1);
String name = rs.getString("name");
int balaance = rs.getInt(3);
System.out.println(id+"==="+name+"==="+balaance);
}
PreparedStatement:
执行sql的对象
英 /prɪˈpeəd/ 英 /ˈsteɪtmənt/ [普瑞 派的 斯戴特闷特]
1,sql 注入问题:
1.用户随便输入密码: a' or 'a'='a
2.sql:select * from user where username ='fhdsjkf' and password = 'a' or 'a'='a'
解决方案:
public static void main(String[] args) {
//键盘录入姓名和密码
System.out.println("请输入用户名:");
Scanner sc=new Scanner(System.in);
String name = sc.nextLine();
System.out.println("请输入密码:");
String password = sc.nextLine();
boolean flag = opinion(name, password);
if (flag){
System.out.println("登陆成功");
}else {
System.out.println("登录失败");
}
}
public static boolean opinion(String name ,String password){
if (name==null||password==null){
System.out.println("请检查账户或者密码");
return false;
}
Connection conn=null;
PreparedStatement pstmt=null;
ResultSet rs=null;
try {
//使用工具类获取connection对象
conn = Utils.getConnection();
String sql="select *from account where name=? and password=?;";
//select *from account where name='lisi' or 1=1 and password='1234' ;
//获取Statement对象
pstmt = conn.prepareStatement(sql);
pstmt.setString(1,name);
pstmt.setString(2,password);
rs = pstmt.executeQuery();
return rs.next();
} catch (SQLException throwables) {
throwables.printStackTrace();
}finally {
Utils.close(rs,pstmt,conn);
}
return false;
}
抽取jdbc的工具类
JDBCUtils
目的:简化书写
分析:
1.注册驱动也抽取
2.抽取一个方法获取连接对象
需求:不想传递参数(麻烦那),还得保证工具类的通用性.
解决:配置文件
jdbc.properties
url=
user=
passwo=
JDBC.properties文件:
url=jdbc:mysql:///db3
user=root
password=1234
driver=com.mysql.jdbc.Driver
3.抽取一个方法释放资源
JDBC工具类:
public class Utils {
private static String url;
private static String user;
private static String password;
private static String driver;
/**
* 文件的读取,只需要读取一次即可拿到这些值,使用静态代码块
* */
static {
//读取资源文件,获取值
try {
//1.创建Properties集合类
Properties pro = new Properties();
//获取src路径下的文件的方式:--->ClassLoader 类加载器
ClassLoader classLoader = Utils.class.getClassLoader();
URL res = classLoader.getResource("jdbc.properties");
String path = res.getPath();
//2.加载文件
pro.load(new FileReader(path));
//3.获取数据,在赋值
url = pro.getProperty("url");
user = pro.getProperty("user");
password = pro.getProperty("password");
driver = pro.getProperty("driver");
//4.注册驱动
Class.forName(driver);
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
/**
* 获取连接
* return连接对象
**/
public static Connection getConnection() throws SQLException {
return DriverManager.getConnection(url, user, password);
}
/**
* 释放资源
*/
public static void close(Statement stmt, Connection conn) {
if (stmt != null) {
try {
stmt.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (conn != null) {
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
public static void close(ResultSet rs, Statement stmt, Connection conn) {
if (rs != null) {
try {
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (stmt != null) {
try {
stmt.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (conn != null) {
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
测试工具类:
public class Test002 {
//测试工具类
public static void main(String[] args) {
Connection conn=null;
Statement stat=null;
ResultSet rs=null;
try {
//使用工具类的方法
conn = Utils.getConnection();
//3.获取statement对象
stat = conn.createStatement();
//4.定义sql语句
String sql="select *from account;";//删除account表中字段你name=wangwu的所有记录
//5.执行sql语句
rs = stat.executeQuery(sql);
//6.输出结果
while (rs.next()){
int id = rs.getInt(1);
String name = rs.getString("name");
int balaance = rs.getInt(3);
System.out.println(id+"==="+name+"==="+balaance);
}
} catch (SQLException throwables) {
throwables.printStackTrace();
}finally{
//释放资源
if(rs!=null){
try {
rs.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
if(stat!=null){
try {
rs.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
if(conn!=null){
try {
rs.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
}
}
}
JDBC控制事务
事务:一个包含多个步骤的业务操作.如果这个业务操作被事务管理,则这个步骤要么同时成功,要么同时失败
操作
开启事务
提交事务
回滚事务
使用connection对象来管理事务
开启事务:setAutoCommit(Boolean autoCommit):调用该方法设置参数为false,即为开启事务
提交事务:commit()
回滚事务:rollback()
案例:银行转账系统张三给李四转账500元,中途手动制造异常,使用事务处理
public static void main(String[] args) throws SQLException {
Connection conn=null;
PreparedStatement pstmt1=null;
PreparedStatement pstmt2=null;
try {
//获取连接
conn = Utils.getConnection();
//开启事务
conn.setAutoCommit(false);//false为开启事务
//定义sql
String sql1="update yinhang set money=money-? where name=?;";//定义张三-500
String sql2="update yinhang set money=money+? where name=?;";//定义李四+500
//获取sql对象
pstmt1 = conn.prepareStatement(sql1);
pstmt2 = conn.prepareStatement(sql2);
//设置参数
pstmt1.setInt(1,500);
pstmt1.setString(2,"zhangsan");
pstmt2.setInt(1,500);
pstmt2.setString(2,"lisi");
pstmt1.executeUpdate();
//手动制造异常
int i=3/0;
pstmt2.executeUpdate();
//提交事务
conn.commit();
} catch (Exception throwables) {
if(conn!=null){
try {
conn.rollback();
} catch (SQLException e) {
e.printStackTrace();
}
}
throwables.printStackTrace();
}finally {
Utils.close(pstmt1,conn);
Utils.close(pstmt2,null);//实际开发不能这样写,只为测试
}
}
数据库连接池
概念 :
其实就是一个容器(集合),存放数据库连接的容器
当容器初始化好,容器被创建,容器中会申请一些连接对象,当用户来访问数据库时,从容器中获取连接对象,用户访问完之后,会将连接对象归还给容器;
好处:
节约资源
用户访问高效
实现:
标准接口:DataSource javax.sql包下的
方法:
获取连接:getConnection()
归还连接:Connection.close().
如果连接对象connection是从连接池中获取的,那么调用Connection.close()方法
则不会再关闭了,而是归还连接.
一般我们不去实现它,有数据库厂商来实现
C3P0:数据库连接池技术;
Druid:数据库连接池技术,由阿里巴巴提供的
C3P0:数据库连接池技术
步骤:
1导入jar包(两个)c3p0-0.9.5.2.jar mchange-commons-java-0.2.12.jar
*不要忘记导入数据库驱动jar包
2.定义配文件:
*名称:c3p0.properties或者c3p0-config.xml
* 路径:直接将文件放在src目录下即可。
3.创建核心对旅数据库连接池对象EomboPooledDataSource
4.获取连接:getConnection
Druid:数据库连接池技术
步骤:
1.导入jar包 druid-1.0.9.jar
2.定义配文件:
*是properties形式的
可以叫任意名称,可以放在任意目录下
3.加载配文件。Properties
4.获取数据库连接池对象:通过工厂来来获取DruidDataSourceFactory
5.获取连接:getConnection
public static void main(String[ args) throws :Exception {
//1.导入jar包 文件复制到lib
//2.定义配文件 把properties文件复制
//3.加载配置文件
Properties pro = new Properties();
InputStream is =DruidDemo.class.getClassLoader.getResourceAsStream( name: "druid.properties" );
pro.load(is);
//4.获取连接池对象
DataSource ds =DruidDataSourceFactory.createDataSource(pro);
//5.获取连接
Connection conn =ds.getConnection();
System.out.println(conn);
定义一个工具类:
druid.properties文件
url=jdbc:mysql:///db3
username=root
password=1234
driverClassName=com.mysql.jdbc.Driver
initialSize=5
maxActive=10
maxWait=3000
定义一个类 JDBCUtils
提供静态代码块加载配置文件,初始化连接池对象
提供方法
获取连接的方法:通过数据库连接池获取连接
释放资源
获取连接池的方法
//1定义成员变量DataSource
private static DataSource ds;
static {
try {
//1.加载配置文件
Properties pro = new Properties();//创建properties属性集对象
//读取druid.properties配置文件
pro.load(JDBCUtils.class.getClassLoader().getResourceAsStream(name:"druid.properties"));
//使用druid提供的api,获取DataSource
ds = DruidDataSourceFactory.createDataSource(pro);
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 获取连接
*/
public static Connection getConnection() throws SQLException {
return ds.getConnection();
}
/**
* 释放资源
* <p>
* /**
* 释放资源
*/
public static void close(Statement stmt, Connection conn) {
if (stmt != null) {
try {
stmt.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (conn != null) {
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
public static void close(ResultSet rs, Statement stmt, Connection conn) {
if (rs != null) {
try {
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (stmt != null) {
try {
stmt.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (conn != null) {
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
public static DataSource getDataSource(){
return ds;
}
测试druid工具类
给account表增加一条数据,添加成功则控制台打印输出:录入数据的行数
public static void main(String[] args) {
Connection conn = null;
PreparedStatement pstmt = null;
//给account表添加一条记录
try {
//获取数据
conn = JDBCUtils.getConnection();
//定义sql
String sql = "insert into account(ID,NAME, password) value (NULL,?,?);";
//获取PreparedStatement对象
pstmt = conn.prepareStatement(sql);
//给?赋值
pstmt.setString(1, "zhangsan");
pstmt.setInt(2, 1000);
//执行sql
int index = pstmt.executeUpdate();
System.out.println(index);
} catch (SQLException throwables) {
throwables.printStackTrace();
} finally {
JDBCUtils.close(pstmt,conn);
}
}