jdbc笔记doc

一、JDBC概述

为什么要使用JDBC?
JDBC:java database connectivity SUN公司提供的一套操作数据库的标准规范。
JDBC与数据库驱动的关系:接口与实现的关系。
在这里插入图片描述

JDBC规范(掌握四个核心对象):

  • DriverManager:用于注册驱动
  • Connection: 表示与数据库创建的连接
  • Statement: 操作数据库sql语句的对象
  • ResultSet: 结果集或一张虚拟表

开发一个JDBC程序的准备工作:

JDBC规范在哪里:
JDK中:
java.sql.;
javax.sql.
;
数据库厂商提供的驱动:jar文件
*.jar

在这里插入图片描述

二、开发一个JDBC程序(重要)

实现查询数据库中的数据显示在java的控制台中

1 、创建数据库表,并向表中添加测试数据

create database day06;
use day06;

create table users(
	id int primary key auto_increment,
	name varchar(40),
	password varchar(40),
	email varchar(60),
	birthday date
)character set utf8 collate utf8_general_ci;

insert into users(name,password,email,birthday) values('zs','123456','zs@sina.com','1980-12-04');
insert into users(name,password,email,birthday) values('lisi','123456','lisi@sina.com','1981-12-04');
insert into users(name,password,email,birthday) values('wangwu','123456','wangwu@sina.com','1979-12-04');

2、创建java project项目,添加数据库驱动(mysql-connector-java-5.0.8-bin.jar)

3、实现JDBC操作

	//1、注册驱动
	//2、创建连接
	//3、得到执行sql语句的Statement对象
	//4、执行sql语句,并返回结果
	//5、处理结果
	//6关闭资源
    //注册驱动
	DriverManager.registerDriver(new com.mysql.jdbc.Driver());
	//获取连接Connection
	Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/day06", "root", "abc");
	//得到执行sequel语句的对象Statement
	Statement stmt = conn.createStatement();
	//执行sql语句,并返回结果
	java.sql.ResultSet rs = stmt.executeQuery("select password,email,birthday,id,name from users");
	//处理结果 
	while(rs.next()){ 
		System.out.println(rs.getObject("password"));
		System.out.println(rs.getObject("id"));
		System.out.println(rs.getObject("name"));
		System.out.println(rs.getObject("birthday"));
		System.out.println(rs.getObject("email"));
		System.out.println("-----------------");
	}
	//关闭资源
	rs.close();
	stmt.close();
	conn.close();

在这里插入图片描述

三、JDBC常用的类和接口详解

1、java.sql.Drivermanager类 : 创建连接

a、注册驱动

DriverManager.registerDriver(new com.mysql.jdbc.Driver());不建议使用

原因有2个:

  • 导致驱动被注册2次。
  • 强烈依赖数据库的驱动jar
    缺点:由new com.mysql.jdbc.Driver()可以知道,这里需要创建一个类的实例。创建类的实例就需要在java文件中将该类通过import导入,否则就会报错,即采用这种方式,程序在编译的时候不能脱离驱动类包,为程序切换到其他数据库带来麻烦。实际上这个地方还做了一次无用功,Driver类中本身已经含有静态块将instance放入驱动列表中。(详细说明可以参照mysql的Driver类)
    可见,在创建Driver类的时候,其实已经调用一次registerDriver方法了
    https://wenku.baidu.com/view/a542eb0d79563c1ec4da7105.html
  • 解决办法:
    Class.forName(“com.mysql.jdbc.Driver”);注册一遍,在driver.class里面
关于 forName 和 loadClass

关于forName()方法
这个方法总是返回要加载的类的Class类的实例
1、forName(String className)单参数时, initialize=true
a.总是使用当前类装载器(也就是装载执行forName()请求的类 的类装载器)
b.总是初始化这个被装载的类(当然也包括:装载、连接、初始化)

2、forName(String className, boolean initialize, ClassLoader loader)
a.loader指定装载参数类所用的类装载器,如果null则用bootstrap装载器。
b.initialize=true时,肯定连接,而且初始化了;
c.false时,绝对不会初始化,但是可能被连接了,但是这里有个例外,如果在调用这个forName()前,已经被初始化了(当然,这里也暗含着:className是被同一个loader所装载的,即被参数中的loader所装载的,而且这个类被初始化了),那么返回的类型也肯定是被初始化的

public Class<?> loadClass(String name) throws ClassNotFoundException {
        return loadClass(name, false);

关于用户自定义的类装载器的loadClass()方法
1、loadClass(String name)单参数时, resolve=false
a.如果这个类已经被这个类装载器所装载,那么,返回这个已经被装载的类型的Class的实例,否则,就用这个自定义的类装载器来装载这个class,这时不知道是否被连接。绝对不会被初始化
b.这时唯一可以保证的是,这个类被装载了。但是不知道这个类是不是被连接和初始化了
2、loadClass(String name, boolean resolve)
a.resolve=true时,则保证已经装载,而且已经连接了。resolve=falses时,则仅仅是去装载这个类,不关心是否连接了,所以此时可能被连接了,也可能没有被连接

另外:这里所谓的“初始化”是指类的初始化,即执行了className字节码的方法

再者:类是这么加载的
1、装载
2、连接
a)验证–>检查类格式等
b)准备–>给类变量分配内存,并根据类变量类型设置默认值(即内存中置0)
c)解析–>常量池解析
3、初始化
即执行Java代码的字节码的方法,给类变量赋予程序员需要的值

在这里插入图片描述

b、与数据库建立连接

static Connection getConnection(String url, String user, String password) 
          试图建立到给定数据库 URL 的连接。

getConnection("jdbc:mysql://localhost:3306/day06", "root", "root");

URL:SUN公司与数据库厂商之间的一种协议。

jdbc:mysql://localhost:3306/day06

协议 子协议 IP :端口号 数据库

mysql: jdbc:mysql://localhost:3306/day14 或者 jdbc:mysql:///day14(默认本机连接)
oracle: jdbc:oracle:thin:@localhost:1521:sid

要参考数据库文档

	Properties info = new Properties();//要参考数据库文档
	info.setProperty("user", "root");
	info.setProperty("password","root");

getConnection(String url, Properties info) 

getConnection(String url) 
DriverManager.getConnection("jdbc:mysql://localhost:3306/day14?user=root&password=root");

2、java.sql.Connection接口:一个连接

接口的实现在数据库驱动中。所有与数据库交互都是基于连接对象的。

Statement  createStatement(); //创建操作sql语句的对象

3、java.sql.Statement接口: 操作sql语句,并返回相应结果的对象(小货车)

接口的实现在数据库驱动中。用于执行静态 SQL 语句并返回它所生成结果的对象。

ResultSet  executeQuery(String sql) 根据查询语句返回结果集。只能执行select语句。
int executeUpdate(String sql) 根据执行的DML(insert update delete)语句,返回受影响的行数。
boolean execute(String sql)  此方法可以执行任意sql语句。返回boolean值,表示是否返回ResultSet结果集。仅当执行select语句,且有返回结果时返回true, 其它语句都返回false;

4、java.sql.ResultSet接口: 结果集(客户端存表数据的对象)

a、封装结果集的。

提供一个游标,默认游标指向结果集第一行之前。
调用一次next(),游标向下移动一行。
提供一些get方法。

封装数据的方法

Object getObject(int columnIndex); 根据序号取值,索引从1开始
Object getObject(String ColomnName); 根据列名取值。

将结果集中的数据封装到javaBean中

java的数据类型与数据库中的类型的关系

byte          tityint
short         smallint
int           int
long          bigint
float         float
double        double
String        char varchar 
 Date         date


boolean next()	将光标从当前位置向下移动一行
int getInt(int colIndex)	以int形式获取ResultSet结果集当前行指定列号值
int getInt(String colLabel)	以int形式获取ResultSet结果集当前行指定列名值
float getFloat(int colIndex)	以float形式获取ResultSet结果集当前行指定列号值
float getFloat(String colLabel)	以float形式获取ResultSet结果集当前行指定列名值
String getString(int colIndex)	以String 形式获取ResultSet结果集当前行指定列号值
String getString(String colLabel)	以String形式获取ResultSet结果集当前行指定列名值
Date getDate(int columnIndex);  
Date getDate(String columnName); 返回的date类是sql中的,但一般用util包中的date接收
父类util兼容sql子类
void close()	关闭ResultSet 对象

b、可移动游标的方法

 boolean next()  将光标从当前位置向前移一行。 
boolean previous()     将光标移动到此 ResultSet 对象的上一行。 
 boolean absolute(int row) 参数是当前行的索引,从1开始	根据行的索引定位移动的指定索引行。
 void afterLast() 将光标移动到末尾,正好位于最后一行之后。 
 void beforeFirst()   将光标移动到开头,正好位于第一行之前。 

5、释放资源

资源有限,要正确关闭。

		//获取连接Connection
	Connection conn = null;
	//得到执行sql语句的对象Statement
	Statement stmt = null;
	//执行sql语句,并返回结果
	java.sql.ResultSet rs = null;
	try {
		//加载驱动
		Class.forName("com.mysql.jdbc.Driver");
		conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/day06?user=root&password=abc");
		stmt = conn.createStatement();
		rs = stmt.executeQuery("select id,name,password,email,birthday form users");
		//处理结果 
		while(rs.next()){ 
			System.out.println(rs.getObject(1));
			~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
			System.out.println(rs.getObject(5));
			System.out.println("-----------------");
		}
	} catch (Exception e) {
		e.printStackTrace();
	}finally{
		//关闭资源
		if(rs!=null){
			try {
				rs.close();
			} catch (Exception e) {
				e.printStackTrace();
			}
			rs = null;
		}
		if(stmt!=null){
			try {
				stmt.close();
			} catch (Exception e) {
				e.printStackTrace();
			}
			stmt = null;
		}
		if(conn!=null){
			try {
				conn.close();
			} catch (Exception e) {
				e.printStackTrace();
			}
			conn = null;
		}
		
	}

四、使用JDBC实现CRUD操作

第一种

TestCRUD

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;

import org.junit.Test;




public class TestCRUD {

@Test
public void testSelect() throws Exception{
	//加载驱动
	Class.forName("com.mysql.jdbc.Driver");
	//获取连接Connection
	Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/day06", "root", "abc");
	//得到执行sql语句的对象Statement
	Statement stmt = conn.createStatement();
	//执行sql语句,并返回结果
	ResultSet rs = stmt.executeQuery("select password,email,birthday,id,name from users");
	List<User> list = new ArrayList<User>();
	//处理结果 
	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);
	}
	//关闭资源
	rs.close();
	stmt.close();
	conn.close();
	
	for (User user : list) {
		System.out.println(user);
	}
}

@Test
public void testSelect1() throws Exception{
	//加载驱动
	Class.forName("com.mysql.jdbc.Driver");
	//获取连接Connection
	Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/day06", "root", "abc");
	//得到执行sql语句的对象Statement
	Statement stmt = conn.createStatement();
	//执行sql语句,并返回结果
	ResultSet rs = stmt.executeQuery("select password,email,birthday,id,name from users");
	List<User> list = new ArrayList<User>();
	
	rs.afterLast();
	rs.previous();
	//处理结果 
	//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);
	//}
	//关闭资源
	rs.close();
	stmt.close();
	conn.close();
	System.out.println(u);	
}
@Test
public void testInsert() throws Exception{
			//加载驱动
			Class.forName("com.mysql.jdbc.Driver");
			//获取连接Connection
			Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/day06?user=root&password=abc");
			//得到执行sql语句的对象Statement
			Statement stmt = conn.createStatement();
			//执行sql语句,并返回结果
			int i = stmt.executeUpdate("INSERT INTO users VALUES(4,'tom','123','tom@163.com','2015-09-28')");
			if(i>0){
				System.out.println("success");
			}
			//关闭资源
			stmt.close();
			conn.close();
}

@Test
public void testUpdate() throws Exception{
	//加载驱动
	Class.forName("com.mysql.jdbc.Driver");
	//获取连接Connection
	Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/day06?user=root&password=abc");
	//得到执行sql语句的对象Statement
	Statement stmt = conn.createStatement();
	//执行sql语句,并返回结果
	int i = stmt.executeUpdate("UPDATE users SET NAME='jerry',PASSWORD='333',email='jerry@163.com' WHERE id=3");
	if(i>0){
		System.out.println("success"+" 修改了"+i+"行");
	}else{
		System.out.println("修改了"+i+"行");
	}
	
	//关闭资源
	stmt.close();
	conn.close();
	
}


@Test
public void testDelete() throws Exception{
	//加载驱动
	Class.forName("com.mysql.jdbc.Driver");
	//获取连接Connection
	Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/day06?user=root&password=abc");
	//得到执行sql语句的对象Statement
	Statement stmt = conn.createStatement();
	//执行sql语句,并返回结果
	int i = stmt.executeUpdate("DELETE FROM users WHERE id=4");
	if(i>0){
		System.out.println("success");
	}
	//关闭资源
	stmt.close();
	conn.close();
	
}

}

第二种 Dbutils_自己实现

Apache也有一个dbutils注意区分,其实应该叫他jdbcutils

dbinfo.properties
driverClass=com.mysql.jdbc.Driver
url=jdbc:mysql:///day06
username=root
password=abc

DBUtils

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ResourceBundle;

public class DBUtils {
	private static String driverClass;
	private static String url;
	private static String username;
	private static String password;

static{
	//此对象是用于加载properties文件数据的
	ResourceBundle rb = ResourceBundle.getBundle("dbinfo");
	driverClass = rb.getString("driverClass");
	url = rb.getString("url");
	username = rb.getString("username");
	password = rb.getString("password");
	try {
		Class.forName(driverClass);
	} catch (ClassNotFoundException e) {
		e.printStackTrace();
	}
}

//得到连接的方法
public static Connection getConnection() throws Exception{
	return DriverManager.getConnection(url, username, password);
}

//关闭资源的方法
public static void closeAll(ResultSet rs,Statement stmt,Connection conn){
	//关闭资源
	if(rs!=null){
		try {
			rs.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
		rs = null;
	}
	if(stmt!=null){
		try {
			stmt.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
		stmt = null;
	}
	if(conn!=null){
		try {
			conn.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
		conn = null;
	}
}
}

TestCRUD

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import org.junit.Test;

import com.itheima.entity.User;
import com.itheima.util.DBUtils;

public class TestCRUD {
	@Test
	public void testSelect(){
		Connection conn = null;
		Statement stmt = null;
		ResultSet rs = null;
	
	try {
		conn = DBUtils.getConnection();
		stmt = conn.createStatement();
		rs = stmt.executeQuery("select * from users");
		List<User> list = new ArrayList<User>();
		while(rs.next()){
			User u = new User();
			u.setId(rs.getInt(1));
			u.setName(rs.getString(2));
			u.setPassword(rs.getString(3));
			u.setEmail(rs.getString(4));
			u.setBirthday(rs.getDate(5));
			list.add(u);
		}
		
		for (User user : list) {
			System.out.println(user);
		}
	} catch (Exception e) {
		e.printStackTrace();
	}finally{
		DBUtils.closeAll(rs, stmt, conn);
	}
}

@Test
public void testInsert(){
	Connection conn = null;
	PreparedStatement stmt = null;

	try {
		conn = DBUtils.getConnection();
		stmt = conn.prepareStatement("INSERT INTO users VALUES(?,?,?,?,?)");
		stmt.setInt(1, 5);
		stmt.setString(2, "tom");
		stmt.setString(3, "333");
		stmt.setString(4, "tom@163.com");
		//stmt.setDate(5, new java.sql.Date(System.currentTimeMillis()));
		stmt.setString(5, "2015-09-11");
		
		int i = stmt.executeUpdate();
		if(i>0){
			System.out.println("success");
		}
	} catch (Exception e) {
		e.printStackTrace();
	}finally{
		DBUtils.closeAll(null, stmt, conn);
	}
}

@Test
public void testUpdate(){
	Connection conn = null;
	PreparedStatement stmt = null;

	try {
		conn = DBUtils.getConnection();
		stmt = conn.prepareStatement("UPDATE users SET NAME=?,PASSWORD=?,email=? WHERE id=?");
		stmt.setString(1, "jerry123");
		stmt.setString(2, "123");
		stmt.setString(3, "jerry@163.com");
		stmt.setInt(4, 5);
		
		int i = stmt.executeUpdate();
		if(i>0){
			System.out.println("success");
		}
	} catch (Exception e) {
		e.printStackTrace();
	}finally{
		DBUtils.closeAll(null, stmt, conn);
	}
}

@Test
public void testDelete(){
	Connection conn = null;
	Statement stmt = null;

	try {
		conn = DBUtils.getConnection();
		stmt = conn.createStatement();
		int i = stmt.executeUpdate("DELETE FROM users WHERE id=4");
		if(i>0){
			System.out.println("success");
		}
	} catch (Exception e) {
		e.printStackTrace();
	}finally{
		DBUtils.closeAll(null, stmt, conn);
	}
}

}

五、实现一个用户登录的功能

在这里插入图片描述

六、SQL注入问题:preparedStatement

preparedStatement:预编译对象, 是Statement对象的子类。
特点:
性能要高
会把sql语句先编译
sql语句中的参数会发生变化,过滤掉用户输入的关键字。

补充例子:

在这里插入图片描述

七、分页理论

转自 传播智客

什么是分页及其作用

分页就是将数据以多页展示出来,使用分页的目的是为了提高用户的感受

分页分类

物理分页

只从数据库中查询出要显示的数据
优点:不占用很多内存
缺点:速度比较低,每一次都要从数据库中获取

逻辑分页

从数据库中将所有记录查找到,存储到内存中,需要什么数据
直接从内存中获取.
优点:速度比较快
缺点:占用比较多的内存,如果数据比较多,可以出现内在溢出。
数据实时更新需要单独处理.

mysql中limit介绍

利用mysql的limit,进行物理分页。

select * from 表名  limit m,n;
m是从0开始,代表是第几条记录   
n代表显示多少条记录

例如

select * from person limit 4,10;
从第五条记录开始,显示10条.

分页实现原理分析

1.知道一共有多少条记录

select count(*) from 表;

2.知道每一页显示多少条记录
人为定义的.
3.一共有多少页
1.总页数=总条数%每页条数==0?总条数/每页条数:总条数/每页条数+1
2.总页数=Math.ceil(总条数*1.0/每页条数);
4.当前页码
默认值为1,代表第一页.
当点击上一页,下一页,就是对页码进行+1 -1操作.
5.需要当前页的数据
例如:每页显示五条,要查询第三页数据

	select * from 表 limit(3-1)*5,5;
    用(当前页码-1)*每页条数,就求出了开始的记录位置,在向下查找每页数个     记录。就得到了这页的数据.

(currentPage-1)*pageSize

八、数据库连接池

1、连接池原理:(面试)

应用程序直接获取链接的缺点
在这里插入图片描述

数据库连接池负责分配、管理和释放数据库连接,它允许应用程序重复使用一个现有的数据库连接,而不是再重新建立一个;
释放空闲时间超过最大空闲时间的数据库连接来避免因为没有释放数据库连接而引起的数据库连接遗漏。这
项技术能明显提高对数据库操作的性能

在这里插入图片描述
目的:解决建立数据库连接耗费资源和时间很多的问题,提高性能。

2、编写标准的数据源

//模拟数据库连接池,但不具备实际开发意义,这里用到的dbutils是我们自己开发的一个工具类,代码在上边
在这里插入图片描述
在这里插入图片描述

自定义数据库连接池要实现javax.sql.DataSource接口,一般都叫数据源。

在这里插入图片描述

3、编写数据源时遇到的问题及解决办法

在这里插入图片描述

a、装饰设计模式:使用频率很高

目的:改写已存在的类的某个方法或某些方法,装饰设计模式(包装模式)
口诀:
1、编写一个类,实现与被包装类相同的接口。(具备相同的行为)
2、定义一个被包装类类型的变量。
3、定义构造方法,把被包装类的对象注入,给被包装类变量赋值。
4、对于不需要改写的方法,调用原有的方法。
5、对于需要改写的方法,写自己的代码。

在这里插入图片描述
在这里插入图片描述

b、默认适配器:装饰设计模式一个变体

(a实现了一个接口,实现接口所定义的方法,
然后b继承a,只需要重写我们需要的方法,)

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
代码看起来更加简洁

3、常用的数据源配置(日后都使用数据源,一定要配置一下)

3.1、DBCP

Properties类文件不支持中文
DBCP:Apache推出的Database Connection Pool
使用步骤:

  • 添加jar包 commons-dbcp-1.4.jar commons-pool-1.5.6.jar
  • 添加属性资源文件
  • 编写数据源工具类

在这里插入图片描述
在这里插入图片描述

3.2、C3P0

使用步骤:
1、添加jar包
2、编写配置文件
c3p0-config.xml,放在classpath中,或classes目录中
在这里插入图片描述
3、编写工具类:
在这里插入图片描述

九、完成全选/全不选

1、添加checkall的单击事件
2、调用执行方法checkAll()
//得到ckall全选框
//得到所有ck的复选框
//根据ckall复选框的选中状态给所有ck赋值

在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值