JDBC,通过java来操作数据库 https://jsd.onmicrosoft.cn/gh/LuckyTiger12138/images//img/202311121855703.png
JDBC概述 JDBC API允许用户访问任何形式的表格数据,尤其是存储在关系数据库中的数据,JDBC其实是一套接口,定义了java操作数据库的规范,各家数据库厂商,想要使用java语言,跟自家数据库建立连接,需要自己去实现驱动,数据库厂商写的这套实现类称为数据库驱动。
操作流程
导入数据库厂商写的驱动,也就是jar包
1 2 3 4 5 6 7 8 9 10 <dependency > <groupId > mysql</groupId > <artifactId > mysql-connector-java</artifactId > <version > 5.1.41</version > </dependency > <dependency > <groupId > org.apache.commons</groupId > <artifactId > commons-dbcp2</artifactId > <version > 2.0.1</version > </dependency >
加载驱动,drive文件的全路径
建立连接
.获取操作对象
编写SQL语句
执行SQL语句
释放资源
往数据库中插入数据 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 public class 连接数据库 {public static void main (String[] args) throws ClassNotFoundException, SQLException {Class.forName("com.mysql.jdbc.Driver" ); String url="jdbc:mysql://localhost:3306/mydb" ; String username="root" ; String password="123456" ; Connection conn = DriverManager.getConnection(url, username, password);Statement statement = conn.createStatement();String str="insert into test11(nam,age) values('cc',40)" ; statement.executeUpdate(str); conn.close(); statement.close();}}
从数据库中读取数据 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 public class 读取数据库 {public static void main (String[] args) throws Exception {Class.forName("com.mysql.jdbc.Driver" ); String url=("jdbc:mysql://localhost:3306/mydb" ); String username="root" ; String password="123456" ; Connection conn = DriverManager.getConnection(url, username, password);Statement statement = conn.createStatement();String str="select * from test11" ; ResultSet resultSet = statement.executeQuery(str);ArrayList<Object> list = new ArrayList <>(); while (resultSet.next()){ int anInt = resultSet.getInt(1 ); String string = resultSet.getString(2 ); int anInt1 = resultSet.getInt(3 ); System.out.println(anInt+" " +string+" " +anInt1); } System.out.println(list); }}
SQL注入 如果你通过网页获取用户输入的数据并将其插入一个MySQL数据库,那么就有可能发生SQL注入安全的问题。所谓SQL注入,就是通过SQL命令插入到Web表单递交或输入域名或页面请求的查询字符串,最终达到欺骗服务器执行恶意的SQL命令。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 public class LoginDemo {public static void main (String[] args) throws Exception {String username="1' or '1'='1" ; String password="1' or '1'='1" ; Class.forName("com.mysql.jdbc.Driver" ); Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/mydb" , "root" , "123456" );Statement statement = conn.createStatement();String sql="select * from users where username='" +username+"' and password='" +password+"'" ; ResultSet resultSet = statement.executeQuery(sql);boolean b = resultSet.next();if (b){ System.out.println("登录成功" ); }else { System.out.println("登录失败" );}}}
使用PreparedStatement预编译操作对象 来防止SQL注入 SQL 语句被预编译并存储在 PreparedStatement
对象中。然后可以使用此对象多次高效地执行该语句。
1 2 3 4 5 6 使用步骤: 1. conn.prepareStatement(sql);2. sql语句中的字段的值用?问号占位3. 给sql语句中的问号赋值
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 public class LoginDemo2 {public static void main (String[] args) throws Exception {String username="'1' or '1'='1'" ; String password="'1' or '1'='1'" ; Class.forName("com.mysql.jdbc.Driver" ); Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/mydb" , "root" , "123456" );String sql = "select * from users where username=? and password=?" ;PreparedStatement preparedStatement = conn.prepareStatement(sql);preparedStatement.setString(1 ,username); preparedStatement.setString(2 ,password); ResultSet resultSet = preparedStatement.executeQuery(); boolean b = resultSet.next();if (b){ System.out.println("登录成功" ); }else { System.out.println("登录失败" );}}}
使用ResourceBundle来读取配置文件 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 public class MyTest {public static void main (String[] args) throws IOException {ResourceBundle bundle = ResourceBundle.getBundle("jdbcProperties" );String className = bundle.getString("className" );String url = bundle.getString("url" );String username = bundle.getString("username" );String password = bundle.getString("password" );System.out.println(className); System.out.println(url); System.out.println(username); System.out.println(password); InputStream in = MyTest.class.getClassLoader().getResourceAsStream("jdbcProperties.properties" );System.out.println("-----------------------------------------------" ); BufferedReader bufferedReader = new BufferedReader (new InputStreamReader (in));String[] split = bufferedReader.readLine().split("=" ); System.out.println(split[0 ]); System.out.println(split[1 ]);}}
连接池 数据库连接 — 执行完毕 — 释放
连接 — 释放 十分浪费系统费资源
池化技术:准备一些预先资源,过来就连接预先准备好的
最小连接数 10
最大连接数 15
等待超时 : 100ms
编写连接池,实现一个接口 DataSourse
简介 由于建立数据库连接是一种非常耗时,耗费资源的行为,所以通过连接池预先同数据库建立一些连接,放在内存中,应用程序需要建立数据库连接时直接到连接池中申请一个就行,使用完毕再归还到连接池中,现在市面上常见的连接池有三种,分别是 DBCP连接池,C3P0连接池,阿里Druid连接池
DBCP 需要用到的jar包
commons-dbcp 1.4
1 2 3 4 5 6 <dependency > <groupId > commons-dbcp</groupId > <artifactId > commons-dbcp</artifactId > <version > 1.4</version > </dependency >
commons-pool 1.6
1 2 3 4 5 6 <dependency > <groupId > commons-pool</groupId > <artifactId > commons-pool</artifactId > <version > 1.6</version > </dependency >
新建dbcpconfig.properties文件 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 driverClassName =com.mysql.jdbc.Driver url =jdbc:mysql://localhost:3306/school?useUnicode=true&characterEncoding=utf8&useSSL=true username =root password =123456 initialSize =10 maxActive =20 maxIdle =20 minIdle =5 maxWait =60000 connectionPropertier =useUnicode=true&characterEncoding=UTF8 defaultAutoCommit =true defaultReadOnly =false defaultTransactionIsolation = READ_UNCOMMITTED
ConnectionFactory类 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 private static DataSource dataSource=null ;static { try { InputStream in = ConnectionFactory.class.getClassLoader().getResourceAsStream("dbcpconfig.properties" ); System.out.println(in==null ); System.out.println(in); Properties pror = new Properties (); pror.load(in); dataSource = BasicDataSourceFactory.createDataSource(pror); } catch (Exception e) { e.printStackTrace(); } } private ConnectionFactory () { } public static Connection getConnection () throws SQLException { return dataSource.getConnection(); } public static void closeResourse (ResultSet rs, PreparedStatement pstm, Connection conn) { try { if (rs != null ) { rs.close(); } if (pstm != null ) { pstm.close(); } if (conn != null ) { conn.close(); } } catch (Exception e) { e.printStackTrace();}}
测试 CommonDao类 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 public static void main (String[] args) { PreparedStatement psmt = null ; ResultSet rs = null ; Connection conn = null ; try { String sql = "INSERT INTO school.student (id, name, age) VALUE (?,?,?)" ; conn = ConnectionFactory.getConnection(); psmt = conn.prepareStatement(sql); psmt.setInt(1 ,5 ); psmt.setString(2 ,"zhangsan" ); psmt.setInt(3 ,50 ); int i = psmt.executeUpdate(); if (i>0 ){ System.out.println("success" ); } else { System.out.println("error" );}} catch (SQLException e){ e.printStackTrace();} finally { ConnectionFactory.closeResourse(rs, psmt, conn); }}
c3p0 需要的jar包
com.mchange 0.9.5.5
1 2 3 4 5 <dependency > <groupId > com.mchange</groupId > <artifactId > c3p0</artifactId > <version > 0.9.5.5</version > </dependency >
mchange-commons 0.2.19
1 2 3 4 5 <dependency > <groupId > com.mchange</groupId > <artifactId > mchange-commons-java</artifactId > <version > 0.2.19</version > </dependency >
新建c3p0-config.xml文件 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 <?xml version="1.0" encoding="UTF-8" ?> <c3p0-config > <default-config > <property name ="driverClass" > com.mysql.jdbc.Driver</property > <property name ="jdbcUrl" > jdbc:mysql://localhost:3306/school</property > <property name ="user" > root</property > <property name ="password" > 123456</property > <property name ="acquireIncrement" > 5</property > <property name ="initialPoolSize" > 10</property > <property name ="minPoolSize" > 5</property > <property name ="maxPoolSize" > 20</property > <property name ="maxStatements" > 0</property > <property name ="maxStatementsPerConnection" > 5</property > </default-config > <named-config name ="MySQL" > <property name ="driverClass" > com.mysql.jdbc.Driver</property > <property name ="jdbcUrl" > jdbc:mysql://localhost:3306/school</property > <property name ="user" > root</property > <property name ="password" > 123456</property > <property name ="acquireIncrement" > 5</property > <property name ="initialPoolSize" > 10</property > <property name ="minPoolSize" > 5</property > <property name ="maxPoolSize" > 20</property > <property name ="maxStatements" > 0</property > <property name ="maxStatementsPerConnection" > 5</property > </named-config > </c3p0-config >
ConnectionFactory类 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 private static DataSource dataSource=null ;static {try { dataSource = new ComboPooledDataSource ("MySQL" ); } catch (Exception e) { e.printStackTrace(); }} private ConnectionFactory () {}public static Connection getConnection () throws SQLException { return dataSource.getConnection();} public static void closeResourse (ResultSet rs, PreparedStatement pstm, Connection conn) {try { if (rs != null ) { rs.close(); } if (pstm != null ) { pstm.close(); } if (conn != null ) { conn.close(); } } catch (Exception e) { e.printStackTrace();}}
测试 CommonDao类 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 public static void main (String[] args) {PreparedStatement psmt = null ;ResultSet rs = null ;Connection conn = null ;try { String sql = "INSERT INTO school.student (id, name, age) VALUE (?,?,?)" ; conn = ConnectionFactory.getConnection(); psmt = conn.prepareStatement(sql); psmt.setInt(1 ,7 ); psmt.setString(2 ,"zhangsan" ); psmt.setInt(3 ,50 ); int i = psmt.executeUpdate(); if (i>0 ){ System.out.println("success" ); } else { System.out.println("error" ); } } catch (SQLException e) { e.printStackTrace(); } finally { ConnectionFactory.closeResourse(rs, psmt, conn); } }
注意
c3p0-config.xml文件、dbcpconfig.properties文件 eclipse放在src的根目录下,idea放在resources目录下即可。