JDBC主要知识概括

1.JDBC是什么?

   Java DataBase Connectivity(Java语言连接数据库)

    使用java代码(程序)发送sql语句的技术,就是jdbc技术

2.JDBC的本质是什么?

    JDBC是SUN公司制定的一套接口(interface)

     接口都有调用者和实现者

   为什么要面向接口编程?

     解耦合:降低程序的耦合度,提高程序的扩展能力

     多态机制就是非常典型的:面向抽象编程

3.JDBC编程六步

接口:

      Connection:  连接对象

      Statement:   执行命令对象: 把SQL语句发送到数据库执行

      ResultSet:    (在线式)结果集接口, 必须要保持与数据库的连接!

    第一步:注册驱动(作用: 告诉java程序,即将要连接的是哪个品牌的数据库)

    第二步:获取连接(表示JVM的进程和数据库之间的通道打开了,这属于进程之间的通信,重量级                  的,使用完一定要关闭)

    第三步:获取数据库操作对象(专门执行sql语句)

    第四步:执行sql语句(DQL DML...)

    第五步:处理查询结果集(只有当第四步执行的是select语句的时候,才有第五步处理查询结果                      集)

    第六步:释放资源(使用完资源之后一定要关闭资源,JAVA和数据库属于进程之间的通信,开                     启之后一定要关闭)

 /**
	 * 执行DDL语句(创建表)
	 */
	
	public void test1(){
		Statement stmt = null;
		Connection conn = null;
		try {
			//1.驱动注册程序
			Class.forName("com.mysql.cj.jdbc.Driver");
			
			//2.获取连接对象
			conn = DriverManager.getConnection(url, user, password);
			
			//3.创建Statement
			stmt = conn.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 = stmt.executeUpdate(sql);
			
			//6.输出
			System.out.println("影响了"+count+"行!");
		} catch (Exception e) {
			e.printStackTrace();
			throw new RuntimeException(e);
		} finally{
			//7.关闭连接(顺序:后打开的先关闭)
			if(stmt!=null)
				try {
					stmt.close();
				} catch (SQLException e) {
					e.printStackTrace();
					throw new RuntimeException(e);
				}
			if(conn!=null)
				try {
					conn.close();
				} catch (SQLException e) {
					e.printStackTrace();
					throw new RuntimeException(e);
				}
		}
	}

------------------------------------------------------jdbc增强--------------------------------------------------------------- 

4.预编译sql处理(防止sql注入) 

    使用预编译SQL语句的命令对象,好处:

    ①避免了频繁sql拼接 (可以使用占位符)

    ②可以防止sql注入

   登陆模块,

      输入用户名,密码!

     注意, 要避免用户输入的恶意密码!

public class App {
	
	// 连接参数
	//private String url = "jdbc:mysql://localhost:3306/bjpowernode";
	private String url = "jdbc:mysql:///bjpowernode";
	private String user = "root";
	private String password = "root";
	
	private Connection con;
	private Statement stmt;
	private PreparedStatement pstmt;
	private ResultSet rs;
	

	// 1. 没有使用防止sql注入的案例
	@Test
	public void testLogin() {
		
		// 1.0 模拟登陆的用户名,密码
		String userName = "tom";
		//String pwd = "8881";
		String pwd = " ' or 1=1 -- ";
		
		// SQL语句
		String sql = "select * from admin where userName='"+userName+"'  and pwd='"+pwd+"' ";
		System.out.println(sql);
		try {
			// 1.1 加载驱动,创建连接
			Class.forName("com.mysql.jdbc.Driver");		
			con = DriverManager.getConnection(url, user, password);
			// 1.2 创建stmt对象
			stmt = con.createStatement();
			// 1.3 执行查询
			rs = stmt.executeQuery(sql);
			// 业务判断
			if (rs.next()) {
				System.out.println("登陆成功, 编号:" + rs.getInt("id"));
			}
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			// 1.4 关闭
			try {
				rs.close();
				stmt.close();
				con.close();
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
	}
	
	
	// 2. 使用PreparedStatement, 防止sql注入
	@Test
	public void testLogin2() {
		
		// 1.0 模拟登陆的用户名,密码
		String userName = "tom";
		//String pwd = "8881";
		String pwd = " ' or 1=1 -- ";
		
		// SQL语句
		String sql = "select * from admin where userName=?  and pwd=? ";
		try {
			// 1.1 加载驱动,创建连接
			Class.forName("com.mysql.jdbc.Driver");		
			con = DriverManager.getConnection(url, user, password);
			// 1.2 创建pstmt对象
			pstmt = con.prepareStatement(sql);   // 对sql语句预编译
			// 设置占位符值
			pstmt.setString(1, userName);
			pstmt.setString(2, pwd);
			
			// 1.3 执行
			rs = pstmt.executeQuery();
			if (rs.next()) {
				System.out.println("登陆成功," + rs.getInt("id"));
			}
			
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			// 1.4 关闭
			try {
				rs.close();
				pstmt.close();
				con.close();
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
	}
	
	
}

5.批处理

  很多时候,需要批量执行sql语句!

   需求:批量保存信息! 

   设计:

AdminDao
		Public  void  save(List<Admin list){    // 目前用这种方式
			// 循环
			// 保存  (批量保存)
		}

		Public  void  save(Admin  admin ){
			// 循环
			// 保存

技术:

|-- Statement
	批处理相关方法
		void addBatch(String sql)     添加批处理
		void clearBatch()            清空批处理
int[] executeBatch()         执行批处理

  实现:

Admin.java         实体类封装数据
	AdminDao.java      封装所有的与数据库的操作
	App.java           测试
public class Admin {

	private String userName;
	private String pwd;

public class App {
	// 测试批处理操作
	@Test
	public void testBatch() throws Exception {
		
		// 模拟数据
		List<Admin> list = new ArrayList<Admin>();
		for (int i=1; i<21; i++) {
			Admin admin = new Admin();
			admin.setUserName("Jack" + i);
			admin.setPwd("888" + i);
			list.add(admin);
		}
		
		// 保存
		AdminDao dao = new AdminDao();
		dao.save(list);
	}
}



// 封装所有的与数据库的操作
public class AdminDao {
	
	// 全局参数
	private Connection con;
	private PreparedStatement pstmt;
	private ResultSet rs;

	// 批量保存管理员
	public void save(List<Admin> list) {
		// SQL
		String sql = "INSERT INTO admin(userName,pwd) values(?,?)";
		
		try {
			
			// 获取连接
			con = JdbcUtil.getConnection();
			// 创建stmt 
			pstmt = con.prepareStatement(sql);   		// 【预编译SQL语句】
			
			for (int i=0; i<list.size(); i++) {
				Admin admin = list.get(i);
				// 设置参数
				pstmt.setString(1, admin.getUserName());
				pstmt.setString(2, admin.getPwd());
				
				// 添加批处理
				pstmt.addBatch();						// 【不需要传入SQL】
				
				// 测试:每5条执行一次批处理
				if (i % 5 == 0) {
					// 批量执行 
					pstmt.executeBatch();
					// 清空批处理
					pstmt.clearBatch();
				}
				
			}
			
			// 批量执行 
			pstmt.executeBatch();
			// 清空批处理
			pstmt.clearBatch();
			
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			JdbcUtil.closeAll(con, pstmt, rs);
		}
	}
}

6.事务

  什么是事务?

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

 事务ACID特性

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

   事务的特性:

   原子性,是一个最小逻辑操作单元 !

   一致性,事务过程中,数据处于一致状态。

   持久性, 事务一旦提交成功,对数据的更改会反映到数据库中。

   隔离性, 事务与事务之间是隔离的。

事务:

void commit() ();                    手动提交事务

void rollback() ;                    回滚(出现异常时候,所有已经执行成功的代码需要回退到事务开始前的状态。)

Savepoint setSavepoint(String name)

eg:

public class AccountDao {

	// 全局参数
	private Connection con;
	private PreparedStatement pstmt;

	// 1. 转账,没有使用事务
	public void trans1() {

		String sql_zs = "UPDATE account SET money=money-1000 WHERE accountName='张三';";
		String sql_ls = "UPDATE account SET money=money+1000 WHERE accountName='李四';";

		try {
			con = JdbcUtil.getConnection(); // 默认开启的隐士事务
			con.setAutoCommit(true);

			/*** 第一次执行SQL ***/
			pstmt = con.prepareStatement(sql_zs);
			pstmt.executeUpdate();

			/*** 第二次执行SQL ***/
			pstmt = con.prepareStatement(sql_ls);
			pstmt.executeUpdate();

		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			JdbcUtil.closeAll(con, pstmt, null);
		}

	}

	// 2. 转账,使用事务
	public void trans2() {

		String sql_zs = "UPDATE account SET money=money-1000 WHERE accountName='张三';";
		String sql_ls = "UPDATE1 account SET money=money+1000 WHERE accountName='李四';";

		try {
			con = JdbcUtil.getConnection(); // 默认开启的隐士事务
			// 一、设置事务为手动提交
			con.setAutoCommit(false);

			/*** 第一次执行SQL ***/
			pstmt = con.prepareStatement(sql_zs);
			pstmt.executeUpdate();

			/*** 第二次执行SQL ***/
			pstmt = con.prepareStatement(sql_ls);
			pstmt.executeUpdate();

		} catch (Exception e) {
			try {
				// 二、 出现异常,需要回滚事务
				con.rollback();
			} catch (SQLException e1) {
			}
			e.printStackTrace();
		} finally {
			try {
				// 三、所有的操作执行成功, 提交事务
				con.commit();
				JdbcUtil.closeAll(con, pstmt, null);
			} catch (SQLException e) {
			}
		}

	}

	// 3. 转账,使用事务, 回滚到指定的代码段
	public void trans() {
		// 定义个标记
		Savepoint sp = null;
		
		// 第一次转账
		String sql_zs1 = "UPDATE account SET money=money-1000 WHERE accountName='张三';";
		String sql_ls1 = "UPDATE account SET money=money+1000 WHERE accountName='李四';";
		
		// 第二次转账
		String sql_zs2 = "UPDATE account SET money=money-500 WHERE accountName='张三';";
		String sql_ls2 = "UPDATE1 account SET money=money+500 WHERE accountName='李四';";

		try {
			con = JdbcUtil.getConnection(); // 默认开启的隐士事务
			con.setAutoCommit(false);       // 设置事务手动提交

			/*** 第一次转账 ***/
			pstmt = con.prepareStatement(sql_zs1);
			pstmt.executeUpdate();
			pstmt = con.prepareStatement(sql_ls1);
			pstmt.executeUpdate();
			
			// 回滚到这个位置?
			sp = con.setSavepoint(); 
			
			
			/*** 第二次转账 ***/
			pstmt = con.prepareStatement(sql_zs2);
			pstmt.executeUpdate();
			pstmt = con.prepareStatement(sql_ls2);
			pstmt.executeUpdate();
			

		} catch (Exception e) {
			try {
				// 回滚 (回滚到指定的代码段)
				con.rollback(sp);
			} catch (SQLException e1) {
			}
			e.printStackTrace();
		} finally {
			try {
				// 提交
				con.commit();
			} catch (SQLException e) {
			}
			JdbcUtil.closeAll(con, pstmt, null);
		}

7.Jdbc中大文本类型的处理   

Oracle中大文本数据类型,

   Clob    长文本类型   (MySQL中不支持,使用的是text)

   Blob    二进制类型

MySQL数据库,

   Text    长文本类型

   Blob    二进制类型

Text:

public class App_text {
	
	// 全局参数
	private Connection con;
	private Statement stmt;
	private PreparedStatement pstmt;
	private ResultSet rs;
	

	@Test
	// 1. 保存大文本数据类型   ( 写longtext)
	public void testSaveText() {
		String sql = "insert into test(content) values(?)";
		try {
			// 连接
			con = JdbcUtil.getConnection();
			// pstmt 对象
			pstmt = con.prepareStatement(sql);
			// 设置参数
			// 先获取文件路径
			String path = App_text.class.getResource("tips.txt").getPath();
			FileReader reader = new FileReader(new File(path));
			pstmt.setCharacterStream(1, reader);
			
			// 执行sql
			pstmt.executeUpdate();
			
			// 关闭
			reader.close();
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			JdbcUtil.closeAll(con, pstmt, null);
		}
	}
	
	@Test
	// 2. 读取大文本数据类型   ( 读longtext)
	public void testGetAsText() {
		String sql = "select * from  test;";
		try {
			// 连接
			con = JdbcUtil.getConnection();
			// pstmt 对象
			pstmt = con.prepareStatement(sql);
			// 读取
			rs = pstmt.executeQuery();
			if (rs.next()) {
				// 获取长文本数据, 方式1:
				//Reader r = rs.getCharacterStream("content");
				
				// 获取长文本数据, 方式2:
				System.out.print(rs.getString("content"));
			}
			
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			JdbcUtil.closeAll(con, pstmt, null);
		}
	}
}

blob:

public class App_blob {
	
	// 全局参数
	private Connection con;
	private Statement stmt;
	private PreparedStatement pstmt;
	private ResultSet rs;
	

	@Test
	// 1. 二进制数据类型   ( 写longblob)
	public void testSaveText() {
		String sql = "insert into test(img) values(?)";
		try {
			// 连接
			con = JdbcUtil.getConnection();
			// pstmt 对象
			pstmt = con.prepareStatement(sql);
			// 获取图片流
			InputStream in = App_text.class.getResourceAsStream("7.jpg");
			pstmt.setBinaryStream(1, in);
			
			// 执行保存图片
			pstmt.execute();
			
			// 关闭
			in.close();
			
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			JdbcUtil.closeAll(con, pstmt, null);
		}
	}
	
	@Test
	// 2. 读取大文本数据类型   ( 读longblob)
	public void testGetAsText() {
		String sql = "select img from  test where id=2;";
		try {
			// 连接
			con = JdbcUtil.getConnection();
			// pstmt 对象
			pstmt = con.prepareStatement(sql);
			// 读取
			rs = pstmt.executeQuery();
			if (rs.next()) {
				// 获取图片流
				InputStream in = rs.getBinaryStream("img");
				// 图片输出流
				FileOutputStream out = new FileOutputStream(new File("c://1.jpg"));
				int len = -1;
				byte b[] = new byte[1024];
				while ((len = in.read(b)) != -1) {
					out.write(b, 0, len);
				}
				// 关闭
				out.close();
				in.close();
			}
			
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			JdbcUtil.closeAll(con, pstmt, null);
		}
	}
}

 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
使用JDBC访问数据库主要流程如下: 1. 加载数据库驱动程序:使用 Class.forName() 方法动态加载数据库驱动程序。 2. 建立数据库连接:使用 DriverManager.getConnection() 方法建立与数据库的连接。 3. 创建 SQL 语句:使用 Statement 或 PreparedStatement 对象创建 SQL 查询或更新语句。 4. 执行 SQL 语句:使用 Statement 或 PreparedStatement 对象执行 SQL 查询或更新语句。 5. 处理结果集:使用 ResultSet 对象处理查询结果。 6. 关闭连接:使用 Connection 对象关闭与数据库的连接。 具体代码实现可以参考以下示例: ```java import java.sql.*; public class JdbcDemo { public static void main(String[] args) { Connection conn = null; Statement stmt = null; ResultSet rs = null; try { // 加载数据库驱动程序 Class.forName("com.mysql.jdbc.Driver"); // 建立数据库连接 conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/test", "root", "123456"); // 创建 SQL 查询语句 String sql = "SELECT * FROM user"; // 创建 Statement 对象 stmt = conn.createStatement(); // 执行 SQL 查询语句 rs = stmt.executeQuery(sql); // 处理查询结果集 while (rs.next()) { System.out.println(rs.getInt("id") + "\t" + rs.getString("name") + "\t" + rs.getInt("age")); } } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (SQLException e) { e.printStackTrace(); } finally { try { // 关闭结果集 if (rs != null) rs.close(); // 关闭 Statement 对象 if (stmt != null) stmt.close(); // 关闭数据库连接 if (conn != null) conn.close(); } catch (SQLException e) { e.printStackTrace(); } } } } ```

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值