JDBC
JDBC是个接口,需要对应的实现类也就是对应的驱动。
还记不记得的接口是都是抽象的?使用时得实例化对象,而驱动恰恰就是一个对应jdbc接口的全部实现类。这样一来,我们就能使用JDBC里面的抽象类了!!
那数据库连接的底层原理是什么?其实很简单,就是之前讲的IO流与反射机制,通过IO流找到对应的文件位置,反射机制在创建类加载对象,从而实现数据的增删改.....
OK,原理解释清楚了,接下来就介绍一下JAVA!中如何使用JDBC,一共有6步哦!(必须记住!)
4.JDBC编程六部(需要背会)
第一步:注册驱动(作用:告诉java程序连接的是哪个品牌的数据库)
第二种常用,因为字符串可以写到配置文件中
第二步:获取连接(表示jvm的进程和数据库进程之间的通道打开,重量级的,使用完之后一定要关闭进程!!)
对url的解释:
第三步:获取数据库操作对象(专门执行sql语句的对象)
第四步:执行sql语句(DQL,DML...)
//executeupdate是专门执行DML(增删改),executequery是专门执行DQl(查)语句的方法
第五步:处理查询结果集(只有当第四步执行的是select语句时,才有第五步处理查询结果集。)
查询本质:使用while(rs.next)的形式来迭代,当rs.next执行后所指位置向下一行,一开始在行最上边,当所指行有数的时候返回TRUE,否则false,结束循环。
这个很重要,select查询展现出来的是另一张表,不是数据库中的表
//也可以使用getint等等,这样取出来的数可以直接参与运算
//String型
//指定类型
//下标
//以列名,sql语句中的类名
第六步:释放资源(使用完资源之后一定要关闭资源,java与数据库之间属于进程间的通信,开启之后一定要记得关闭!)
记得验证是否输出完毕!!!
if(!=null)
trycatch包围.close,
执行DML
import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; import java.sql.Statement; public class Main { public static void main(String[] args) { Connection con=null;//获取连接 Statement statement=null;//执行sql try { //1.注册驱动 DriverManager.registerDriver(new com.mysql.cj.jdbc.Driver()); String url="jdbc:mysql://127.0.0.1:3306/lengbonode"; String user="root"; String password="wjn12345"; //2.获取对象 con=DriverManager.getConnection( url,user,password);//静态引用使用类名 System.out.println("数据库连接成功!是"+con); //3.获取数据库连接(Statement是专门执行sql语句的) statement=con.createStatement(); //4.执行sql String sql="update dept set dname='销售部',loc='天津' where deptno =20"; //这个是专门执行DML语句的(insert,update,delete) //int返回值是影响数据库中的记录条数 int count=statement.executeUpdate(sql); //5.处理查询结果集 System.out.println(count==1?"保存成功!!":"保存失败!"); } catch (SQLException e) { throw new RuntimeException(e); }finally { //6.释放资源 //为了保证资源一定释放,在finally语句块中关闭资源 //并且要遵循从小到大依次关闭 //分别对其trycatch if (con != null) { try { con.close(); } catch (SQLException e) { throw new RuntimeException(e); } } if (statement != null) { try { statement.close(); } catch (SQLException e) { throw new RuntimeException(e); } } } } }
//执行DQL
import java.sql.*; import java.util.ResourceBundle; public class Main { public static void main(String[] args) { ResourceBundle bundle=ResourceBundle.getBundle("jdbc"); String driver=bundle.getString("driver"); String url=bundle.getString("url"); String user=bundle.getString("user"); String password=bundle.getString("password"); Connection con=null; Statement statement=null; ResultSet resultSet=null; try { //1.注册驱动 //或者 Class.forName("com.mysql.cj.jdbc.Driver"); //2.获取对象 con=DriverManager.getConnection( url,user,password);//静态引用使用类名 System.out.println("数据库连接成功!是"+con); //3.获取数据库连接(Statement是专门执行sql语句的) statement=con.createStatement(); //4.执行sql String sql="select ename,sal from emp"; //查询语句用结果集,增删改用数量 /* int executeupdate(insert,update,delete) Resultset executequery(select) */ resultSet=statement.executeQuery(sql); //5.处理查询结果集 while (resultSet.next()) {
//getString()中数字代表列,结果集中的.next光标代表行
String ename =resultSet.getString(1); String sal =resultSet.getString(2); System.out.println(ename+","+sal); } } catch (SQLException e) { throw new RuntimeException(e); } catch (ClassNotFoundException e) { throw new RuntimeException(e); } finally { //6.释放资源 //为了保证资源一定释放,在finally语句块中关闭资源 //并且要遵循从小到大依次关闭 //分别对其trycatch if (resultSet != null) { try { resultSet.close(); } catch (SQLException e) { throw new RuntimeException(e); } } if (statement != null) { try { statement.close(); } catch (SQLException e) { throw new RuntimeException(e); } } if (con != null) { try { con.close(); } catch (SQLException e) { throw new RuntimeException(e); } } } } }
like模糊查询
import java.sql.*; public class JDBCStatementText01 { public static void main(String[] args) { Connection c=null; PreparedStatement ps=null; ResultSet rs=null; try { //注册驱动 Class.forName("com.mysql.cj.jdbc.Driver"); //获取连接 c= DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/lengbonode","root","wjn12345"); c.setAutoCommit(false);//开启手动提交 //获取预处理数据库对象 //直接like ?就行,语句自己写,——是位置,%是不限 String sql="select ename from emp where ename like ?"; ps=c.prepareStatement(sql); ps.setString(1,"_A%"); rs=ps.executeQuery(); while (rs.next()) { System.out.println(rs.getString("ename")); } c.commit();//提交事务 } catch (ClassNotFoundException | SQLException e) { throw new RuntimeException(e); }finally { if (rs != null) { try { rs.close(); } catch (SQLException e) { throw new RuntimeException(e); } } try { if (ps != null) { ps.close(); } } catch (SQLException e) { throw new RuntimeException(e); } try { if (c != null) { c.close(); } } catch (SQLException e) { throw new RuntimeException(e); } } } }
sql注入:是Statement的问题,,使用preparedstatement就没问题了
PreparedStataement是预编译的statement,它是直接将sql框架提交,所以即使输入了,也不会执行,ps的父类是statement
代码跟statement略有不同,主要在获取预编译的数据库操作对象上,?自动加‘’
import java.sql.*; import java.util.HashMap; import java.util.Map; import java.util.ResourceBundle; import java.util.Scanner; public class Main { public static void main(String[] args) { Map<String,String> userInfo=initUI(); boolean userSuccess=login(userInfo); System.out.println(userSuccess?"登录成功!":"登录失败!"); } private static boolean login(Map<String, String> userInfo) { boolean userSuccess=false; String userName=userInfo.get("userName"); String userPassward=userInfo.get("userPassward"); Connection connection=null; PreparedStatement ps=null; ResultSet rs=null; try { //注册驱动 Class.forName("com.mysql.cj.jdbc.Driver"); //获取连接 connection= DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/lengbonode","root","wjn12345"); //获取预编译的数据库操作对象 //sql语句框架,?是占位符,以后只能传值,住:占位符不能被’’括起来。 String sql="select * from t_user where userName= ? and userPassward= ?"; ps=connection.prepareStatement(sql); //给占位符传值 ps.setString(1,userName); ps.setString(2,userPassward); //执行sql rs=ps.executeQuery(); //处理结果集 if (rs.next()) { userSuccess=true; } } catch (ClassNotFoundException | SQLException e) { throw new RuntimeException(e); }//释放资源 finally { if (rs != null) { try { rs.close(); } catch (SQLException e) { throw new RuntimeException(e); } } if (ps != null) { try { ps.close(); } catch (SQLException e) { throw new RuntimeException(e); } } if (connection != null) { try { connection.close(); } catch (SQLException e) { throw new RuntimeException(e); } } } return userSuccess; } private static Map<String, String> initUI() { Scanner scanner=new Scanner(System.in); System.out.println("用户名:"); String userName=scanner.nextLine(); System.out.println("密码:"); String userPassward=scanner.nextLine(); Map<String,String> userInfo=new HashMap<>(); userInfo.put("userName",userName); userInfo.put("userPassward",userPassward); return userInfo; } }
行级锁(悲观锁与乐观锁)sql语句后+for update
当事务修改数据后版本号会变
悲观锁:事务不允许并发,必须排队执行。
乐观锁:事务允许并发,只不过需要看版本号,版本号与之前不一样回滚事务。