JDBC技术

9 篇文章 0 订阅

JDBC技术

本文是基于Windows 10系统环境,学习和使用JDBC技术:

  • Windows 10
  • MyEclipse 10
  • MySQL 5.5

一、JDBC的基本概念

(1) JDBC的定义

  • 使用java代码(程序)去发送sql语句的技术

(2) JDBC发送sql的前提

  • 连接mysql数据库服务器
  • IP地址
  • 端口号
  • 用户名
  • 密码

二、JDBC的使用

(1) JDBC的连接MySQL数据库

  • java代码
package com.inspur.a_jdbc;

import java.sql.Connection;
import java.sql.Driver;
import java.sql.SQLException;
import java.util.Properties;

import org.junit.Test;

/**
 * ClassName: Demo1
 * Function: TODO ADD FUNCTION
 * @author: xuzheng
 * date: 2019-4-29 上午8:18:10
 */
public class Demo1 {
	             //url:   jdbc协议:数据库子协议:主机:端口/连接的数据库
	private String url = "jdbc:mysql://172.30.12.59:3306/day15";
	private String user = "root";
	private String password = "123456";
	
	@Test
	public void test1() throws Exception{
		//1.创建驱动程序类对象
		//com.mysql.jdbc.Driver类需要导包 mysql-connector-java-5.1.7-bin.jar
		Driver driver = new com.mysql.jdbc.Driver();
		
		Properties props = new Properties();
		props.setProperty("user", user);
		props.setProperty("password", password);
		
		//2.连接数据库,返回连接对象
		Connection conn = driver.connect(url, props);
		
		System.out.println(conn);
	}
	/**
	 * 使用驱动管理器类连接数据库
	 * @throws Exception 
	 */
	@Test
	public void test2() throws Exception{
		Driver driver = new com.mysql.jdbc.Driver();
		//Driver driver2 = new com.oracle.jdbc.Driver();
		
		//1.注册驱动程序,可以注册多个驱动程序
		DriverManager.registerDriver(driver);
		//DriverManager.registerDriver(driver2);
		
		//2.连接数据库
		Connection conn = DriverManager.getConnection(url, user, password);
		
		System.out.println(conn);
	}

	/**
	 * 优化版本代码
	 * @throws Exception 
	 */
	@Test
	public void test3() throws Exception{

		//1.通过得到字节码对象的方式加载静态代码块,从而注册驱动程序
		Class.forName("com.mysql.jdbc.Driver");

		//2.连接数据库
		Connection conn = DriverManager.getConnection(url, user, password);
		
		System.out.println(conn);
	}
}
  • 可以打印出类似下面的结果,说明连接成功
    在这里插入图片描述

(2) JDBC接口核心的API

  • Driver接口类:java驱动程序接口
connection(url, properties);  // 连接数据库的方法
// url:   jdbc协议:数据库子协议:主机:端口/连接的数据库
// Properties properties= new Properties();
// properties.setProperty("user", user);
// properties.setProperty("password", password);
  • DriverManager类: 驱动管理器类,用于管理所有注册的驱动程序
registerDriver(driver)  // 注册驱动类对象
Connection getConnection(url,user,password);  // 获取连接对象
  • Connection接口类: 表示java程序和数据库的连接对象
Statement createStatement() // 创建Statement对象
PreparedStatement prepareStatement(String sql) // 创建PreparedStatement对象
CallableStatement prepareCall(String sql) // 创建CallableStatement对象
  • Statement接口类: 用于执行静态的sql语句
int executeUpdate(String sql) // 执行静态的更新sql语句(DDL,DML)
ResultSet executeQuery(String sql) // 执行的静态的查询sql语句(DQL)
  • PreparedStatement接口:用于执行预编译sql语句
int executeUpdate() // 执行预编译的更新sql语句(DDL,DML)
ResultSet executeQuery() // 执行预编译的查询sql语句(DQL)
  • CallableStatement接口:用于执行存储过程的sql语句(call xxx)
ResultSet executeQuery() // 调用存储过程的方法
  • ResultSet接口:用于封装查询出来的数据
boolean next() // 将光标移动到下一行
getXX() // 获取列的值

(3) 数据库的三类语言

  • DDL(data definition language)数据库定义语言
create alter drop
  • DML(data manipulation language)数据操纵语言
update insert delete truncate
  • DQL(data query language)数据查询语言
select show

(4) 使用statement执行sql语句

  • 执行DDL语句(创建表)
package com.inspur.b_statement;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
import org.junit.Test;
/**
 * 执行DDL语句(创建表)
 * 使用Statement对象执行静态sql语句
 */
public class Demo1 {
	
	private String url ="jdbc:mysql://172.30.12.59:3306/day15";
	private String user = "root";
	private String password = "123456";
	
	@Test
	public void test1(){
		Connection connection = null;
		Statement statement = null;
		try {
			//1.驱动注册程序
			Class.forName("com.mysql.jdbc.Driver");
			//2.获取连接对象
			connection = DriverManager.getConnection(url, user, password);
			//3.创建Statement对象
			statement = connection.createStatement();
			//4.准备sql语句
			String sql = "create table student(id int primary key auto_increment, name varchar(20), gender varchar(2))";
			//5.发送sql语句,执行sql语句,得到返回结果
			int count = statement.executeUpdate(sql);
			//6.输出
			System.out.println("影响了"+count+"行");
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			throw new RuntimeException(e);
		} finally{
			//7.关闭连接
			if(statement!=null){
				try {
					statement.close();
				} catch (Exception e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
					throw new RuntimeException(e);
				}
			}
			if(connection!=null){
				try {
					connection.close();
				} catch (Exception e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
					throw new RuntimeException(e);
				}
			}
		}
	}
}
  • 执行DML语句(插入数据)
package com.inspur.b_statement;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
import org.junit.Test;

public class Demo1 {
	private String url ="jdbc:mysql://172.30.12.59:3306/day15";
	private String user = "root";
	private String password = "123456";
	/**
	 * 使用Statement对象执行DML语句
	 */
	@Test
	public void test2(){
		Connection connection = null;
		Statement statement = null;
		try {
			//1.驱动注册程序
			Class.forName("com.mysql.jdbc.Driver");
			//2.获取连接对象
			connection = DriverManager.getConnection(url, user, password);
			//3.创建Statement对象
			statement = connection.createStatement();
			//4.准备sql语句
			String sql = "insert into student(name, gender) values('xuzheng','男')";
			//5.发送sql语句,执行sql语句,得到返回结果
			int count = statement.executeUpdate(sql);
			//6.输出
			System.out.println("影响了"+count+"行");
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			throw new RuntimeException(e);
		} finally{
			if(statement!=null){
				try {
					statement.close();
				} catch (Exception e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
					throw new RuntimeException(e);
				}
			}
			if(connection!=null){
				try {
					connection.close();
				} catch (Exception e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
					throw new RuntimeException(e);
				}
			}
		}
	}
}
  • 配置文件db.properties
url=jdbc:mysql://172.30.12.59:3306/day15
user=root
password=123456
driverClass=com.mysql.jdbc.Driver
  • 数据库工具类
package com.inspur.util;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;

/**
 * ClassName: JdbcUtil
 * Function: TODO ADD FUNCTION
 * @author: xuzheng
 * date: 2019-4-29 下午3:07:46
 */
public class JdbcUtil {
	
	private static String url = null;
	private static String user = null;
	private static String password = null;
	private static String driverClass = null;
	
	static{
		try {
			Properties properties = new Properties();
			FileInputStream inStream = new FileInputStream("./src/db.properties");
			properties.load(inStream);
			url = properties.getProperty("url");
			user = properties.getProperty("user");
			password = properties.getProperty("password");
			driverClass = properties.getProperty("driverClass");
			Class.forName(driverClass);
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			System.out.println("驱动程序注册出错");
		}
	}
	
	public static Connection getConnection(){
		try {
			Connection connection = DriverManager.getConnection(url, user, password);
			return connection;
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			throw new RuntimeException(e);
		}
	}
	
	public static void close(Connection conn, Statement stmt, ResultSet rs){
		if(rs!=null){
			try {
				rs.close();
				rs = null // 建议垃圾回收器回收资源
			} catch (SQLException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
				throw new RuntimeException(e);
			}
		}
		if(stmt!=null){
			try {
				stmt.close();
				stmt = null // 建议垃圾回收器回收资源
			} catch (SQLException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
				throw new RuntimeException(e);
			}
		}
		if(conn!=null){
			try {
				conn.close();
				conn = null // 建议垃圾回收器回收资源
			} catch (SQLException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
				throw new RuntimeException(e);
			}
		}
	}
	
	public static void close(Connection conn, Statement stmt){
		if(stmt!=null){
			try {
				stmt.close();
				stmt = null // 建议垃圾回收器回收资源
			} catch (SQLException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
				throw new RuntimeException(e);
			}
		}
		if(conn!=null){
			try {
				conn.close();
				conn = null // 建议垃圾回收器回收资源
			} catch (SQLException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
				throw new RuntimeException(e);
			}
		}
	}
}
  • 执行DQL语句(查询数据)
package com.inspur.b_statement;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import org.junit.Test;
import com.inspur.util.JdbcUtil;

/**
 * 使用Statement对象执行静态sql语句
 */
public class Demo1 {
	private String url ="jdbc:mysql://172.30.12.59:3306/day15";
	private String user = "root";
	private String password = "123456";
	/**
	 * 使用Statement对象执行DQL语句
	 */
	@Test
	public void test3(){
		Connection connection = null;
		Statement statement = null;
		try {
			//获取连接
			connection = JdbcUtil.getConnection();
			//创建Statement对象
			statement = connection.createStatement();
			//准备sql语句
			String sql = "select * from student";
			ResultSet executeQuery = statement.executeQuery(sql);
			while(executeQuery.next()){
				int id = executeQuery.getInt("id");
				String name = executeQuery.getString("name");
				String gender = executeQuery.getString("gender");
				System.out.println(id+","+name+","+gender);
			}
		} catch (Exception e) {
			e.printStackTrace();
			throw new RuntimeException(e);
		} finally{
			JdbcUtil.close(connection, statement);
		}
	}
}

(5) 使用PreparedStatement执行sql语句

  • PreparedStatement可以预防恶意的非法注入
因为sql缓存区,PreparedStatement的执行效率比Statement高
支持sql缓存区的数据库:oracle、sql
不支持sql缓存区的数据库:mysql
  • 执行增删改查
/**
 * 
 */
package com.inspur.c_prepared;

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

import org.junit.Test;

import com.inspur.util.JdbcUtil;

/**
 * PreparedStatement执行sql语句
 */
public class Demo1 {
		/*
		 * 增加操作
		 */
		@Test
		public void testInsert(){
			Connection connection = null;
			PreparedStatement prepareStatement = null;
			try {
				//1.获取连接
				connection = JdbcUtil.getConnection();
				//2.准备预编译的sql语句
				String sql = "insert into student(name,gender) values (?,?)";//一个?表示一个参数的占位符
				//3.执行预编译的sql语句
				prepareStatement = connection.prepareStatement(sql);
				//4.设置参数值
				prepareStatement.setString(1, "leifeng");
				prepareStatement.setString(2, "nv");
				//5.发送参数,执行sql
				int count = prepareStatement.executeUpdate();
				
				System.out.println(count);
			} catch (Exception e) {
				e.printStackTrace();
				throw new RuntimeException(e);
			} finally{
				JdbcUtil.close(connection, prepareStatement);
			}
		}
		/*
		 * 修改操作
		 */
		@Test
		public void testUpdate(){
			Connection connection = null;
			PreparedStatement prepareStatement = null;
			try {
				//1.获取连接
				connection = JdbcUtil.getConnection();
				//2.准备预编译的sql语句
				String sql = "update student set name=? where id=?";//一个?表示一个参数的占位符
				//3.执行预编译的sql语句
				prepareStatement = connection.prepareStatement(sql);
				//4.设置参数值
				prepareStatement.setString(1, "fenglei");
				prepareStatement.setInt(2, 4);
				//5.发送参数,执行sql
				int count = prepareStatement.executeUpdate();
				
				System.out.println(count);
			} catch (Exception e) {
				e.printStackTrace();
				throw new RuntimeException(e);
			} finally{
				JdbcUtil.close(connection, prepareStatement);
			}
		}
		/*
		 * 删除操作
		 */
		@Test
		public void testDelete(){
			Connection connection = null;
			PreparedStatement prepareStatement = null;
			try {
				//1.获取连接
				connection = JdbcUtil.getConnection();
				//2.准备预编译的sql语句
				String sql = "delete from student where id=?";//一个?表示一个参数的占位符
				//3.执行预编译的sql语句
				prepareStatement = connection.prepareStatement(sql);
				//4.设置参数值
				prepareStatement.setInt(1, 5);
				//5.发送参数,执行sql
				int count = prepareStatement.executeUpdate();
				
				System.out.println(count);
			} catch (Exception e) {
				e.printStackTrace();
				throw new RuntimeException(e);
			} finally{
				JdbcUtil.close(connection, prepareStatement);
			}
		}
		/*
		 * 查询操作
		 */
		@Test
		public void testQuery(){
			Connection connection = null;
			PreparedStatement prepareStatement = null;
			ResultSet executeQuery = null;
			try {
				//1.获取连接
				connection = JdbcUtil.getConnection();
				//2.准备预编译的sql语句
				String sql = "select * from student";//一个?表示一个参数的占位符
				//3.执行预编译的sql语句
				prepareStatement = connection.prepareStatement(sql);
				//4.执行sql
				executeQuery = prepareStatement.executeQuery();
				//5.遍历读取ResultSet
				while(executeQuery.next()){
					int id = executeQuery.getInt("id");
					String name = executeQuery.getString("name");
					String gender = executeQuery.getString("gender");
					System.out.println(id+","+name+","+gender);
				}
				
			} catch (Exception e) {
				e.printStackTrace();
				throw new RuntimeException(e);
			} finally{
				JdbcUtil.close(connection, prepareStatement, executeQuery);
			}
		}
}

(6) PreparedStatement与Statement的区别

  • 语法不同
PreparedStatement可以使用预编译的sql,而Statement只能使用静态的sql
  • 效率不同
PreparedStatement可以使用sql缓存区,效率比Statement高
  • 安全性不同
PreparedStatement可以有效防止非法sql的注入,而Statement不能防止非法sql的注入

(7) 使用CallableStatement执行存储过程

  • 带输入参数和带输入输出参数的存储过程
package com.inspur.d_callable;

import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;

import org.junit.Test;

import com.inspur.util.JdbcUtil;

/**
 * ClassName: Demo1
 * Function: TODO ADD FUNCTION
 * @author: xuzheng
 * date: 2019-4-30 上午10:03:56
 */
public class Demo1 {
	/*
	 * 执行带有输入参数的CallableStatement
	 */
	@Test
	public void test1(){
		Connection connection = null;
		CallableStatement prepareCall = null;
		
		try {
			//1.获取连接
			connection = JdbcUtil.getConnection();
			//2.准备预编译的sql语句
			String sql = "call pro_findById(?)";//一个?表示一个参数的占位符
			//3.预编译
			prepareCall = connection.prepareCall(sql);
			//4.设置参数
			prepareCall.setInt(1, 4);
			//5.发送sql
			ResultSet executeQuery = prepareCall.executeQuery();
			//6.遍历读取ResultSet
			while(executeQuery.next()){
				int id = executeQuery.getInt("id");
				String name = executeQuery.getString("name");
				String gender = executeQuery.getString("gender");
				System.out.println(id+","+name+","+gender);
			}
			
		} catch (Exception e) {
			e.printStackTrace();
			throw new RuntimeException(e);
		} finally{
			JdbcUtil.close(connection, prepareCall);
		}
	}
	/*
	 * 执行带有输入输出参数的CallableStatement
	 */
	@Test
	public void test2(){
		Connection connection = null;
		CallableStatement prepareCall = null;
		
		try {
			//1.获取连接
			connection = JdbcUtil.getConnection();
			//2.准备预编译的sql语句
			String sql = "call pro_findNameById(?,?)";//一个?表示一个参数的占位符
			//3.预编译
			prepareCall = connection.prepareCall(sql);
			//4.设置参数
			prepareCall.setInt(1, 2);
			prepareCall.registerOutParameter(2, java.sql.Types.VARCHAR);
			//5.发送sql
			prepareCall.executeQuery();
			String result = prepareCall.getString(2);
			
			System.out.println(result);
		} catch (Exception e) {
			e.printStackTrace();
			throw new RuntimeException(e);
		} finally{
			JdbcUtil.close(connection, prepareCall);
		}
	}
}

(7) 批处理

  • Statement类: 用于执行批处理的api
void addBatch(String sql)  // 添加批处理
void clearBatch()          // 清空批处理
int[] executeBatch()       // 执行批处理
  • sql批处理插入多个对象
  • User.java
package com.inspur.e_batch;
public class User {
	private String name;
	private String password;
	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;
	}
}
  • UserDao.java
package com.inspur.e_batch;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;
import com.inspur.util.JdbcUtil;

public class UserDao {
	private Connection conn;
	private PreparedStatement pstmt;
	public void save(List<User> list){
		String sql = "insert into user(name, password) values(?, ?)";
		try {
			conn = JdbcUtil.getConnection();
			pstmt = conn.prepareStatement(sql);
			
			for(int i=0;i<list.size();i++){
				User user = list.get(i);
				pstmt.setString(1, user.getName());
				pstmt.setString(2, user.getPassword());
				//添加批处理
				pstmt.addBatch();	
			}
			//执行批处理
			pstmt.executeBatch();
			//情况批处理
			pstmt.clearBatch();
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			throw new RuntimeException(e);
		} finally{
			JdbcUtil.close(conn, pstmt);
		}
	}
}
  • App.java 测试类
package com.inspur.e_batch;

import java.util.ArrayList;
import java.util.List;
import org.junit.Test;

public class App {
	@Test
	public void test1(){
		List<User> list = new ArrayList<User>();
		//创建21个用户对象
		for(int i=1;i<21;i++){
			User user = new User();
			user.setName("Jack"+i);
			user.setPassword("888"+i);
			list.add(user);
		}
		
		UserDao dao = new UserDao();
		dao.save(list);
	}
}

三、java项目和java web项目的读取路径问题

(1) 一般的读取方式

  • . 点表示java命令运行的目录
  • 在java项目下,java命令运行的目录从项目的根目录开始
  • 在web项目下,java命令运行的目录从tomcat/bin目录开始

(2) 类路径读取方式

  • /:斜杆表示classpath的根目录
  • 在java项目下,classpath的根目录从bin目录开始
  • 在web项目下,classpath的根目录从WEB-INF/classes目录开始
  • 在web项目下,如果文件db.xml放在src下,那么访问路径就是/db.properties
  • 在web项目下:
InputStream in = JdbcUtil.class.getResourceAsStream("/db.properties");
properties.load(in);

四、事务

(1) 事务的基本概念

  • 事务使指一组最小逻辑操作单元,里面有多个操作组成。 组成事务的每一部分必须要同时提交成功,如果有一个操作失败,整个操作就回滚。

(2) 事务的特性

  • 原子性是指事务是一个不可分割的工作单位,事务中的操作要么都发生,要么都不发生
  • 一致性是指事务必须使数据库从一个一致性状态变换到另外一个一致性状态。
  • 隔离性是指多个用户并发访问数据库时,数据库为每一个用户开启的事务,不能被其他事务的操作数据所干扰,多个并发事务之间要相互隔离
  • 持久性是指一个事务一旦被提交,它对数据库中数据的改变就是永久性的,接下来即使数据库发生故障也不应该对其有任何影响

(3) 事务的案例——转账

  • Connection类: 用于执行事务的api
void setAutoCommit(false/true)  // 设置自动提交
void rollback()          		// 回滚
void commit()       			// 手动提交
Savepoint setSavepoint(String name) // 创建一个保存点
a. 转账—不回滚到保存点
  • AccountDao.java
package com.inspur.f_transaction;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import com.inspur.util.JdbcUtil;

public class AccountDao {
	private Connection conn;
	private PreparedStatement pstmt;
	public void transaction(){
		try {
			String sql_zs = "update account set money=money+1000 where name='xu'";
			String sql_ls = "update account set money=money-1000 where name='wang'";
			
			conn = JdbcUtil.getConnection();
			conn.setAutoCommit(false);
			pstmt = conn.prepareStatement(sql_zs);
			int count1 = pstmt.executeUpdate();
			System.out.println(count1);
			
			pstmt = conn.prepareStatement(sql_ls);
			int count2 = pstmt.executeUpdate();
			System.out.println(count2);
			
		} catch (Exception e) {
			// TODO Auto-generated catch block
			try {
				conn.rollback();
			} catch (SQLException e1) {
				// TODO Auto-generated catch block
				e1.printStackTrace();
			}
			e.printStackTrace();
			//throw new RuntimeException(e);
		} finally{
			try {
				conn.commit();
				JdbcUtil.close(conn, pstmt);
			} catch (SQLException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}	
		}
	}
}
  • Demo1.java测试类
package com.inspur.f_transaction;
import org.junit.Test;

public class Demo1 {
	@Test
	public void test1(){
		AccountDao dao = new AccountDao();
		dao.transaction();
	}
}
b. 转账—回滚保存点
  • AccountDao.java
package com.inspur.f_transaction;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.sql.Savepoint;
import com.inspur.util.JdbcUtil;

public class AccountDao {
	private Connection conn;
	private PreparedStatement pstmt;
	Savepoint sp = null;
	public void transaction(){
		try {
			String sql_zs1 = "update account set money=money+1000 where name='xu'";
			String sql_ls1 = "update account set money=money-1000 where name='wang'";
			String sql_zs2 = "update account set money=money+500 where name='xu'";
			String sql_ls2 = "update account set money=money-500 where name='wang'";	
			conn = JdbcUtil.getConnection();
			conn.setAutoCommit(false);
			//第一次转账
			pstmt = conn.prepareStatement(sql_zs1);
			int count1 = pstmt.executeUpdate();
			System.out.println(count1);
			
			pstmt = conn.prepareStatement(sql_ls1);
			int count2 = pstmt.executeUpdate();
			System.out.println(count2);
			
			//定义个保存点,回滚
			sp = conn.setSavepoint();
			
			//第二次转账
			pstmt = conn.prepareStatement(sql_zs2);
			int count3 = pstmt.executeUpdate();
			System.out.println(count3);
			
			pstmt = conn.prepareStatement(sql_ls2);
			int count4 = pstmt.executeUpdate();
			System.out.println(count4);
			
		} catch (Exception e) {
			// TODO Auto-generated catch block
			try {
				if(sp!=null){
					conn.rollback(sp);
				} else{
					conn.rollback();
				}
			} catch (SQLException e1) {
				// TODO Auto-generated catch block
				e1.printStackTrace();
			}
			e.printStackTrace();
			//throw new RuntimeException(e);
		} finally{
			try {
				conn.commit();
				JdbcUtil.close(conn, pstmt);
			} catch (SQLException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}	
		}
	}
}
  • Demo1.java测试类
package com.inspur.f_transaction;
import org.junit.Test;

public class Demo1 {
	@Test
	public void test1(){
		AccountDao dao = new AccountDao();
		dao.transaction();
	}
}

四、构建一个持久层

(1) 更新的通用方法

  • BaseDao类
/**
 * 
 */
package com.inspur.util;

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

/**
 * ClassName: BaseDao
 * Function: TODO ADD FUNCTION
 * @author: xuzheng
 * date: 2019-5-5 下午8:14:31
 */
public class BaseDao {
	private Connection conn;
	private PreparedStatement pstmt;
	/*
	 * 更新的通用方法
	 * @param sql 更新的sql语句(update insert delete)
	 * @param paramsValue sql语句中占位符对应的值(如果没有,则传入null)
	 */
	public void update(String sql, Object[] paramsValue){
		try {
			//获取连接
			conn = JdbcUtil.getConnection();
			//创建执行命令的pstmt对象
			pstmt = conn.prepareStatement(sql);
			//参数元数据,得到占位符参数的个数
			int count = pstmt.getParameterMetaData().getParameterCount();
			if(paramsValue!=null && paramsValue.length>0){
				//循环给参数赋值
				for(int i=0;i<count;i++){
					pstmt.setObject(i+1 , paramsValue[i]);
				}
			}
			//执行更新
			pstmt.executeUpdate();
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			throw new RuntimeException(e);
		} finally{
			JdbcUtil.close(conn, pstmt);
		}
	}
}
  • AdminDao类
/**
 * 
 */
package com.inspur.b_metadata;

import com.inspur.util.BaseDao;

/**
 * ClassName: AdminDao
 * Function: TODO ADD FUNCTION
 * @author: xuzheng
 * date: 2019-5-5 ÏÂÎç8:33:21
 */
public class AdminDao extends BaseDao {
	public void delete(int id){
		String sql = "delete from user where id=?";
		Object[] paramsValue ={id};
		super.update(sql, paramsValue);
	}
	
	public void save(Admin admin){
		String sql = "insert into user(name,password) values(?,?)";
		Object[] paramsValue ={admin.getName(),admin.getPassword()};
		super.update(sql, paramsValue);
	}
}

(1) 查询的通用方法

  • BaseDao类
/**
 * 
 */
package com.inspur.util;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

/**
 * ClassName: BaseDao
 * Function: TODO ADD FUNCTION
 * @author: xuzheng
 * date: 2019-5-5 下午8:14:31
 */
public class BaseDao {
	private Connection conn;
	private PreparedStatement pstmt;
	private ResultSet rs;
	/*
	 * 更新的通用方法
	 * @param sql 更新的sql语句(update insert delete)
	 * @param paramsValue sql语句中占位符对应的值(如果没有,则传入null)
	 */
	public void update(String sql, Object[] paramsValue){
		try {
			//获取连接
			conn = JdbcUtil.getConnection();
			//创建执行命令的pstmt对象
			pstmt = conn.prepareStatement(sql);
			//参数元数据,得到占位符参数的个数
			int count = pstmt.getParameterMetaData().getParameterCount();
			if(paramsValue!=null && paramsValue.length>0){
				//循环给参数赋值
				for(int i=0;i<count;i++){
					pstmt.setObject(i+1 , paramsValue[i]);
				}
			}
			//执行更新
			pstmt.executeUpdate();
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			throw new RuntimeException(e);
		} finally{
			JdbcUtil.close(conn, pstmt);
		}
	}
	public <T> List<T> query(String sql, Object[] paramsValue, Class<T> clazz){
		try {
			//返回的集合 
			List<T> list = new ArrayList<T>();
			T t = null;
			//获取连接
			conn = JdbcUtil.getConnection();
			//创建执行命令的pstmt对象
			pstmt = conn.prepareStatement(sql);
			//获取占位符参数的个数,并设置每个参数的值
			int count = pstmt.getParameterMetaData().getParameterCount();
			if(paramsValue!=null && paramsValue.length>0){
				//循环给参数赋值
				for(int i=0;i<count;i++){
					pstmt.setObject(i+1 , paramsValue[i]);
				}
			}
			//执行查询
			ResultSet rs = pstmt.executeQuery();
			//获取结果集元数据
			ResultSetMetaData metaData = rs.getMetaData();
			//获取列的个数
			int columnCount = metaData.getColumnCount();
			//遍历rs
			while(rs.next()){
				//要封装的对象
				t = clazz.newInstance();
				//遍历每一行的每一列,封装数据
				for(int i=0;i<columnCount;i++){
					//获取每一列的名称,
					String columnName = metaData.getColumnName(i+1);
					//获取每一列的名称和对应的值,
					Object columnValue = rs.getObject(columnName);
					//封装,设置到对象的属性中
					BeanUtils.copyProperty(t, columnName, columnValue);
				}
				list.add(t);
			}
			
			return list;
		} catch (Exception e) {
			throw new RuntimeException(e);
		} finally {
			JdbcUtil.close(conn, pstmt, rs);
		}
	}
}
  • AdminDao类
/**
 * 
 */
package com.inspur.b_metadata;

import java.util.List;

import com.inspur.util.BaseDao;

/**
 * ClassName: AdminDao
 * Function: TODO ADD FUNCTION
 * @author: xuzheng
 * date: 2019-5-5 下午8:33:21
 */
public class AdminDao extends BaseDao {
	//删除
	public void delete(int id){
		String sql = "delete from user where id=?";
		Object[] paramsValue ={id};
		super.update(sql, paramsValue);
	}
	//插入
	public void save(Admin admin){
		String sql = "insert into user(name,password) values(?,?)";
		Object[] paramsValue ={admin.getName(),admin.getPassword()};
		super.update(sql, paramsValue);
	}
	//查询
	public List<Admin> getAll(){
		String sql = "select * from user";
		return super.query(sql, null, Admin.class);
	}
	//根据条件查询(主键)
	public Admin findById(int id){
		String sql = "select * from user where id=?";
		List<Admin> list = super.query(sql, new Object[]{id}, Admin.class);
		if(list!=null && list.size()>0){
			return list.get(0)
		} else{
			return null;
		}
		
	}
}

五、DBUtil的使用

(1) 更新的通用方法

  • App_update类
package cn.itcast.d_dbUtils;

import java.sql.Connection;

import org.apache.commons.dbutils.DbUtils;
import org.apache.commons.dbutils.QueryRunner;
import org.junit.Test;

import cn.itcast.utils.JdbcUtil;

public class App_update {

	private Connection conn;

	// 1. 更新
	@Test
	public void testUpdate() throws Exception {
		String sql = "delete from admin where id=?";
		// 连接对象
		conn = JdbcUtil.getConnection();

		// 创建DbUtils核心工具类对象
		QueryRunner qr = new QueryRunner();
		qr.update(conn, sql, 26);

		// 关闭
		DbUtils.close(conn);
	}

	// 2. 批处理
	@Test
	public void testBatch() throws Exception {
		String sql = "insert into admin (userName, pwd) values(?,?)";
		conn = JdbcUtil.getConnection();
		QueryRunner qr = new QueryRunner();
		// 批量删除
		qr.batch(conn, sql, new Object[][]{ {"jack1","888"},{"jack2","999"}  });
		
		// 关闭
		conn.close();
	}
}

(2) 查询的通用方法

  • App_query类
/**
 * 
 */
package com.inspur.d_dbUtil;

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;
import java.util.Map;

import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.ResultSetHandler;
import org.apache.commons.dbutils.handlers.ArrayHandler;
import org.apache.commons.dbutils.handlers.ArrayListHandler;
import org.apache.commons.dbutils.handlers.BeanHandler;
import org.apache.commons.dbutils.handlers.BeanListHandler;
import org.apache.commons.dbutils.handlers.MapHandler;
import org.apache.commons.dbutils.handlers.ScalarHandler;
import org.junit.Test;
import com.inspur.b_metadata.Admin;
import com.inspur.util.JdbcUtil;

/**
 * ClassName: App_query
 * Function: TODO ADD FUNCTION
 * @author: xuzheng
 * date: 2019-5-6 上午8:14:17
 */
public class App_query {
	private Connection conn;
	/*
	 * 查询,查询返回单个对象
	 */
	@Test
	public void testBeanHandler() throws Exception{
		//获取连接
		conn = JdbcUtil.getConnection();
		String sql ="select * from user where id=?";
		//创建dbUtil核心工具类对象
		QueryRunner qr = new QueryRunner();
		//查询返回单个对象
		Admin admin = qr.query(conn, sql,new BeanHandler<Admin>(Admin.class) ,10);
		
		System.out.println(admin);
		conn.close();
	}
	/*
	 * 查询,返回list集合,集合元素是指定的对象
	 */
	@Test
	public void testBeanListHandler() throws Exception{
		//获取连接
		conn = JdbcUtil.getConnection();
		String sql ="select * from user";
		//创建dbUtil核心工具类对象
		QueryRunner qr = new QueryRunner();
		//查询返回单个对象
		List<Admin> list = qr.query(conn, sql, new BeanListHandler<Admin>(Admin.class));
		
		for(Admin admin : list){
			System.out.println(admin);
		}
		conn.close();
	}
	/*
	 * 查询,返回结果的第一行,封装成对象数组,即返回object[]
	 */
	@Test
	public void testArrayHandler() throws Exception{
		//获取连接
		conn = JdbcUtil.getConnection();
		String sql ="select * from user";
		//创建dbUtil核心工具类对象
		QueryRunner qr = new QueryRunner();
		//查询返回单个对象
		Object[] obj = qr.query(conn, sql, new ArrayHandler());
		for(int i=0;i<obj.length;i++)
			System.out.println(obj[i]);
		
		conn.close();
	}
	/*
	 * 查询,把查询记录的每一行都封装成对象数组,再添加到list集合中
	 */
	@Test
	public void testArrayListHandler() throws Exception{
		//获取连接
		conn = JdbcUtil.getConnection();
		String sql ="select * from user";
		//创建dbUtil核心工具类对象
		QueryRunner qr = new QueryRunner();
		//查询返回单个对象
		List<Object[]> list = qr.query(conn, sql, new ArrayListHandler());
		for(Object[] obj : list){
			for(int i=0;i<obj.length;i++)
				System.out.print(obj[i]+" ");
			System.out.print("\n");
		}
		
		conn.close();
	}
	/*
	 * 查询,返回结果记录的第一行第一列(再聚合函数统计的时候使用)
	 */
	@Test
	public void testScalarHandler() throws Exception{
		//获取连接
		conn = JdbcUtil.getConnection();
		String sql ="select count(*) from user";
		//创建dbUtil核心工具类对象
		QueryRunner qr = new QueryRunner();
		//查询返回单个对象
		Long num = qr.query(conn, sql, new ScalarHandler<Long>());
		
		System.out.print(num);
		
		
		conn.close();
	}
	/*
	 * 查询,返回结果记录的第一条记录,封装为map
	 */
	@Test
	public void testMapHandler() throws Exception{
		//获取连接
		conn = JdbcUtil.getConnection();
		String sql ="select * from user where id=30";
		//创建dbUtil核心工具类对象
		QueryRunner qr = new QueryRunner();
		//查询返回单个对象
		Map<String, Object> map = qr.query(conn, sql, new MapHandler());
		System.out.print(map);
		conn.close();
	}
}

六、BeanUtil的使用

  • Admin类
package com.inspur.a_beans;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.beanutils.ConvertUtils;
import org.apache.commons.beanutils.Converter;
import org.apache.commons.beanutils.locale.converters.DateLocaleConverter;
import org.junit.Test;

public class App {

	//1. 对javabean的基本操作
	@Test
	public void test1() throws Exception {
		
		// a. 基本操作
		Admin admin = new Admin();
//		admin.setUserName("Jack");
//		admin.setPwd("999");
		
		// b. BeanUtils组件实现对象属性的拷贝
		BeanUtils.copyProperty(admin, "userName", "jack");
		BeanUtils.setProperty(admin, "age", 18);
		
		// 总结1: 对于基本数据类型,会自动进行类型转换!
		
		
		// c. 对象的拷贝
		Admin newAdmin = new Admin();
		BeanUtils.copyProperties(newAdmin, admin);
		
		// d. map数据,拷贝到对象中
		Admin adminMap = new Admin();
		Map<String,Object> map = new HashMap<String,Object>();
		map.put("userName", "Jerry");
		map.put("age", 29);
		// 注意:map中的key要与javabean的属性名称一致
		BeanUtils.populate(adminMap, map);
		
		// 测试
		System.out.println(adminMap.getUserName());
		System.out.println(adminMap.getAge());
	}
	
	
	//2. 自定义日期类型转换器
	@Test
	public void test2() throws Exception {
		// 模拟表单数据
		String name = "jack";
		String age = "20";
		String birth = "   ";
		
		// 对象
		Admin admin = new Admin();
		
		// 注册日期类型转换器:1, 自定义的方式
		ConvertUtils.register(new Converter() {
			// 转换的内部实现方法,需要重写
			@Override
			public Object convert(Class type, Object value) {
				
				// 判断
				if (type != Date.class) {
					return null;
				}
				if (value == null || "".equals(value.toString().trim())) {
					return null;
				}
				
				
				try {
					// 字符串转换为日期
					SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
					return sdf.parse(value.toString());
				} catch (ParseException e) {
					throw new RuntimeException(e);
				}
			}
		},Date.class);
		
		
		
		// 把表单提交的数据,封装到对象中
		BeanUtils.copyProperty(admin, "userName", name);
		BeanUtils.copyProperty(admin, "age", age);
		BeanUtils.copyProperty(admin, "birth", birth);
		
		//------ 测试------
		System.out.println(admin);
	}
	
	//2. 使用提供的日期类型转换器工具类
	@Test
	public void test3() throws Exception {
		// 模拟表单数据
		String name = "userName";
		String age = "20";
		String birth = null;
		
		// 对象
		Admin admin = new Admin();
		
		// 注册日期类型转换器:2, 使用组件提供的转换器工具类
		ConvertUtils.register(new DateLocaleConverter(), Date.class);
				
		// 把表单提交的数据,封装到对象中
		BeanUtils.copyProperty(admin, "userName", name);
		BeanUtils.copyProperty(admin, "age", age);
		BeanUtils.copyProperty(admin, "birth", birth);
		
		//------ 测试------
		System.out.println(admin);
	}
}
  • App类
package com.inspur.a_beans;

import java.util.Date;

/**
 * 1. 实体类设计
 * @author xuzheng
 *
 */
public class Admin {

	private int id;
	private String userName;
	private String pwd;
	private int age;
	private Date birth;
	
	
	
	public Date getBirth() {
		return birth;
	}
	public void setBirth(Date birth) {
		this.birth = birth;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	public String getPwd() {
		return pwd;
	}
	public void setPwd(String pwd) {
		this.pwd = pwd;
	}
	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
	public String getUserName() {
		return userName;
	}
	public void setUserName(String userName) {
		this.userName = userName;
	}
	@Override
	public String toString() {
		return "Admin [age=" + age + ", birth=" + birth + ", id=" + id
				+ ", pwd=" + pwd + ", userName=" + userName + "]";
	}
}

七、JdbcUtil的封装

  • JdbcUtil类
package com.inspur.utils;

import java.io.InputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;

/**
 * ClassName: JdbcUtil
 * Function: TODO ADD FUNCTION
 * @author: xuzheng
 * date: 2019-4-29 下午3:07:46
 */
public class JdbcUtil {
	
	private static String url = null;
	private static String user = null;
	private static String password = null;
	private static String driverClass = null;
	
	static{
		try {
			Properties props = new Properties();
			// 文件存放在web项目的src目录下
			InputStream in = JdbcUtil.class.getResourceAsStream("/db.properties");
			props.load(in);
			url = props.getProperty("url");
			user = props.getProperty("user");
			password = props.getProperty("password");
			driverClass = props.getProperty("driverClass");
			Class.forName(driverClass);
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			System.out.println("驱动程序注册出错");
		}
	}
	
	public static Connection getConnection(){
		try {
			Connection connection = DriverManager.getConnection(url, user, password);
			return connection;
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			throw new RuntimeException(e);
		}
	}
	
	public static void close(Connection conn, Statement stmt){
		if(stmt!=null){
			try {
				stmt.close();
			} catch (SQLException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
				throw new RuntimeException(e);
			}
		}
		if(conn!=null){
			try {
				conn.close();
			} catch (SQLException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
				throw new RuntimeException(e);
			}
		}
	}
	/*
	 * close函数重载
	 */
	public static void close(Connection conn, Statement stmt, ResultSet rs){
		if(rs!=null){
			try {
				rs.close();
			} catch (SQLException e) { 
				// TODO Auto-generated catch block
				e.printStackTrace();
				throw new RuntimeException(e);
			}
		}
		if(stmt!=null){
			try {
				stmt.close();
			} catch (SQLException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
				throw new RuntimeException(e);
			}
		}
		if(conn!=null){
			try {
				conn.close();
			} catch (SQLException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
				throw new RuntimeException(e);
			}
		}
	}
}
  • 配置文件db.properties
# 文件存放在web项目的src目录下
url=jdbc:mysql://172.30.12.59:3306/day15
user=root
password=123456
driverClass=com.mysql.jdbc.Driver

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值