本文目录:

 1、JDBC简介

      2、使用JDBC的步骤——第一个JDBC程序

      3、DriverManager ——加载数据库驱动

      4、数据库URL ——标识数据库的位置

      5、Connection ——代表数据库的链接

      6、Statement  ——向数据库发送SQL语句

      7、ResultSet  ——代表Sql语句的执行结果

      8、释放资源 ——释放与数据库进行交互的对象

      9、用JDBC对数据库进行CRUD 

      10、CRUD操作-create 示例Demo

      11、CRUD操作-updata 示例Demo

      12、CRUD操作-delete 示例Demo

      13、CRUD操作-read 示例Demo

      14、SQL 注入的防范

      15、PreparedStatement

      16、数据库分页——实现语句

      17、数据库分页—— 采用Dao工厂模式实现数据库分页原理图解

      18、数据库分页——执行流程中所需的类及代码

      19、数据库分页——QueryInfo类、PageBean类、QueryResult类 三个辅助类的内容

1、JDBC简介

SUN公司为了简化、统一对数据库的操作,定义了一套Java操作数据库的规范,称之为JDBC。JDBC全称为:Java Data Base Connectivity(java数据库连接),它主要由接口组成。

组成JDBC的2个包:java.sql、javax.sql

开发JDBC应用需要以上2个包的支持外,还需要导入相应JDBC的数据库实现(即数据库驱动)。

2、使用JDBC的步骤——第一个JDBC程序

需求:编程从user表中读取数据,并打印在命令行窗口中。

(1) 搭建实验环境 :

a、在mysql中创建一个库,并创建user表t同时插入数据到表中。

b、新建一个Java工程,并导入数据库驱动。

(2) 编写程序,在程序中加载数据库驱动

a、方式一:DriverManager. registerDriver(Driver driver)

b、方式二:Class.forName(“com.mysql.jdbc.Driver”);

(3) 建立连接(Connection)

Connection conn = DriverManager.getConnection(url,user,pass);

(4) 创建用于向数据库发送SQL的Statement对象,并发送sql

Statement st = conn.createStatement();

ResultSet rs = st.excuteQuery(sql);

(5) 从代表结果集的ResultSet中取出数据,打印到命令行窗口

(6) 断开与数据库的连接,并释放相关资源

Demo样例:

 public static void main(String[] args) throws SQLException {
String url = "jdbc:mysql://localhost:3306/day14";
String username = "root";
String password = "root";
//1.加载驱动
DriverManager.registerDriver(new com.mysql.jdbc.Driver());
//2。获取链接
Connection conn = DriverManager.getConnection(url, username, password);
//3.获取向数据库发sql语句的statament对象
Statement st = conn.createStatement();
//4.向数据库发送sql,获取数据库返回的结果集
ResultSet rs = st.executeQuery("select * from users");
//5.从结果集中获取数据
while(rs.next()){
System.out.println("id=" + rs.getObject("id"));
System.out.println("name=" + rs.getObject("name"));
System.out.println("password=" + rs.getObject("password"));
System.out.println("email=" + rs.getObject("email"));
System.out.println("birthday=" + rs.getObject("birthday"));
}
//6.释放资源(释放链接)
rs.close();
st.close();
conn.close();
}

3、DriverManager ——加载数据库驱动

Jdbc程序中的DriverManager用于加载驱动,并创建与数据库的链接,这个API的常用方法:

DriverManager.registerDriver(new Driver())

DriverManager.getConnection(url, user, password),

注意:在实际开发中并不推荐采用registerDriver方法注册驱动。原因有二:

     一、查看Driver的源代码可以看到,如果采用此种方式,会导致驱动程序注册两次,也就是在内存中会有两个Driver对象。

    二、程序依赖mysql的api,脱离mysql的jar包,程序将无法编译,将来程序切换底层数据库将会非常麻烦。

推荐方式:Class.forName(“com.mysql.jdbc.Driver”);

      采用此种方式不会导致驱动对象在内存中重复出现,并且采用此种方式,程序仅仅只需要一个字符串,不需要依赖具体的驱动,使程序的灵活性更高。

     同样,在开发中也不建议采用具体的驱动类型指向getConnection方法返回的connection对象。

Demo:数据库JDBC开发使用的模版(Statement对象。):

     String url = "jdbc:mysql:///day14";
String username = "root";
String password = "root"; Connection conn = null;
Statement st = null;
ResultSet rs = null; try{
Class.forName("com.mysql.jdbc.Driver");
conn = DriverManager.getConnection(url, username, password);
st = conn.createStatement(); //throw CRUD操作…… }finally{
if(rs!=null){
try{
rs.close(); //throw new
}catch (Exception e) { e.printStackTrace();
}
rs = null;
}
if(st!=null){
try{
st.close();
}catch (Exception e) {
e.printStackTrace();
}
st = null;
}
if(conn!=null){
try{
conn.close();
}catch (Exception e) {
e.printStackTrace();
}
}
}

4、数据库URL ——标识数据库的位置

URL用于标识数据库的位置,程序员通过URL地址告诉JDBC程序连接哪个数据库,MySql 数据库的URL写法为: jdbc:mysql:[]//localhost:3306/test ?参数名:参数值

 URL图解

  常用数据库URL地址的写法:

Oracle写法:jdbc:oracle:thin:@localhost:1521:sid

SqlServer—jdbc:microsoft:sqlserver://localhost:1433; DatabaseName=sid

MySql—jdbc:mysql://localhost:3306/sid

Mysql的url地址的简写形式: jdbc:mysql:///sid

常用属性:useUnicode=true&characterEncoding=UTF-8

5、Connection ——代表数据库的链接

Jdbc程序中的Connection,它用于代表数据库的链接。Connection 是数据库编程中最重要的一个对象,客户端与数据库所有交互都是通过Connection 对象完成的,这个对象的常用方法:

(1) createStatement():创建向数据库发送sql的statement对象。

(2) prepareStatement(sql) :创建向数据库发送预编译sql的PrepareSatement对象。

(3) prepareCall(sql):创建执行存储过程的callableStatement对象。

(4) setAutoCommit(boolean autoCommit):设置事务是否自动提交。

(5) commit() :在链接上提交事务。

(6) rollback() :在此链接上回滚事务。

6、Statement  ——向数据库发送SQL语句

Jdbc程序中的Statement对象用于向数据库发送SQL语句, Statement对象常用方法:

(1) executeQuery(String sql) :用于向数据库发送查询语句。

(2) executeUpdate(String sql):用于向数据库发送insert、update或delete语句

(3) execute(String sql):用于向数据库发送任意sql语句

(4) addBatch(String sql) :把多条sql语句放到一个批处理中。

(5) executeBatch():向数据库发送一批sql语句执行。

(6) clearBatch() :清空此 Statement 对象的当前 SQL 命令列表。

7、ResultSet  ——代表Sql语句的执行结果

  Jdbc程序中的ResultSet用于代表Sql语句的执行结果。Resultset封装执行结果时,采用的类似于表格的方式。 ResultSet 对象维护了一个指向表格数据行的游标,初始的时候,游标在第一行之前,调用ResultSet.next() 方法,可以使游标指向具体的数据行,进行调用方法获取该行的数据。

(1) ResultSet提供了对结果集进行滚动的方法:

a、next():移动到下一行

b、Previous():移动到前一行

c、absolute(int row):移动到指定行

d、beforeFirst():移动resultSet的最前面。

e、 afterLast() :移动到resultSet的最后面。

(2) ResultSet既然用于封装执行结果的,所以该对象提供了用于获取数据的get方法:

获取任意类型的数据

getObject(int index)

getObject(string columnName)

 获取指定类型的数据,例如:

getString(int index)

getString(String columnName)

其他获取指定类型数据的方法见下表:

常用数据类型转换表:

8、释放资源 ——释放与数据库进行交互的对象 

Jdbc程序运行完后,切记要释放程序在运行过程中,创建的那些与数据库进行交互的对象,这些对象通常是ResultSet, Statement和Connection对象。

特别是Connection对象,它是非常稀有的资源,用完后必须马上释放,如果Connection不能及时、正确的关闭,极易导致系统宕机。Connection的使用原则是尽量晚创建,尽量早的释放。

为确保资源释放代码能运行,资源释放代码也一定要放在finally语句中。

9、用JDBC对数据库进行CRUD 

Jdbc中的statement对象用于向数据库发送SQL语句,想完成对数据库的增删改查,只需要通过这个对象向数据库发送增删改查语句即可。

Statement对象的executeUpdate方法,用于向数据库发送增、删、改的sql语句,executeUpdate执行完后,将会返回一个int整数(即增删改语句导致了数据库几行数据发生了变化)。

Statement.executeQuery方法用于向数据库发送查询语句,executeQuery方法返回代表查询结果的ResultSet对象。

10、CRUD操作-create 示例Demo

使用executeUpdate(String sql)方法完成数据添加操作,示例操作:

Class.forName("com.mysql.jdbc.Driver");

conn = DriverManager.getConnection(url, username, password);

Statement st = conn.createStatement();

String sql = "insert into user(….) values(…..) ";

int num = st.executeUpdate(sql);

if(num>0){

System.out.println("插入成功!!!");

}

11、CRUD操作-updata 示例Demo

使用executeUpdate(String sql)方法完成数据修改操作,示例操作:

Class.forName("com.mysql.jdbc.Driver");

conn = DriverManager.getConnection(url, username, password);

Statement st = conn.createStatement();

String sql = “update user set name=‘ ’ where name=‘ ’  ";

int num = st.executeUpdate(sql);

if(num>0){

System.out.println(“修改成功!!!");

}

12、CRUD操作-delete 示例Demo

使用executeUpdate(String sql)方法完成数据删除操作,示例操作:

Class.forName("com.mysql.jdbc.Driver");

conn = DriverManager.getConnection(url, username, password);

Statement st = conn.createStatement();

String sql = "delete from user where id=1";

int num = st.executeUpdate(sql);

if(num>0){

System.out.println(“删除成功!!!");

}

13、CRUD操作-read 示例Demo

使用executeQuery(String sql)方法完成数据查询操作,示例操作:

Class.forName("com.mysql.jdbc.Driver");

conn = DriverManager.getConnection(url, username, password);

Statement st = conn.createStatement();

String sql = “select * from user where id=1 “;

ResultSet rs = st.executeUpdate(sql);

while(rs.next()){

//根据获取列的数据类型,分别调用rs的相应方法

//映射到java对象中

}

14、SQL 注入的防范

SQL 注入是用户利用某些系统没有对输入数据进行充分的检查,从而进行恶意破坏的行为。

1、statement存在sql注入攻击问题,例如登陆用户名采用' or 1=1 or username=‘

2、对于防范 SQL 注入,可以采用PreparedStatement取代Statement。

备注:本例只是最基本的防止SQL注入方式,其他情况还请查阅资料。

15、PreparedStatement

PreperedStatement是Statement的孩子,它的实例对象可以通过调用Connection.preparedStatement()方法获得,相对于Statement对象而言的优势:

(1) 防止SQL注入:PreperedStatement可以避免SQL注入的问题。

(2) 预编译SQL语句:Statement会使数据库频繁编译SQL,可能造成数据库缓冲区溢出。PreparedStatement 可对SQL进行预编译,从而提高数据库的执行效率。

(3) 使用占位符简化语句:并且PreperedStatement对于sql中的参数,允许使用占位符的形式进行替换,简化sql语句的编写。 (例如多次循环插入数据)

 Demo样例:

 public List<Customer> getAll(){
Connection conn = null;
PreparedStatement st = null;
ResultSet rs = null;
try{
conn = JdbcUtils.getConnection();
String sql = "select * from customer";
st = conn.prepareStatement(sql);
rs = st.executeQuery();
List list = new ArrayList();
while(rs.next()){
Customer c = new Customer();
c.setBirthday(rs.getDate("birthday"));
c.setCellphone(rs.getString("cellphone"));
c.setDescription(rs.getString("description"));
c.setEmail(rs.getString("email"));
c.setGender(rs.getString("gender"));
c.setId(rs.getString("id"));
c.setName(rs.getString("name"));
c.setPreference(rs.getString("preference"));
c.setType(rs.getString("type"));
list.add(c);
}
return list;
}catch (Exception e) {
throw new DaoException(e);
}finally{
JdbcUtils.release(conn, st, rs);
}
}

16、数据库分页——实现语句

(1) MySQL分页

MySQL分页的实现语句:

Select * from table limit M,N

M:记录开始索引位置

N:取多少条记录。

完成WEB页面的分页显示的步骤:

(a) 先获得需分页显示的记录总数,然后在web页面中显示页码。

(b) 根据页码,从数据库中查询相应的记录显示在web页面中。

以上两项操作通常使用Page对象进行封装。

(2) Oracle分页

Oracle分页的实现语句:

select * from (

select rownum r_, row_.*  from (

select * from student order by id

) row_ where rownum <=5

) where r_>=1

1位置:起始索引位置。

5位置:结束索引位置。

备注:关于Oracle的分页,此处仅是简单讲解,会在Oracle 专题博文中详述。

17、数据库分页—— 采用Dao工厂模式实现数据库分页原理图解

(1) dao工厂模式的原理示意图

  (2) 数据库分页 原理图解

18、数据库分页——执行流程中所需的类及代码

 (1)Servlet层:ListCustomerServlet .java

         //处理用户分页请求
public class ListCustomerServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
try{
QueryInfo info = WebUtils.request2Bean(request, QueryInfo.class);
BusinessService service = new BusinessServiceImpl();
PageBean pagebean = service.pageQuery(info);
request.setAttribute("pagebean", pagebean);
request.getRequestDispatcher("/WEB-INF/jsp/listcustomer.jsp").forward(request, response);13
}catch (Exception e) {
e.printStackTrace();
request.setAttribute("message", "查看客户失败!!");
                request.getRequestDispatcher("/message.jsp").forward(request, response);
}
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}

(2) Service层:BusinessServiceImpl.java

   public class BusinessServiceImpl implements BusinessService {
public PageBean pageQuery(QueryInfo queryInfo){
//调用dao获取到页面数据
QueryResult qr = dao.pageQuery(queryInfo.getStartindex(), queryInfo.getPagesize());
//根据dao查询结果,生成页面显示需要pagebean
PageBean bean = new PageBean();
           bean.setCurrentpage(queryInfo.getCurrentpage());
bean.setList(qr.getList());
bean.setPagesize(queryInfo.getPagesize());
bean.setTotalrecord(qr.getTotalrecord());
return bean;
}

 (3)Dao层:CustomerDaoImpl.java   

public class CustomerDaoImpl implements CustomerDao {
//获取到页面数据和页面大小
public QueryResult pageQuery(int startindex,int pagesize){
Connection conn = null;
PreparedStatement st = null;
ResultSet rs = null;
QueryResult qr = new QueryResult();
try{
conn = JdbcUtils.getConnection();
String sql = "select * from customer limit ?,?";
st = conn.prepareStatement(sql);
st.setInt(1, startindex);
st.setInt(2, pagesize);
rs = st.executeQuery();
List list = new ArrayList();
while(rs.next()){
Customer c = new Customer();
c.setBirthday(rs.getDate("birthday"));
c.setCellphone(rs.getString("cellphone"));
c.setDescription(rs.getString("description"));
c.setEmail(rs.getString("email"));
c.setGender(rs.getString("gender"));
c.setId(rs.getString("id"));
c.setName(rs.getString("name"));
c.setPreference(rs.getString("preference"));
c.setType(rs.getString("type"));
list.add(c);
}
qr.setList(list);
sql = "select count(*) from customer";
st = conn.prepareStatement(sql);
rs = st.executeQuery();
if(rs.next()){
qr.setTotalrecord(rs.getInt(1));
}
return qr;
}catch (Exception e) {
throw new DaoException(e);
}finally{
JdbcUtils.release(conn, st, rs);
}
}

19、数据库分页——QueryInfo类、PageBean类、QueryResult类 三个辅助类的内容

(1)QueryInfo.java 类中的内容:

 public class QueryInfo {
private int currentpage = 1; //用户当前看的页
private int pagesize = 5; //记住用户想看的页面大小
private int startindex; //记住用户看的页的数据在数据库的起始位置
public int getCurrentpage() {
return currentpage;
}
public void setCurrentpage(int currentpage) {
this.currentpage = currentpage;
}
public int getPagesize() {
return pagesize;
}
public void setPagesize(int pagesize) {
this.pagesize = pagesize;
}
public int getStartindex() {
this.startindex = (this.currentpage-1)*this.pagesize;
return startindex;
}
}

(2)PageBean.java  类中的内容:

        public class PageBean {
private List list;
private int totalrecord;
private int pagesize;
private int totalpage;
private int currentpage;
private int previouspage;
private int nextpage;
private int[] pagebar; public List getList() {
return list; }
public void setList(List list) {
this.list = list;
}
public int getTotalrecord() {
return totalrecord; }
public void setTotalrecord(int totalrecord) {
this.totalrecord = totalrecord;
}
public int getPagesize() {
return pagesize;
}
public void setPagesize(int pagesize) {
this.pagesize = pagesize;
}
public int getTotalpage() {
//100 5 20
//101 5 21
//99 5 20
if(this.totalrecord%this.pagesize==0){
this.totalpage = this.totalrecord/this.pagesize;
}else{
this.totalpage = this.totalrecord/this.pagesize+1;
}
return totalpage;
}
public int getCurrentpage() {
return currentpage;
}
public void setCurrentpage(int currentpage) {
this.currentpage = currentpage;
}
public int getPreviouspage() {
if(this.currentpage-1<1){
this.previouspage = 1;
}else{
this.previouspage = this.currentpage-1;
}
return previouspage;
}
public int getNextpage() {
if(this.currentpage+1>=this.totalpage){
this.nextpage = this.totalpage;
}else{
this.nextpage = this.currentpage +1;
}
return nextpage;
} public int[] getPagebar() {
int startpage;
int endpage;
int pagebar[] = null;
if(this.totalpage<=10){
pagebar = new int[this.totalpage];
startpage = 1;
endpage = this.totalpage;
}else{
pagebar = new int[10];
startpage = this.currentpage - 4;
endpage = this.currentpage + 5;
//总页数=30 3 -1
//总页数=30 29 34 21 30
if(startpage<1){
startpage = 1;
endpage = 10;
}
if(endpage>this.totalpage){
endpage = this.totalpage;
startpage = this.totalpage - 9;
}
}
int index = 0;
for(int i=startpage;i<=endpage;i++){
pagebar[index++] = i;
}
this.pagebar = pagebar;
return this.pagebar;
/*int pagebar[] = new int[this.totalpage];
for(int i=1;i<=this.totalpage;i++){
pagebar[i-1] = i;
}
this.pagebar = pagebar;
return pagebar;*/
}
}

(3)QueryResult.java  类中的内容: 

  public class QueryResult {
private List list; //记住用户看的页的数据
private int totalrecord; //记往总记录数
public List getList() {
return list;
}
public void setList(List list) {
this.list = list;
}
public int getTotalrecord() {
return totalrecord;
}
public void setTotalrecord(int totalrecord) {
this.totalrecord = totalrecord;
}
}

JDBC 学习笔记(一)—— 基础知识 + 分页技术的更多相关文章

  1. MyBatis:学习笔记(1)——基础知识

    MyBatis:学习笔记(1)--基础知识 引入MyBatis JDBC编程的问题及解决设想 ☐ 数据库连接使用时创建,不使用时就释放,频繁开启和关闭,造成数据库资源浪费,影响数据库性能. ☐ 使用数 ...

  2. Quartz学习笔记:基础知识

    Quartz学习笔记:基础知识 引入Quartz 关于任务调度 关于任务调度,Java.util.Timer是最简单的一种实现任务调度的方法,简单的使用如下: import java.util.Tim ...

  3. C#学习笔记(基础知识回顾)之值类型与引用类型转换(装箱和拆箱)

    一:值类型和引用类型的含义参考前一篇文章 C#学习笔记(基础知识回顾)之值类型和引用类型 1.1,C#数据类型分为在栈上分配内存的值类型和在托管堆上分配内存的引用类型.如果int只不过是栈上的一个4字 ...

  4. C#学习笔记(基础知识回顾)之值传递和引用传递

    一:要了解值传递和引用传递,先要知道这两种类型含义,可以参考上一篇 C#学习笔记(基础知识回顾)之值类型和引用类型 二:给方法传递参数分为值传递和引用传递. 2.1在变量通过引用传递给方法时,被调用的 ...

  5. C#学习笔记(基础知识回顾)之值类型和引用类型

    一:C#把数据类型分为值类型和引用类型 1.1:从概念上来看,其区别是值类型直接存储值,而引用类型存储对值的引用. 1.2:这两种类型在内存的不同地方,值类型存储在堆栈中,而引用类型存储在托管对上.存 ...

  6. Docker的学习笔记(一)基础知识

    概述 本人最近在学习docker相关的知识,既是工作本身的需要也是自己对技术的追求的必要,以后我也会推出容器相关的随笔,既可以增长自己的知识,也可以和读者广泛交流,岂不乐乎?话不多说.第一篇先介绍do ...

  7. .net学习笔记---xml基础知识

    一.XML简介 XML是一种标记语言,用于描述数据,它提供一种标准化的方式来来表示文本数据.XML文档以.xml为后缀.需要彻底注意的是XML是区分大小写的. 先从一个简单的XML例子来了解下xml基 ...

  8. Scala学习笔记--正则表达式基础知识、如何在scala内使用

    正则表达式语法:https://msdn.microsoft.com/zh-cn/library/ae5bf541(VS.80).aspx 基础知识:正则表达式30分钟入门教程 http://www. ...

  9. (C/C++学习笔记) 一. 基础知识

    一. 基础知识 ● 程序和C/C++ 程序: 根据Wirth (1976), Algorithms + Data Structures = Programs. Whence C: 1972, Denn ...

  10. C#学习笔记(基础知识回顾)之枚举

    一:枚举的含义 枚举是用户定义的整数类型.在声明一个枚举时,要指定该枚举的示例可以包含的一组可接受的值.还可以给值指定易于记忆的名称.个人理解就是为一组整数值赋予意义. 二:枚举的优势 2.1:枚举可 ...

随机推荐

  1. 说一说Android的工程目录结构

    这段时间正在学习有关Android的知识,对在Eclipse下开发的Android项目的目录结构有了一定的了解,在此对目录结构做一个简单的介绍.下图是在Eclipse下Android项目展开的项目目录 ...

  2. INSERT IGNORE 与 INSERT INTO的区别

    例 insert ignore表示,如果中已经存在相同的记录,则忽略当前新数据: insert ignore into table(name)  select  name from table2 例 ...

  3. Ajax Array Json 示例

    function functionName(){ var list=new Array(); $("td.classA").each(function(){ list.push($ ...

  4. 【转】C#异步编程及其同步机制

    C#异步编程及其同步机制 本篇文章涵盖一下几部分内容: 1. 什么是异步编程,为什么会需要异步编程 2. .NET下的异步编程及其发展 3. .NET线程同步机制及线程间数据封送 4. 异步模式 5. ...

  5. linux 内核和应用程序区别

    应用程序存在于虚拟内存中, 有一个非常大的堆栈区. 堆栈, 当然, 是用来保存函数调用历史以及所有的由当前活跃的函数创建的自动变量. 内核, 相反, 有一个非常小的堆栈; 它可能小到一个, 4096 ...

  6. 学习笔记:JavaScript传参方式———ECMAScript中所有函数的参数都是按值传递

    我们把命名参数(arguments)视为局部变量,在向参数传递基本类型值时,如同基本类型变量的复制一样,传递一个副本,参数在函数内部的改变不会影响外部的基本类型值.如: function add10( ...

  7. 博客转移到 海胖网 http://haipz.com/ 希望你能支持我们!

    博客转移到 海胖网 http://haipz.com/ 希望你能支持我们! 博客转移到 海胖网 http://haipz.com/ 希望你能支持我们! 博客转移到 海胖网 http://haipz.c ...

  8. oc - runtime运行机制

      Objective-C语言是一门动态语言,它将很多静态语言在编译和链接时做的事放到了运行时来处理.同时OC也是一门简单的语言,很大一部分是C的内容,只是在语言层面上加了关键字和语法,真正让OC强大 ...

  9. 3.servlet实现页面的跳转

    效果: 在网页的输入框中输入lily,跳到成功的页面(请求转发),输入的不是lily则跳到百度的页面(跳到工程之外的页面,则是请求重定向) 1.建Web project“2Servlet_Basic” ...

  10. NSS_08 extjs表单验证

    Extjs做了非常好的表单验证功能, 使用起来非常方便. 系统内置了4种验证功能,分别是alpha, alphanumeric,url, email, 在程序中可以直接使用,(可以结合allowBla ...