一、CRUD(增删改查)
C:增加Create R查询(Retrieve) U更新(Update) D删除(Delete)
在JDBC中,增加,删除,修改,操作都基本一样,只是传递不同SQL语句,最后使用execute()方法执行SQL语句
查询,使用executeQuery()方法执行SQL语句。
1、使用Statement来执行SQL语句

package jdbc; import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; import java.sql.Statement; public class TestJDBC{ public static void main(String[] args){ try{ Class.forName("com.mysql.jdbc.Driver");//加载数据库驱动 }catch(ClassNotFoundException e){ e.printStackTrace(); } try( Connection c=DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/test?characterEncoding=UTF-8","root","root");//建立连接数据库 Statement s=c.createStatement(); ){ String strSql="delete from demo where id=6"; //执行删除语句 s.execute(strSql); String sql="select * from user where name='"+name+"' and password='"+password+"'"; //执行查询语句,并把结果集返回给ResultSet ResultSet rs=s.executeQuery(sql); if(rs.next()){//从结果集获取到账号密码 System.out.println("账号密码正确!"); } else{ System.out.println("账号密码错误!"); } }catch(SQLException e){ e.printStackTrace(); } } }
2、使用PreparedStatement来执行SQL语句(采用预编译,性能比Statement快,能防止SQL注入)
区别:能够设定参数,指定相应的值,而不是Statement那样使用字符串拼接

package jdbc; import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; import java.sql.Statement; public class TestJDBC{ public static void main(String[] args){ try{ Class.forName("com.mysql.jdbc.Driver");//加载数据库驱动 }catch(ClassNotFoundException e){ e.printStackTrace(); } String strSql="insert into hero values(null,?,?,?)"; try( Connection c=DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/test?characterEncoding=UTF-8","root","root");//建立连接数据库 PreparedStatement ps=c.prepareStatement(strSql); ){ //设置strSql问号的参数 ps.setString(1,"temo"); ps.setFloat(2,22.0f); ps.setInt(3,59); //执行sql ps.execute(); }catch(SQLException e){ e.printStackTrace(); } } }
二、数据库连接池
连接池原理
-
- 有多个线程,每个线程都需要连接数据库执行SQL语句,那么每个线程都会创建数据库连接,并在使用完之后关闭,由于创建连接和关闭连接过程是比较消耗时间的,多线程的时候,系统就会很卡顿,而一个数据库同时支持连接总数也是有限的,如果多线程并发量很大,那么数据库连接的总数就会被消耗完,那么后续线程连接数据库就会失败。
- 数据库连接池,在使用之前,就会创建好一定数量的连接,如果有任何线程需要连接,就会在连接池中借用,而不是自己创建。使用完毕后,又把这个连接归还给连接池供下一次使用或者其他线程使用。
- 加入发成多线程并发情况,连接池里的连接被用光了,那么其他线程就会等待,知道有连接被归还回来,再继续使用整个过程,这些连接都不会被关闭,而是不断的被循环使用,从而节约了启动和关闭连接的时间。

package jdbc; import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; import java.util.ArrayList; import java.util.List; public class ConnectionPool { List<Connection> cs = new ArrayList<Connection>(); int size; public ConnectionPool(int size) { this.size = size; init(); } public void init() { //这里恰恰不能使用try-with-resource的方式,因为这些连接都需要是"活"的,不要被自动关闭了 try { Class.forName("com.mysql.jdbc.Driver"); for (int i = 0; i < size; i++) { Connection c = DriverManager .getConnection("jdbc:mysql://127.0.0.1:3306/how2java?characterEncoding=UTF-8", "root", "admin"); cs.add(c); } } catch (ClassNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } } public synchronized Connection getConnection() { while (cs.isEmpty()) { try { this.wait(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } Connection c = cs.remove(0); return c; } public synchronized void returnConnection(Connection c) { cs.add(c); this.notifyAll(); } }