Java 数据库程序设计(JDBC)

image

补:数据库的基本操作

JDBC的基本概念

全称: Java Data Base Connectivity
组成:
由一组用Java语言编写的类和接口组成,不同的数据库都会实现这种接口。
作用:
为多种关系数据库提供同一的接口

优点:
对于不同厂商的数据库,JDBC驱动包都相同。
一次编写,处处运行

JAR包:
用JAVA语言实现与数据库的交互,是直接访问数据库,执行效率高
image

编程步骤:

  1. 加载数据库驱动:告知JVM使用的是哪一个数据库的驱动
  2. 连接数据库。
  3. 创建SQL语句的执行者对象。
  4. 执行sql语句:使用执行者对象,向数据库执行SQL语句 获取到数据库的执行后的结果
  5. 处理结果。
  6. 关闭SQL语句执行对象 。
  7. 关闭连接。
  8. 程序结束。

常用API

Driver接口

概念:
  Driver接口由数据库厂家提供。在编程中要连接数据库,必须先装载特定厂商的数据库驱动程序,不同的数据库有不同的装载方法。
用到的实现类:JAVA.lang.Class
方法:
装载驱动:Class.forName(String className);
返回与 给定字符串名的类或接口 相关联的Class对象。 ---加载JDBC驱动时使用

装载MySql驱动:Class.forName("com.mysql.jdbc.Driver");

Connection接口

作用:
与特定数据库的连接,和创建向数据库发送sql的statement对象。
用到的实现类:JAVA.sql.DruverMannager
连接数据库方法:
Connction getConnection (String url ,String user, String password)
---获取url对应的数据库的链接

连接MySql数据库:
Connection conn = DriverManager.getConnection("jdbc:mysql://host:port/database", "user", "password");

创建statement对象方法:
createStatement():创建向数据库发送sql的statement对象。
prepareStatement(String sql) :创建向数据库发送预编译sql的PrepareSatement对象。

Statement接口

作用:
用于执行SQL语句并返回它所生成结果的对象。

用到的实现类:
Statement:
由createStatement创建,用于发送简单的SQL语句(不带参数)。
PreparedStatement :
继承自Statement接口,由preparedStatement创建,用于发送含有一个或多个参数的SQL语句。PreparedStatement对象比Statement对象的效率更高,并且可以防止SQL注入,一般都使用PreparedStatement。

常用Statement方法:
executeQuery(String sql):运行select语句,返回ResultSet结果集。
executeUpdate(String sql):运行insert/update/delete操作,返回更新的行数。

ResultSet接口

作用:
提供检索不同类型字段的方法。
用到的实现类:ResultSet

获取信息的方法
getString(int index)、getString(String columnName):获得在数据库里是varchar、char等类型的数据对象。
getFloat(int index)、getFloat(String columnName):获得在数据库里是Float类型的数据对象。
getDate(int index)、getDate(String columnName):获得在数据库里是Date类型的数据。
getBoolean(int index)、getBoolean(String columnName):获得在数据库里是Boolean类型的数据。
getObject(int index)、getObject(String columnName):获取在数据库里任意类型的数据。

对结果集进行滚动的方法:
next():移动到下一行
Previous():移动到前一行
absolute(int row):移动到指定行
beforeFirst():移动resultSet的最前面。
afterLast() :移动到resultSet的最后面。

代码实现

编程步骤

  1. 加载数据库驱动:Class.forName("...")
    告知JVM使用的是哪一个数据库的驱动

  2. 连接数据库:DriverManager.getConnection(url,user,password)->con

  3. 创建SQL语句的执行者对象:con.createStatement()或者con.PreparedStatement()->st

  4. 执行sql语句:st.executeUpdate("...")或者st.executeQuery("...")
    使用执行者对象,向数据库执行SQL语句 获取到数据库的执行后的结果

  5. 处理结果

  6. 关闭SQL语句执行对象 :st.close;

  7. 关闭连接: con.close();

  8. 程序结束

基础JDBC

固定语句的JDBC管理

准备
新建JAVA project
新建lib文件夹
粘贴mysql-connector-java-5.1.18-bin.jar到lib文件夹下
在.jar下右键,选择如下
image
连接数据库+插入

package cn.sdut.text;

import static java.sql.DriverManager.getConnection;

import java.sql.Connection;
import java.sql.SQLException;

import com.mysql.jdbc.Statement;

public class JDBCText {

	public static void main(String[] args) throws ClassNotFoundException, SQLException {
		// TODO Auto-generated method stub
      //加载JDBC驱动
		Class.forName("com.mysql.jdbc.Driver");
		
		//获取数据库的链接
		Connection con = (Connection) DriverManager.getConnection("jdbc:mysql://localhost:3306/book","root","usbw");
	
		//准备SQL语句执行对象
		Statement st=(Statement) con.createStatement();
		
		// 准备SQL语句
		String sql= "insert into student values(null,'JOHN',22)";

		//执行SQL语句
		int result= st.executeUpdate(sql);
			System.out.println(result>0?"成功":"失败");
		
	    //关闭SQL语句执行对象
		st.close();
        //关闭数据库链接
		con.close();
	
	}

}

遍历输出

        //准备SQL语句
        String selectSql="select *from student";
        //执行SQL语句
        ResultSet rs = st.executeQuery(selectSql);//和增删改不一样
        //如果指针还有元素则输出
        while(rs.next()) {
        	int stuId=rs.getInt(1);
        	String stuName=rs.getString("name");
            String stuIn=rs.getString(3);
            int StuScore=rs.getInt(4);
            System.out.println(stuId+" "+stuName+" "+stuIn+" "+StuScore);
        }

单条查询:

String selectSql1 = "select *from student where id=3";
		ResultSet rs2 = st.executeQuery(selectSql1);//和增删改不一样
		System.out.println("id为3的数据为:");
		if (rs2.next()) {
			int stuId = rs2.getInt(1);
			String stuName = rs2.getString("name");
			String stuIn = rs2.getString(3);
			int StuScore = rs2.getInt(4);
			System.out.println(stuId + " " + stuName + " " + stuIn + " " + StuScore);
		} else {
			System.out.println("没有查询到id=3的数据");
		}

删除

		// 删除id为1的数据
		String deleteSql1 = "delete from student where id=1";
		int deleteResult1 = st.executeUpdate(deleteSql1);
		System.out.println(deleteResult1 > 0 ? "id为1的数据删除成功" : "id为1的数据删除失败(可能是因为id为1的数据不存在)");

更新数据

// 修改id=2的数据
		String updataSql1 = "update student set name='山东理工' where id=2";
		int updataResult1 = st.executeUpdate(updataSql1);
		System.out.println(updataResult1 > 0 ? "修改id为2的数据成功" : "修改id为2的数据失败(可能是因为id为2的数据不存在)");

输入变量JDBC

方法1:
更改准备SQL语句阶段

// 准备SQL语句
		String name="里斯";
		int age=20;
		
		String sql= "insert into student values(null,'"+name+"',"+age+")";

但是比较复杂。
方法2:
PreparedStatement代替Statement
优点

  • 速度快
  • 可以防止SQL注入
    image
package cn.sdut.text;

import static java.sql.DriverManager.getConnection;

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;

import com.mysql.jdbc.PreparedStatement;
import com.mysql.jdbc.Statement;

public class JDBCText {

	public static void main(String[] args) throws ClassNotFoundException, SQLException {
		// TODO Auto-generated method stub
      //加载JDBC驱动
		Class.forName("com.mysql.jdbc.Driver");
		
		//获取数据库的链接
		Connection con = getConnection("jdbc:mysql://localhost:3306/book","root","usbw");
	
		//准备SQL语句执行对象
		java.sql.PreparedStatement pst=null;
		
		// 准备SQL语句
		String name="里斯22";
		int age=20;
		String sq14="insert into student values(null,?,?)";
		pst=(PreparedStatement) con.prepareStatement(sq14);
		pst.setString(1,name);
		pst.setInt(2, age);
		String sql="select * from student";
		String sql3="select * from student where id=?";
		
		//执行SQL语句
		int result= pst.executeUpdate();
			System.out.println(result>0?"成功":"失败");
		
			
			//遍历输出
			pst=con.prepareStatement(sql);
			ResultSet rs=pst.executeQuery();
			while(rs.next()) {
			int id1=rs.getInt(1);
			String name1=rs.getString("name");
			int age1=rs.getInt(3);
			System.out.println(id1+" "+name1+" "+age1);
			}
		System.out.println("-----------------------");
			
			pst=con.prepareStatement(sql3);
			pst.setInt(1, 4);
			ResultSet rs1 = pst.executeQuery();
			if(rs1.next()) {
				int id1=rs1.getInt(1);
				String name1=rs1.getString("name");
				int age1=rs1.getInt(3);
				System.out.println(id1+" "+name1+" "+age1);
			}
			else System.out.println("无此人");
			
			rs.close();
			rs1.close();
	    //关闭SQL语句执行对象
			pst.close();
        //关闭数据库链接
		con.close();
	
	}

}

image
image

面向对象JDBC

//数据类

package Work;

public class Student {
      private int id=-1;
      private String name=null;
      private String date=null;
      private int score=-1;
	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 getDate() {
		return date;
	}
	public void setDate(String date) {
		this.date = date;
	}
	public int getScore() {
		return score;
	}
	public void setScore(int score) {
		this.score = score;
	}
	public Student(int id, String name, String date, int score) {
		super();
		this.id = id;
		this.name = name;
		this.date = date;
		this.score = score;
	}
	public Student() {
		super();
		
	}
	@Override
	public String toString() {
		return "Student [id=" + id + ", name=" + name + ", date=" + date + ", score=" + score + "]";
	}
      
      
}

//面向对象JDBC类

package Work;

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

import com.mysql.jdbc.Connection;
import com.mysql.jdbc.PreparedStatement;

public class ClassJdbc {
	Connection con;
	PreparedStatement pst;
	ResultSet rs;

	// 获取数据库连接
	public Connection getConnection() throws Exception {
		// 加载jdbc驱动
		Class.forName("com.mysql.jdbc.Driver");
		// 获取数据库的连接
		Connection con = (Connection) DriverManager.getConnection(
				"jdbc:mysql://localhost:3306/book?useunicode=true&characterEncoding=utf-8", "root", "usbw");

		return con;
	}

	public int addStu(Student stu) throws Exception {
		con = getConnection();
		String sql = "insert into student values (null,?,?,?)";
		pst = (PreparedStatement) con.prepareStatement(sql);
		pst.setString(1, stu.getName());
		pst.setString(2, stu.getDate());
		pst.setInt(3, stu.getScore());
		int result = pst.executeUpdate();
		End();
		return result;
		
	}

	// 删除对象
	public int deleteStu(int id) throws Exception {
		con = getConnection();
		String sql = "delete from student where id=?";
		pst = (PreparedStatement) con.prepareStatement(sql);
		pst.setInt(1, id);
		int result = pst.executeUpdate();
		End();
		return result;
	}

	// 更新数据
	public int updateStu(Student stu) throws Exception {
		
		String sql = "update student set name=?,schoolin=?,score=? where id=?";
		//先查询到待更新的数据,(因为每次不一定要更新全部数据)
		Student data = getStu(stu.getId());
		//获取数据库连接
		con = getConnection();
		pst = (PreparedStatement) con.prepareStatement(sql);
		//如果更新的数据某项为空,则设置原来的数据。(初始化默认为空)
	if (stu.getName() != null) {
			pst.setString(1, stu.getName());
		}
		else {
			pst.setString(1, data.getName());
		}
	//如果更新的数据某项为空,则设置原来的数据。(初始化默认为空)
		if (stu.getDate() != null) {
			pst.setString(2, stu.getDate());
		} else {
			pst.setString(2, data.getDate());
		}
		//如果更新的数据某项为空,则设置原来的数据。(初始化默认为-1)
		if (stu.getScore() != -1) {
			pst.setInt(3, stu.getScore());
		} else {
			pst.setInt(3, data.getScore());
		}
       //因为更新数据id一定存在,所以不需要判断
		pst.setInt(4, stu.getId());
		int result = pst.executeUpdate();
		End();
		return result;
	}

	// 遍历输出数据
	public List<Student> getStuAll() throws Exception {
		con = getConnection();
		//利用List储存查询到的数据
		List<Student> stuAll = new ArrayList<Student>();
		String sql = "select *from student";
		pst = (PreparedStatement) con.prepareStatement(sql);
		rs = pst.executeQuery();
		//如果指针不为空,则代表有元素,继续向下处理数据
		while (rs.next()) {
			//处理数据
			Student stu = new Student();
			stu.setId(rs.getInt(1));
			stu.setName(rs.getString(2));
			stu.setDate(rs.getString(3));
			stu.setScore(rs.getInt(4));
			//将数据存入List
			stuAll.add(stu);
		}
		End();
		return stuAll;
	}

	// 依据id,查询数据
	public Student getStu(int id) throws Exception {
		con = getConnection();
		Student stu = new Student();
		String sql = "select *from student where id=?";
		pst = (PreparedStatement) con.prepareStatement(sql);
		pst.setInt(1, id);
		rs = pst.executeQuery();
		if (rs.next()) {
			stu.setId(rs.getInt(1));
			stu.setName(rs.getString(2));
			stu.setDate(rs.getString(3));
			stu.setScore(rs.getInt(4));
		} else
			stu.setId(-1);//如果id为-1,代表数据未查询到
		End();
		return stu;
	}

	// 关闭对象,收尾。
	public void End() throws SQLException {
		if (rs != null)
			rs.close();
		if (pst != null)
			pst.close();
		if (con != null)
			con.close();

	}

	public static void main(String[] args) throws Exception {
		ClassJdbc jdbc = new ClassJdbc();
		
		// 准备插入数据
		Student addStu1 = new Student(4, "李三", "2017-09-01", 96);
		Student addStu2 = new Student(5, "王四", "2018-09-01", 97);
		Student addStu3 = new Student(6, "长武", "2019-09-01", 98);
		// 插入默认数据
		int result1 = jdbc.addStu(addStu1);
		System.out.println(result1 > 0 ? "语句1插入成功" : "语句1插入失败");
		int result2 = jdbc.addStu(addStu2);
		System.out.println(result2 > 0 ? "语句1插入成功" : "语句1插入失败");
		int result3 = jdbc.addStu(addStu3);
		System.out.println(result3 > 0 ? "语句1插入成功" : "语句1插入失败");

		// 删除id为1的数据
		int deleteResult1 = jdbc.deleteStu(1);
		System.out.println(deleteResult1 > 0 ? "id为1的数据删除成功" : "id为1的数据删除失败(可能是因为id为1的数据不存在)");
		// 显示所有记录
		List<Student> stuAll = jdbc.getStuAll();
		if (stuAll != null) {
			System.out.println("此时数据库的全部数据为");
			for (Student t : stuAll) {
				System.out.println(t);
			}
		} else {
			System.out.println("此时数据库没有数据");
		}

		// 修改id=2的数据
		Student updataStu = new Student();
		updataStu.setName("山东理工");
		updataStu.setId(2);
		int updataResult1 = jdbc.updateStu(updataStu);
		System.out.println(updataResult1 > 0 ? "修改id为2的数据成功" : "修改id为2的数据失败(可能是因为id为2的数据不存在)");

		// 查询表中id=3的记录并显示
		Student selectStu = jdbc.getStu(3);

		if (selectStu.getId() != -1) {
			System.out.println("id为3的数据为:" + selectStu);
		} else {
			System.out.println("没有查询到id=3的数据");
		}
	}
}

面向对象JDBC升级改造

将con封装成父类

package cn.sdut.dao;

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

import com.mysql.jdbc.PreparedStatement;

public class BaseDao {
	protected Connection con;
    protected	PreparedStatement pst;
    protected 	ResultSet rs;
	//获得数据库的链接
	public Connection getConnection() throws SQLException, ClassNotFoundException {
		// 加载JDBC驱动
		Class.forName("com.mysql.jdbc.Driver");

		// 获取数据库的链接
		Connection con = DriverManager.getConnection("jdbc:mysql://localhost:3306/book", "root", "usbw");

		return con;
	}
	
	//关闭对象
		public void closeAll() throws SQLException {
			if(rs!=null) {
				rs.close();
			}
			if(pst!=null) {
				pst.close();
			}
			if(con!=null) {
				con.close();
			}
		}
	

}

面向接口编程是把客户的业务功能提取出来,作为接口。业务的具体实现通过该接口的实现类来完成。当客户需求变化时,只需编写该业务逻辑的新的实现类,或者通过更改配置文件中该接口的实现类就可以完成需求,不需要改写现有代码,减少对系统的影响。采用面向接口编程的好处包括:业务逻辑清晰、代码易懂、降低了程序的耦合性、方便扩展、可维护性强。

子类记得继承
public class StudentDao extends BaseDao{

将方法封装成接口

package cn.sdut.dao;
import java.sql.SQLException;
import java.util.List;

import  cn.sdut.po.*;
public interface StudentDaoInterface {
	public int addStudent (Student student) throws ClassNotFoundException, SQLException ;
	public int delStudent (int id) throws ClassNotFoundException, SQLException;
	public int updataStudent(Student student) throws SQLException, ClassNotFoundException;
	public List<Student> getStudent () throws SQLException, ClassNotFoundException;
    public Student getStudentById(int id) throws SQLException, ClassNotFoundException;
}

注意引入实现方法
public class StudentDao extends BaseDao implements StudentDaoInterface{

三层架构

image

访问层/界面层(用户与程序的交互)
^
||
业务逻辑层(判断数据的合法性)
^
||
数据库访问层(访问数据库)

界面层

package cn.sdut.aview;


import java.util.Scanner;
import java.util.List;
import cn.sdut.base.BookBiz;
import cn.sdut.po.Book;

public class Main {
        public static void main(String[] args)  {
			Scanner sc=new Scanner(System.in);
			String name =sc.next();
			double price=sc.nextDouble();
			int count=sc.nextInt();
			
			BookBiz biz=new BookBiz();
			Book addbook=new Book(1,name,price,count);//id为 系统自动赋值,故随意输入
			try {
				int reulst=biz.addBook(addbook);
				
				 List<Book> booklist=biz.selectAll();
				 for(Book b:booklist) {
					 System.out.println(b);
				 }
			}
			catch (Exception e) {
				// TODO: handle exception
				//e.printStackTrace();
				System.out.println("dadsdsdsa");
			}
			sc.close();
		}
}

业务逻辑层

package cn.sdut.base;

import java.sql.SQLException;
import java.util.List;

import cn.sdut.dao.BookDao;
import cn.sdut.po.Book;

public class BookBiz {
	BookDao bookDao = new BookDao();

	public int addBook(Book book) throws SQLException {
		
		int result = 0;
		if (book.getPrice() > 0 && book.getCount() > 0) {
			result = bookDao.addBook(book);
		}
		return result;
	}
	//和用户无关,故只需过度一下
	public List<Book> selectAll() throws SQLException {
		return bookDao.selectAll();
	}
}

数据访问层

上面JDBC便是。

事务

定义:
指逻辑上的一组操作,组成这组操作的各个单元,要么全部成功,要么全部失败。
特性

  1. 原子性(atomicity) 一个事务是一个不可分割的工作单位,事务中包括的诸操作要么都做,要么都不做。
  2. 一致性(consistency) 事务必须是使数据库从一个一致性状态变到另一个一致性状态。一致性与原子性是密切相关的。
  3. 隔离性(isolation) 一个事务的执行不能被其他事务干扰。即一个事务内部的操作及使用的数据对并发的其他事务是隔离的,并发执行的各个事务之间不能互相干扰。
  4. 持久性(durability) 持久性也称永久性(permanence),指一个事务一旦提交,它对数据库中数据的改变就应该是永久性的。接下来的其他操作或故障不应该对其有任何影响。

实现方法

在JDBC中,通过Connection对象进行事务管理,默认是自动提交事务。
如果人工设计事务需要:

  • 手工将自动提交关闭(con.setAutoCommit(false); ),

  • 通过commit方法进行提交,

  • rollback方法进行回滚,如果不提交,则数据不会真正的插入到数据库中。

    public boolean transactionTset (Student student ,int id) throws ClassNotFoundException, SQLException {
    	con=getConnection();
    	con.setAutoCommit(false);
    	//设置SQL的非自动提交,并开启事务
    	//不会自动提交,而是进入缓冲区
    	
    	//增加一个学生
    	
    	String sql1= "insert into student values(null,?,?)";
    	pst=(PreparedStatement) con.prepareStatement(sql1);
    	pst.setString(1, student.getName()) ;
    	pst.setInt(2, student.getAge());
    	int resutl1=pst.executeUpdate();
    	//删除一个学生
    	
    	String sql="updade student set name?,age=?,where id=?";
    	pst=(PreparedStatement) con.prepareStatement(sql);
    	pst.setString(1, student.getName());
    	pst.setInt(2, student.getAge());
    	pst.setInt(3, student.getId());
    	int result2=pst.executeUpdate();
    	
    	int result=resutl1*result2;
       if(result==1) {
    	 con.commit();//提交事务
    	 return true;
       }
       else 
       {
    	   con.rollback();//回滚事务
    	   return false;
       }
    
    }
    
```java
	public void testtransactionTset() throws ClassNotFoundException, SQLException {
		Student stu=new Student();
		stu.setName("fs");
		stu.setAge(1);
		stu.setId(11);
		int id=11;
		boolean result=dao.transactionTset (stu ,id);
		assertEquals(result, true);
		//断言他是对的
	}
posted @ 2021-11-28 17:32  kingwzun  阅读(130)  评论(0编辑  收藏  举报