jdbc怎么引入项目,jdbc连接步骤

首页 > 书籍文档 > 作者:YD1662023-12-30 23:32:01

1. 简介与基本代码实现

1. 简介:jdbc即java数据库连接,是sun公司用于统一数据库操作代码而制定的一套规范(提供了一套接口由数据库厂商实现,开发者只需加载相应的数据库驱动并调用这些接口即可操作数据库),简称为JDBC。

2. 基本代码实现:

import java.sql.Connection; import java.SQL.DriverManager; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.statement; import com.MySQL.jdbc.Driver;//这个就是mysql实现的Driver接口实现类 /** * @ClassName:JDBCDemo1 * @Description:JDBC基础开发过程 * 首先需要引入需要连接的对应数据库的jar包,比如mysql为mysql-connector-java */ public class JDBCDemo1 { public static void main(String[] args) { try { //1. 注册mysql数据库连接的驱动类 DriverManager.registerDriver(new Driver()); // 2. 获取到数据库的连接对象,指定数据库的url,用户名和密码 Connection con=DriverManager.getConnection("jdbc:mysql://localhost:3306/studytest", "root", "123456"); //3. 编写SQL语句 String sql="select * from employee"; // 4. 执行SQL语句,创建能执行SQL语句的Statement对象,然后通过这个对象执行 Statement statement=con.createStatement(); // 5. 获取执行SQL语句的结果 ResultSet rs=statement.executeQuery(sql); // 6. 遍历rs中的结果 while(rs.next()){ // 获取某个字段的数据,可以通过字段名,也可以通过查询的所有字段中目标字段在第几个位置的下标 System.out.println(rs.getInt("id"));//可以通过字段名 System.out.println(rs.getString(2));;//也就是获取第二个字段username下的数据 System.out.println(rs.getFloat("salary")); System.out.println(); //注意获取的字段值的类型必须要对应get 数据类型()的方法 } // 7. 释放资源 rs.close(); statement.close(); con.close(); } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }

3. 上面所写的基本JDBC实现代码的缺点:

jdbc怎么引入项目,jdbc连接步骤(1)

所以,可以使用Class.forName()来改善上面两个缺点。改善代码如下

import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; public class JDBCDemo2 { public static void main(String[] args) { try { //加载com.mysql.jdbc.Driver类,直接进行数据库驱动注册 Class.forName("com.mysql.jdbc.Driver"); // 2. 获取到数据库的连接对象,指定数据库的url,用户名和密码 Connection con=DriverManager.getConnection("jdbc:mysql://localhost:3306/studytest", "root", "123456"); //3. 编写SQL语句 String sql="select * from employee"; // 4. 执行SQL语句,创建能执行SQL语句的Statement对象,然后通过这个对象执行 Statement statement=con.createStatement(); // 5. 获取执行SQL语句的结果 ResultSet rs=statement.executeQuery(sql); // 6. 遍历rs中的结果 while(rs.next()){ // 获取某个字段的数据,可以通过字段名,也可以通过查询的所有字段中目标字段在第几个位置的下标 System.out.println(rs.getInt("id"));//可以通过字段名 System.out.println(rs.getString(2));;//也就是获取第二个字段username下的数据 System.out.println(rs.getFloat("salary")); System.out.println(); //注意获取的字段值的类型必须要对应get 数据类型()的方法 } // 7. 释放资源 rs.close(); statement.close(); con.close(); } catch (ClassNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }

4. Connection对象:代表一个与数据库之间的连接对象。其作用有

5. Statement对象:用于向数据库发送要执行的SQL语句,常用执行方法

使用批处理执行大量SQL语句肯定要比单条SQL语句执行更快。

6. ResultSet 对象:用于保存查询语句返回的结果集,只有查询语句的执行才会返回该对象。其封装数据采用类似与表格的数据结构,其内部维护了一个指向表格数据行的游标,游标初始时会指向第一行数据,当执行ResultSet 对象的 next()方法时,游标便会下移一行,可以通过get 指定数据类型()的方法来获取指定字段下的当前行数据。比如

还有其余获取数据方法,其方法名形式都为get 指定数据类型;每个方法都有两个版本,一个版本的参数为字段名字符串,另一个则是字段在查询得到的字段集中按照书写顺序的下标。通常都使用字段名字符串来取值。

7. 资源对象的释放:ResultSet对象、Statement对象和Connection对象在使用结束后都必须立即释放,尤其是Connection对象,而资源的释放代码一般都放在finally块里,保证资源释放代码一定会执行。

import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; public class JDBCDemo2 { public static void main(String[] args) { Connection con=null; Statement statement=null; ResultSet rs=null; try { //加载com.mysql.jdbc.Driver类,直接进行数据库驱动注册 Class.forName("com.mysql.jdbc.Driver"); // 2. 获取到数据库的连接对象,指定数据库的url,用户名和密码 con=DriverManager.getConnection("jdbc:mysql://localhost:3306/studytest", "root", "123456"); //3. 编写SQL语句 String sql="select * from employee"; // 4. 执行SQL语句,创建能执行SQL语句的Statement对象,然后通过这个对象执行 statement=con.createStatement(); // 5. 获取执行SQL语句的结果 rs=statement.executeQuery(sql); // 6. 遍历rs中的结果 while(rs.next()){ // 获取某个字段的数据,可以通过字段名,也可以通过查询的所有字段中目标字段在第几个位置的下标 System.out.println(rs.getInt("id"));//可以通过字段名 System.out.println(rs.getString(2));;//也就是获取第二个字段username下的数据 System.out.println(rs.getFloat("salary")); System.out.println(); //注意获取的字段值的类型必须要对应get 数据类型()的方法 } } catch (ClassNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); }finally { // 7. 释放资源 try { if(rs!=null){ rs.close(); } rs=null; } catch (SQLException e) { e.printStackTrace(); } try { if(statement!=null){ statement.close(); } statement=null; } catch (SQLException e) { e.printStackTrace(); } try { if(con!=null){ con.close(); } con=null; } catch (SQLException e) { e.printStackTrace(); } } } }

8. 修改连接数据库的几个必需字符串,改为通过配置文件的方式来获取:先添加一个db.properties文件,并填写对应数据

import java.io.IOException; import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import java.util.Properties; public class JDBCDemo3 { public static void main(String[] args) { Connection con=null; Statement statement=null; ResultSet rs=null; try { Properties pro=new Properties(); pro.load(JDBCDemo3.class.getClassLoader().getResourceAsStream("jdbc/db.properties")); String driver=pro.getProperty("driver"); String user=pro.getProperty("user"); String url=pro.getProperty("url"); String password=pro.getProperty("password"); Class.forName(driver); con=DriverManager.getConnection(url, user, password); String sql="select * from employee"; statement=con.createStatement(); rs=statement.executeQuery(sql); while(rs.next()){ System.out.println(rs.getInt("id")); System.out.println(rs.getString(2)); System.out.println(rs.getFloat("salary")); System.out.println(); } } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (SQLException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); }finally { try { if(rs!=null){ rs.close(); } } catch (SQLException e) { e.printStackTrace(); } rs=null; try { if(statement!=null){ statement.close(); } } catch (SQLException e) { e.printStackTrace(); } statement=null; try { if(con!=null){ con.close(); } } catch (SQLException e) { e.printStackTrace(); } con=null; } } }

2. SQL注入漏洞

1. SQL语句是字符串类型,而且其通常都由多个字符串拼接而成,以用户登录为例

String username; String password; String sql="select * from user where username=" username "and password=" password;

username和password的值通常都是由用户输入,由前端传入后台进行验证,如果username输入为" 'sdfds' or 1=1",而password的值任意那么SQL语句就变成:

select * from user where username='sdfds' or 1=1 and password='任意值';

如果username正确,那么 username='sdfds' 得到true,而密码是错误的,而且and的优先级更高,所以 1=1 and password='任意值' 先进行逻辑运算 得到false,然后 true or false 得到true,所以会判断密码正确,进而就造成了不安全的SQL注入漏洞。

2. 解决方法:SQL语句的执行对象使用PreparedStatement对象,因为该对象会预编译SQL,可以防止SQL注入漏洞;该对象所执行的SQL语句,不需要通过字符串拼接来指定SQL语句中需要手动填入的字符串符合,而是替换为 ? 占位符的形式,然后将该SQL语句的格式进行预编译,当编译完成后SQL语句的格式就会被固定,通过PreparedStatement对象向 ? 处的数据需要填充的参数,填充在占位符的数据全部都会成为指定的数据类型形式,而不会出现上面拼接字符串中出现的情况(也就是说会把or、=等关键字当做普通字符串处理),所以就避免了SQL注入漏洞。

PreparedStatement对象通过

import java.io.IOException; import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.util.Properties; public class JDBCDemo4 { public static void main(String[] args) { Connection con=null; PreparedStatement statement=null; ResultSet rs=null; try { Properties pro=new Properties(); pro.load(JDBCDemo3.class.getClassLoader().getResourceAsStream("jdbc/db.properties")); String driver=pro.getProperty("driver"); String user=pro.getProperty("user"); String url=pro.getProperty("url"); String password=pro.getProperty("password"); Class.forName(driver); con=DriverManager.getConnection(url, user, password); String id="1"; //String sql="select * from employee where id=" id; String sql="select * from employee where id=?";//将拼接字符串改为占位符形式 statement=con.prepareStatement(sql);//进行预编译,固定SQL语句格式 //设置占位符处参数的值,填充数据的参数类型为int型,设置在第一个 ? 占位符处,填充数据为2 //对于or、=等数据库关键字是不被识别的,也是会报错的,无法在这里设置字符串类型的数据,只能是int值 statement.setInt(1,2); //执行时不需要传入sql语句作为参数,因为在预编译时就已经传入,只需直接执行即可 rs=statement.executeQuery(); while(rs.next()){ System.out.println(rs.getInt("id")); System.out.println(rs.getString(2)); System.out.println(rs.getFloat("salary")); System.out.println(); } } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (SQLException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); }finally { try { if(rs!=null){ rs.close(); } } catch (SQLException e) { e.printStackTrace(); } rs=null; try { if(statement!=null){ statement.close(); } } catch (SQLException e) { e.printStackTrace(); } statement=null; try { if(con!=null){ con.close(); } } catch (SQLException e) { e.printStackTrace(); } con=null; } } }

3. 事务

1. 简介:事务表示一组逻辑上的操作,要么全部成功要么全部失败。其有四个特性,原子性、一致性、隔离性和持续性。通常用于一组数据更新操作。

2. MySQL中事务相关的命令:

3. 开启事务的两种方法:在事务中执行的SQL语句,操作的是临时表,更改的数据也是临时表的数据,提交之后才会更改数据库表中的数据

start transaction;//开启事务 //执行多个SQL语句 sql1; sql2; ... commit;//提交SQL语句执行结果 或 rollback;//回滚SQL语句执行结果

show variables like '%commit%';//查看当前数据库是否自动提交SQL执行结果的,如果是 set autocommit = off或0; sql1; sql2; ... commit;//提交 或 rollback;//回滚

4. JDBC代码中使用事务:通过java.sql.Connection对象来操作事务

import java.io.IOException; import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.util.Properties; /** * @ClassName:JDBCDemo5 * @Description:JDBC代码中使用事务 */ public class JDBCDemo5 { public static void main(String[] args) { Connection con=null; PreparedStatement statement=null; ResultSet rs=null; try { Properties pro=new Properties(); pro.load(JDBCDemo3.class.getClassLoader().getResourceAsStream("jdbc/db.properties")); String driver=pro.getProperty("driver"); String user=pro.getProperty("user"); String url=pro.getProperty("url"); String password=pro.getProperty("password"); Class.forName(driver); con=DriverManager.getConnection(url, user, password); //开启事务 con.setAutoCommit(false); String sql="insert into employee values(null,'vn',20234,1)"; PreparedStatement ps=con.prepareStatement(sql); ps.executeUpdate(sql);//执行SQL语句 //提交事务 con.commit(); } catch (ClassNotFoundException e) { //若发生异常,则事务回滚 try { con.rollback(); } catch (SQLException e1) { // TODO Auto-generated catch block e1.printStackTrace(); } e.printStackTrace(); } catch (SQLException e) { //若发生异常,则事务回滚 try { con.rollback(); } catch (SQLException e1) { // TODO Auto-generated catch block e1.printStackTrace(); } e.printStackTrace(); } catch (IOException e) { //若发生异常,则事务回滚 try { con.rollback(); } catch (SQLException e1) { // TODO Auto-generated catch block e1.printStackTrace(); } e.printStackTrace(); }finally { try { if(rs!=null){ rs.close(); } } catch (SQLException e) { e.printStackTrace(); } rs=null; try { if(statement!=null){ statement.close(); } } catch (SQLException e) { e.printStackTrace(); } statement=null; try { if(con!=null){ con.close(); } } catch (SQLException e) { e.printStackTrace(); } con=null; } } }

5. 事务的4大特性:原子性、一致性、隔离性和持续性

6. 数据库事务隔离设置:有四个隔离级别,分别是

MySQL数据库中可通过以下命令语句设置事务隔离级别(默认级别为repeatable read)

7. JDBC代码中设置事务隔离级别:四个级别分别对应Connection对象中的四个静态变量

import java.io.IOException; import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.util.Properties; public class JDBCDemo4 { public static void main(String[] args) { Connection con=null; PreparedStatement statement=null; ResultSet rs=null; try { Properties pro=new Properties(); pro.load(JDBCDemo3.class.getClassLoader().getResourceAsStream("jdbc/db.properties")); String driver=pro.getProperty("driver"); String user=pro.getProperty("user"); String url=pro.getProperty("url"); String password=pro.getProperty("password"); Class.forName(driver); con=DriverManager.getConnection(url, user, password); String id="1"; //String sql="select * from employee where id=" id; String sql="select * from employee where id=?";//将拼接字符串改为占位符形式 statement=con.prepareStatement(sql);//进行预编译,固定SQL语句格式 //设置占位符处参数的值,填充数据的参数类型为int型,设置在第一个 ? 占位符处,填充数据为2 //对于or、=等数据库关键字是不被识别的,也是会报错的,无法在这里设置字符串类型的数据,只能是int值 statement.setInt(1,2); rs=statement.executeQuery(); while(rs.next()){ System.out.println(rs.getInt("id")); System.out.println(rs.getString(2)); System.out.println(rs.getFloat("salary")); System.out.println(); } } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (SQLException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); }finally { try { if(rs!=null){ rs.close(); } } catch (SQLException e) { e.printStackTrace(); } rs=null; try { if(statement!=null){ statement.close(); } } catch (SQLException e) { e.printStackTrace(); } statement=null; try { if(con!=null){ con.close(); } } catch (SQLException e) { e.printStackTrace(); } con=null; } } }

4. 数据库连接池技术

1. 在上面的jdbc代码,都是简单的实现代码,在代码中每开启一个Connection连接对象,都需要关闭释放,而获取和销毁连接操作都会消耗一些时间,而当有大量的开启关闭Connection动作时,就会使性能降低,效率低下,而且可能会造成内存溢出,而使用连接池技术就可以很好的避免这个问题。

2. 连接池技术:连接池技术类似于线程池,提前创建多个连接对象并放在连接池(也就是内存中,从内存取肯定比创建快)中,并且使用完后也不需要关闭销毁,当需要使用时就从连接池中获取,使用完后归还即可。

3. 连接池配置参数:

有默认值,但一般需要根据需求和条件来配置性能最高的参数

无默认值,必须配置的参数:

4. 数据库连接池中利用装饰者模式增强的Connection对象:从数据库连接池中获取到的Connection对象并不是普通的由数据库厂商实现的Connection实现类的对象,而是将由数据库厂商实现的Connection实现类增强,将Connection对象方法中的close方法修改为不销毁连接,而是返还给数据库连接池。演示简单原理如下

//首先是sun公司提供的java.sql.Connection接口 //然后是数据库厂商实现sun公司提供的java.sql.Connection接口的实现类,以MySQL为例是com.mysql.jdbc.Connection //然后是数据库连接池中利用装饰者模式实现的com.mysql.jdbc.Connection类的增强类 /** * @ClassName:JDBCDemo7 * @Description:自定义数据库连接池 */ public class MyDataSource implements Connection{ public Connection conn;//该Connection对象指向的是一个由数据库厂商实现的Connection类 public List<Connection> list;//该集合表示数据库连接池中维护的Connection对象集合 //该构造方法会由数据库连接池来执行,当执行getConnection()方法时就会执行该方法并返回这个增强的Connection对象, //并传入对应参数,Connection conn参数就是数据库连接池中创建的com.mysql.jdbc.Connection对象 public MyDataSource(Connection conn,List<Connection> list){ this.conn=conn; this.list=list; } // 增强该方法,或者说修改该方法,不销毁连接对象,而是改为归还连接对象 public void close() throws SQLException { list.add(conn); } //还有其他许多要实现的方法,但都可以使用conn的相对应的方法,主要是close方法 }

所以,对于那些数据连接池的开源项目,其中获取的Connection对象的close方法都是返还连接,而不是销毁连接,所以只需使用该方法即可。

5. 常用的几个数据库开源项目:dbcp连接池、c3p0连接池、druid连接池(阿里提供,性能最好的),使用方式为

import java.io.IOException; import java.sql.Connection; import java.sql.SQLException; import java.util.Properties; import org.apache.commons.dbcp.BasicDataSource; /** * @ClassName:JDBCDemo7 * @Description:使用DBCP连接池,建立一个工厂类获取Connection对象 */ public class JDBCDemo7 { private static BasicDataSource bds; private static String driver; private static String user; private static String url; private static String password; private static String initsize; private static String maxsize; static{ //通过配置文件来读取数据库连接池的相应配置 Properties p=new Properties(); try { p.load(test1.class.getClassLoader().getResourceAsStream("jdbc/db.properties")); driver=p.getProperty("driver"); user=p.getProperty("user"); url=p.getProperty("url"); password=p.getProperty("password"); initsize=p.getProperty("initsize"); maxsize=p.getProperty("maxsize"); bds=new BasicDataSource(); bds.setDriverClassName(driver); bds.setUrl(url); bds.setPassword(password); bds.setUsername(user); bds.setInitialSize(Integer.parseInt(initsize)); bds.setMaxActive(Integer.parseInt(maxsize)); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); throw new RuntimeException("配置文件读取失败",e); } } public Connection getConnection() throws SQLException{ return bds.getConnection(); } public void close(Connection con){ if(con!=null) try { con.close(); } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); throw new RuntimeException("连接关闭异常",e); } } public static void main(String[] args) { JDBCDemo7 t=new JDBCDemo7(); Connection con=null; try { con=t.getConnection(); System.out.println(con.toString()); } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); }finally { try { con.close(); } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } }

5. JDBC查询数据分页

1. 简介:在开发中,常常会将从数据库中查询到的数据,分为多个部分,在客户端使用多个页面来向用户展示,比如百度搜索出来的结果。分页分为物理分页和逻辑分页,

jdbc怎么引入项目,jdbc连接步骤(2)

栏目热文

文档排行

本站推荐

Copyright © 2018 - 2021 www.yd166.com., All Rights Reserved.