03jdbc常用接口--DriverManeger,Connection,PreparedStatement,ResultSet接口浅析

在之前的博文中简单提到了jdbc规范主要有4个核心接口

  1. DriverManager:用于注册驱动并创建符合该驱动的数据库的连接
  2. Connection: 表示与数据库创建的连接对象,即一个connection对应着一个会话,相当于在mysql workbench(数据库窗口化工具)中打开了一个连接。
  3. Statement: 操作数据库sql语句的对象,有个两个实现类:Statement和PreparedStatement(常用)。
  4. ResultSet: 从数据库中查询的结果集。

下面简单分析下这几个接口

1 注册驱动

先看下mysql.Driver中源码,很简洁,一个静态代码块,一个创建驱动的方法

Class.forName(String className)将对应的驱动类加载到内存中,然后执行内存中的static静态代码段,代码段中,会创建一个驱动Driver的实例,放入DriverManager中,供DriverManager使用

注意mysql8.0驱动中className="com.mysql.cj.jdbc.Driver"

public class Driver extends NonRegisteringDriver implements java.sql.Driver {
    // Register ourselves with the DriverManager
       static {
        try {
            java.sql.DriverManager.registerDriver(new Driver());
        } catch (SQLException E) {
            throw new RuntimeException("Can't register driver!");
        }
    }

    /**
     * Construct a new driver and register it with DriverManager
     * @throws SQLException
     *             if a database error occurs.
     */
    public Driver() throws SQLException {
        // Required for Class.forName().newInstance()
    }
}

2 DriverManager接口  

java.sql包下java.sql.DriverManager   DriverManager的主要作用是创建连接

常用方法:

static Connection getConnection(String url);

static Connection getConnection(String url,String user, String password);参数1是数据库连接,mysql8.0版本驱动的url为

"jdbc:mysql://数据库所在机器ip:数据库端口号/数据库名?useSSL=false&serverTimezone=UTC"

第2个参数是用户名,第3个参数是密码,都是字符串类型 

static Connection getConnection(String url,java.util.Properties info);

private static Connection getConnection(String url, java.util.Properties info, Class<?> caller);获取数据库的连接

前3个方法都调用了第4个私有方法创建Connection连接对象,下面是第2个getConnection方法的源码

 @CallerSensitive
    public static Connection getConnection(String url,
        String user, String password) throws SQLException {
        java.util.Properties info = new java.util.Properties();
        if (user != null) {
            info.put("user", user);
        }
        if (password != null) {
            info.put("password", password);
        }

        return (getConnection(url, info, Reflection.getCallerClass()));
    }

其中java.util.Properties类继承自HashTable,是一个跟配置文件相关的类,HashTable类是线程安全的,它和HashMap中的方法类似

Properties类是配置类,将用户名和密码保存到info对象中,再调用第4个getConnection方法,将info作为参数传入该方法中,创建连接对象

 

3 Connection接口

java.sql.Connection  它是与数据库连接会的对象,只有获得特定的数据库连接对象,才可以访问数据库进行数据库操作

常用方法:

void close()关闭Connection连接

Statement createStatement()创建Statement对象

 PreparedStatement  prepareStatement(String sql)创建PreparedStatement对象

 

4 Statement接口

java.sql.Statement,它的作用是操作sql语句,并返回相应结果的对象,好吧,这个接口会有sql注入问题,要认为deprived它,用PreparedStatement接口代替它

常用方法

ResultSet executeQuery(String sql) 执行查询sql语句,返回ResultSet对象,注意参数sql语句不能加分号

int executeUpdate(String sql)执行DML语句,即增,删,改操作,返回int类型,成功返回更新表的行数,失败返回0,注意参数sql语句不能加分号

void close()立即释放此Statement对象的数据库和JDBC资源

boolean excute(String sql) throws SQLException 该方法是执行指定的SQL语句。如果sql语句返回结果,此方法返回true,否则返回false

boolean isClosed() throws SQLException 该方法用来判断Statement对象是否已被关闭

5 PreparedStatement接口

java.sql.PreparedStatement     PreparedStatement是Statement的子接口,不需要动态拼接字符串,使用占位符来代替参数,可以简化拼接sql的过程,可以预防sql注入问题

能够对sql语句进行预编译,预编译后能够提高数据库sql语句执行效率。PreparedStatement 实例包含已编译的 SQL 语句。包含于 PreparedStatement 对象中的 SQL 语句可具有一个或多个 IN 参数。IN参数的值在 SQL 语句创建时未被指定。相反的,该语句为每个 IN 参数保留一个问号(“?”,注意是英文状态)作为占位符。每个问号的值必须在该语句执行之前,通过适当的setXXX 方法来提供。

常用方法:

boolean execute()   如果第一个结果是ResultSet对象,则返回true;如果第一个结果是执行语句后更新的行数或者没有结果,则返回false。

ResultSet executeQuery(): 返回执行查询语句后得到的ResultSet结果集

int executeUpdate(): 返回一个int类型的值,该值代表执行insert,delete,update操作后的更新行数。对于create table table_name或者drop table table_name等操作,返回0,对于没有执行的操作,没有返回值

列举常用的setxxx方法,用第二个参数替换第(参数1)上的占位符,达到修改sql语句的目的,参数1是第几个占位符,从1开始算起,有很多这样的方法,具体可查api

void setInt(int parameterIndex, int x)用参数2替换第(参数1)个占位符

void setString(int parameterIndex, String x)用参数2替换第(参数1)个占位符,字符串如''yyyy-MM-dd'可以代替日期,mysql默认识别此种字符串形式的日期

void setFloat(int parameterIndex, float x)用参数2替换第(参数1)个占位符

void setDate(int parameterIndex, java.sql.Date x)用参数2替换第(参数1)个占位符

void close()立即释放此PreparedStatement对象的数据库和JDBC资源

 

6 ResultSet接口

java.sql.ResultSet,该接口的作用主要用来封装结果集。在sql中select语句查询的结果可以看作一张临时表,而ResultSet就代表这张表

常用方法:

boolean next() throws SQLException 将指针移向下一行,如果该行有值返回true,否则返回false。

void close() 关闭Resultset对象释放jdbc资源

getObject(String ColomnName); 根据列名取值。

getObject(int columnIndex); 根据序号取值,索引从1开始,可读性不强,不建议使用

下面四个方法都有重载的方法,参数为int型的索引,可读性不强,不建议使用就没列出来啦

int getInt(String columnName)以整数的形式获取指定列的内容

float getFloat(String columnName)以浮点数的形式获取指定列的内容

String getString(String columnName)以字符串的形式获取指定列的内容

Date getDate(String columnName)以Date的形式获取指定列的内容,返回值java.sql.Date继承自java.util.Date,两个都可以用

InputStream getBinaryStream(String columnLabel) throws SQLException 以byte流的方式获取ResultSet对象当前行中指定列的值,参数columnLabel为列名称。

boolean previous() throws SQLException 将指针移向上一行,如果该行有效返回true,否则返回false.

boolean isClosed() throws SQLException 判断当前ResultSet对象是否已关闭。boolean absolute(int row) throws SQLException 将光标移动到此ResultSet对象的给定行编号,参数row为行编号。

boolean first() throws SQLException 将光标移动到此ResultSet对象的第一行

boolean last() throws SQLException 将光标移动到此ResultSet对象的最后一行。

 

 

示例:

执行以下脚本在数据库study1中创建新表t_user,并插入三条数据

create table t_user(
    id int primary key auto_increment,
    name varchar(40),
    password varchar(40),
    email varchar(60),
    birthday date
);
insert into t_user(name,password,email,birthday) values('tiger','123456','tiger@163.com','1994-12-01'),
('rabbit','123456','tiger@163.com','1997-06-11'),
('sheep','123456','sheep@163.com','1995-07-15');

说明,字段id设置为主键,自增,在不指定id的情况下,插入数据id会自动增长,如果某id的这行数据被删除,下次会自动跳过该id值继续增长 

下面示例,jdbc增删改查操作

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;

import org.junit.Test;

import com.mysql.cj.xdevapi.Result;

public class JdbcTest02 {

	@Test
	public void testJDBC() throws Exception {
	String driver="com.mysql.cj.jdbc.Driver";
	Class.forName(driver);
	Connection conn=DriverManager.getConnection("jdbc:mysql://localhost:3306/study1?useSSL=false&serverTimezone=UTC", "root", "root");
	Statement stat=conn.createStatement();
	int in1=stat.executeUpdate("insert into t_user(name,password,email,birthday) values ('bird',123,'bird@163.com','1992-01-20') ");
	int in2=stat.executeUpdate("update t_user set password=321 where name='bird'");
	ResultSet rs=stat.executeQuery("select * from t_user");
	while(rs.next()) {
		System.out.println(rs.getObject("id"));
		System.out.println(rs.getString("name"));
		System.out.println(rs.getInt("password"));
		System.out.println(rs.getString("email"));
		System.out.println(rs.getDate("birthday"));
		System.out.println("==================");
	}
	int in3=stat.executeUpdate("delete from t_user where name='bird'");
	rs.close();
	stat.close();
	conn.close();
	}
}
out:
1 tiger 123456 tiger@163.com 1994-12-01 ==================
2 rabbit 123456 tiger@163.com 1997-06-11 ==================
3 sheep 123456 sheep@163.com 1995-07-15 ==================
4 bird 321 bird@163.com 1992-01-20 ==================

 

另外 在做查询操作时,可能会返回多条数据结果,此时可以定义一个JavaBean类,将数据封装到该JavaBean中,多条数据的话将此JavaBean放到集合中。那咱们就创建一个User类

package bean;

import java.util.Date;

public class User {
	private int id;
	private String name;
	private String password;
	private String email;
    private Date birthday;
	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public String getPassword() {
		return password;
	}
	public void setPassword(String password) {
		this.password = password;
	}
	public String getEmail() {
		return email;
	}
	public void setEmail(String email) {
		this.email = email;
	}
	public Date getBirthday() {
		return birthday;
	}
	public void setBirthday(Date birthday) {
		this.birthday = birthday;
	}
	
	@Override
	public String toString() {
		return "User [id=" + id + ", name=" + name + ", password=" + password + ", email=" + email + ", birthday="
				+ birthday + "]";
	}
}

执行JDBC查询操作,将多条查询结果封装到JavaBean对象中并将JavaBean对象放入到集合里面: 

@Test
	public void testJDBC01() throws Exception {
		String driver="com.mysql.cj.jdbc.Driver";
		Class.forName(driver);
		Connection conn=DriverManager.getConnection("jdbc:mysql://localhost:3306/study1?useSSL=false&serverTimezone=UTC", "root", "root");
		Statement stat=conn.createStatement();
		ResultSet rs=stat.executeQuery("select id,name,password,email,birthday from t_user");
		List<User> list=new ArrayList<>();
		while(rs.next()) {
			User u=new User();
			u.setId(rs.getInt("id"));
			u.setName(rs.getString("name"));
			u.setPassword(rs.getString("password"));
			u.setEmail(rs.getString("email"));
			u.setBirthday(rs.getDate("birthday"));
			list.add(u);
		}
		System.out.println(list);
		rs.close();
		stat.close();
		conn.close();
	}

注意:上述程序中将每一行的数据封装进一个javaBean对象,再将每个javaBean对象放入List中,集合List放入的是该对象的引用

创建javaBean对象时应在while循环体中创建,这样才能保证创建出来的对象都是不同的

分析上面程序的执行过程如图

如下代码片段是有问题的

        List<User> list=new ArrayList<>();
        User u=new User();
		while(rs.next()) {
			u.setId(rs.getInt("id"));
			u.setName(rs.getString("name"));
			u.setPassword(rs.getString("password"));
			u.setEmail(rs.getString("email"));
			u.setBirthday(rs.getDate("birthday"));
			list.add(u);
		}

它将会造成完全不同的结果,分析下这个代码段,如图所示

每执行一次循环,更改一次User对象的值,其引用放入到List中,三次循环之后,List中的三个User对象的引用指向的是同一块内存地址,所以这个List中的元素是一样的 

参考:小猴子视频

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值