【JavaWeb】17 JDBC——连接数据库

本文详细介绍了JavaWeb中使用JDBC连接数据库的步骤,包括增删改查操作、JDBC代码规范、ResultSet处理、PreparedStatement的使用以及事务处理。还涉及到了事务的隔离级别、数据库连接池的概念和装饰者模式的应用。同时,文章提到了c3p0连接池的配置以及JdbcUtils工具类的改进,以支持事务管理和多线程并发。
摘要由CSDN通过智能技术生成


JDBC中都是接口,MySQL驱动实现接口后能连接MySQL数据库,Oracle驱动实现接口后能连接Oracle数据库。

得到连接的四步

  • 需要引入包的MySQL连接器-java的。-驱动-加载驱动类:的Class.forName(“类名”); -指定网址,用户名,密码-使用的DriverManager类来获得连接对象所有的java.sql中。驱动程序实现类,都提供了静态块,块内部的代码就是把自己注册到DriverManager jabc4.0后不再需要Class.forName的步骤(会自动扫描文件),但仍需要写,以便版本兼容性
public Demo1 {
   
String driverClassName="com.mysql.jdbc.Driver";
String url="jdbc:mysql://localhost:3306";
String username="root";
String password="1234";
Class.forName(driverClassName); //加载驱动类Connection con = DriverManager。getConnection(网址,用户名,密码); }

如果引发异常,检查:1.三个参数正确正确 2.数据库服务器是否开启

增删改查增加/修改

  1. 通过Connection对象创建语句(语句发送器,向数据库发送SQL语句)
  2. 调用它的 int executeUpdate(String sql),可以发送DML,DDL(返回值是被植入的行数)
public class Demo2{
   
public void fun1 throws ClassNotFoundException,SQLExeption(){
   
	String driverClassName="com.mysql.jdbc.Driver";
	String url="jdbc:mysql://localhost:3306/mydb3";
	String username="root";
	String password="1234";
	Class.forName(driverClassName);
	Connection con=DriverManager.getConnection(url,username,password);
	Statement stmt=con.createStatement();
	String sql="INSERT INT stu VALUES('0003','ZhangSan',30,'male')";
	int r=stmt.executeUpdate(sql);
	System.out.println(r);
}
}

查询

  1. 得到Connection
  2. 得到Statement,发送select语句
  3. 对查询返回的“表格”进行解析
String driverClassName="com.mysql.jdbc.Driver";
String url="jdbc:mysql://localhost:3306/exam";
String username="root";
String password="1234";
Class.forName(driverClassName);
Connection con=DriverManager.getConnection(url,username,password);
Statement stmt=con.createStatement();
//ResultSet相当于一个光标(包含为null的一头一尾)
ResultSet rs=stmt.executeQuery("select * from exp");
while(rs.next()){
   
	int num=rs.getInt(1);
	String name=rs.getString("name");
	Double salary=rs.getDouble("sal");
	System.out.println(num+" "+name+" "+salary);
}
//关闭资源(倒关)
rs.close();
stmt.close();
con.close();

JDBC代码规范化

public void fun3(){
   
//定义引用
Connection con=null;
Statement stmt=null;
ResultSet=rs;
try{
   
	String driverClassName="com.mysql.jdbc.Driver";
	String url="jdbc:mysql://localhost:3306/exam";
	String username="root";
	String password="123";
	Class.forName(driverClassName);
	//实例化
	con=DriverManager.getConnection(url,username,password);
	stmt=con.createStatement();
	rs=Setstmt.executeQuery("select * from emp");
	//遍历rs
	while(rs.next()){
   
		System.out.println(rs.getObject(1)+" "+rs.getString("name")+" "+rs.getDouble("salary"));
}catch(Exception e){
   
	throw new RuntimeException(e);
}finally{
   
	if(rs!=null)rs.close;
	if(stmt!=null)stmt.close;
	if(con!=nulll)con.close;
}

Statement最为重要的方法是:

  • int executeUpdate(String sql):执行更新操作,即执行insert、update、delete语句,其实这个方法也可以执行create table、alter table,以及drop table等语句,但我们很少会使用JDBC来执行这些语句;
  • ResultSet executeQuery(String sql):执行查询操作,执行查询操作会返回ResultSet,即结果集。
  • boolean execute():用来执行增、删、改、查所有SQL语句。该方法返回的是boolean类型,表示SQL语句是否有结果集。
    之后可用int getUpdateCount()来获取insert、update、delete语句所影响的行数。
    如果使用execute()方法执行的是查询语句,那么还要调用ResultSet getResultSet()来获取select语句的查询结果。

ResultSet

滚动结果集

  • void beforeFirst():把光标放到第一行的前面,这也是光标默认的位置;
    void afterLast():把光标放到最后一行的后面;
  • boolean first():把光标放到第一行的位置上,返回值表示调控光标是否成功;
    boolean last():把光标放到最后一行的位置上;
  • boolean isBeforeFirst():当前光标位置是否在第一行前面;
    boolean isAfterLast():当前光标位置是否在最后一行的后面;
    boolean isFirst():当前光标位置是否在第一行上;
    boolean isLast():当前光标位置是否在最后一行上;
  • boolean previous():把光标向上挪一行;
    boolean next():把光标向下挪一行;
    boolean relative(int row):相对位移,当row为正数时,表示向下移动row行,为负数时表示向上移动row行;
    boolean absolute(int row):绝对位移,把光标移动到指定的行上;(行数从1开始)
    int getRow():返回当前光标所在行;
  • 获取结果集元数据
    ResultSetMetaData getMetaData():得到元数据
    int getColumnCount():获取指定集列数
    String getColumnName(int colindex):获取指定列的列名
rs.last();
System.out.println(rs.getRow());//获得行数
System.out.println(rs.getMetaData().getColumnCount());//获得列数

三个特性
是否可滚动
是否敏感
是否可更新

  • con.createStatement() 生成的结果集:不可滚动,不敏感,不可更新
  • con.createStatement(int,int)
    第一个参数:
    ResultSet.TYPE_FORWARD_ONLY:不滚动结果集
    ResultSet.TYPE_SCROLL_INSENSITIVE:滚动结果集,但结果集数据不会再跟随数据库而变化
    ResultSet.TYPE_SCROLL_SENSITIVE:滚动结果集,但结果集数据不会再跟随数据库而变化(没有数据库驱动支持它,不使用)
    第二个参数:
    CONCUR_READ_ONLY:结果集是只读的,不能通过修改结果集而反向影响数据库;
    CONCUR_UPDATABLE:结果集是可更新的,对结果集的更新可以反向影响数据库。(不使用)
  • mysql中默认为可滚动,因此con.createStatement()生成的结果集可以滚动

PreparedStatement

是Statement的子接口
优点:
防SQL攻击
提高代码的可读性、可维护性
提高效率

/*
	使用username和password去查询数据
*/
public boolean login(String username,String password){
   
	String driverClassName="com.mysql.jdbc.Driver";
	String url="jdbc:mysql://localhost:3306/mydb3";
	String mysqlUsername="root";
	String mysqlPassword="1234";
	Class.forName(driverClassName);
	Connection con=DriverManager.getConnection(url,mysqlUsername,mysqlPassword);
	Statement stmt=con.createStatement();
	String sql="select * from t_user where username='"+username+"'and password='"+password+"'";
	ResultSet rs=stmt.executeQuery(sql);
	return rs.next;
}
//SQL攻击
public void fun1() throws Exception{
   
	String username="a' or 'a'='a'";
	String password="a' or 'a'='a'";
	System.out,println(login(username,password));
	//select * from t_user where username='a' or 'a'='a' and password='a' or 'a'='a'
}

PreparedStatement用法

  1. 给出SQL模板:所有参数用?替代
  2. 调用 Connection 的 PreparedStatement(String sql)
  3. 调用 setXxx() 系列方法给?赋值
  4. 调用 executeUpdate()executeQuery()
/*
	使用PreparedStatement
*/
public boolean login(String username,String password){
   
	String driverClassName="com.mysql.jdbc.Driver";
	String url="jdbc:mysql://localhost:3306/mydb3";
	String mysqlUsername="root";
	String mysqlPassword="1234";
	Class.forName(driverClassName);
	Connection con=DriverManager.getConnection(url,mysqlUsername,mysqlPassword);
	/
	String sql="select * from t_user where username=? and password=?";
	PreparedStatement pstmt=con.prepareStatement(sql);
	pstmt.setString(1,username);//给第一个问号赋值,值为username
	pstmt.setString(2,password);//给第二个问号赋值,password
	pstmt.executeQuery();
}

预处理的原理

  • 服务器的工作:
    校验SQL语句的语法
    编译:一个与函数类似的东西
    执行:调用函数
  • PreparedStatement:
    前提:数据库支持预处理(几乎都支持)
    每个pstmt都与一个SQL模板绑定在一起,先把SQL模板给数据库,数据库先进行校验,再进行编译。执行时只传递参数即可。
    若二次执行时,就不用再次校验语法,也不用再次编译,直接执行。
  • MySQL的预编译功能默认是关闭的。需要通过参数打开。

JdbcUtils 小工具

public class JdbcUtils{
   
public static Connection getConnection() throws 
IOException,ClassNotFoundException,SQLException{
   
	InputStream in=JdbcUtils.class.getClassLoader().getResourseAsStream("dbconfig.properties")

面向接口编程

  1. 把 UserDao 修改为接口,原来的类名 UserDo 修改为 UserDaolmple
  2. 修改 UserService 中对 UserDao 的实例化,使用工厂来创建实例:private UserDao userDao=DaoFactory.getUserDao();
  3. 创建 DaoFactory 并创建getUserDao方法
public class DaoFactory{
   
private static Properties props=null;
static{
   
	try{
   
		InputStream in=
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值