zoukankan      html  css  js  c++  java
  • JDBC核心技术(一)

    技术体系

    一、JDBC概述

    1.数据的持久化

    持久化(persistence):把数据保存到可掉电式存储设备中以供之后使用。大多数情况下,特别是企业级应用,数据
    ●持久化意味着将内存中的数据保存到硬盘上加以”固化”,而持久化的实现过程大多通过各种关系数据库来完成。
    ●持久化的主要应用是将内存中的数据存储在关系型数据库中,当然也可以存储在磁盘文件、XML数据文件中。

    2.Java中的数据存储技术

    ●在Java中,数据库存取技术可分为如下几类:

    ➢JDBC直接访问数据库
    ➢JDO (Java Data Object )技术
    ➢第三方O/R工具,如Hibernate, Mybatis等

    ●JDBC是java访问数据库的基石, JDO、Hibernate、 MyBatis等只是 更好的封装了JDBC。

    3.JDBC介绍

    ●JDBC(Java Database Connectivity)是一个独立于特定数据库 管理系统、通用的SQL数据库存取和操作的公共接口(一组API) , 定义了用来访问数据库的标准Java类库,( java.sql.javax.sql )使用这些类库可以以一种标准的方法、方便地访问数据库资源。
    ●JDBC为访问不同的数据库提供了一种统一的途径 ,为开发者屏蔽了一些细节问题。
    ●JDBC的目标是使Java程序员使用JDBC可以连接任何提供了JDBC驱动程序的数据库系统,这样就使得程序员无需对特定的数据库系统的特点有过多的了解,从而大大简化和加快了开发过程。

    4.JDBC体系结构

    JDBC接口( API)包括两个层次:

    面向应用的API : Java API ,抽象接口,供应用程序开发人员使用(连接数据库,执行SQL语句,获得结果)。
    面向数据库的API : Java Driver API ,供开发商开发数据库驱动程序用。

    JDBC是sun公司提供一套用于数据库操作的接口, java程序员只需要面向这套接口编程即可。不同的数据库厂商,需要针对这套接口,提供不同实现。不同的实现的集合,即为不同数据库的驱动。---面向接口编程

    5.JDBC程序编写步骤

    二、获取数据库连接

    package com.xudong.connection;
    
    import java.io.InputStream;
    import java.sql.Connection;
    import java.sql.Driver;
    import java.sql.DriverManager;
    import java.sql.SQLException;
    import java.util.Properties;
    
    import org.junit.Test;
    
    public class ConnectionTest2 {
    	// 方式一:
    	@Test
    	public void testConnectionTest_1() throws SQLException {
    		// 获取Driver的实现类对象
    		Driver driver = new com.mysql.jdbc.Driver();
    
    		String url = "jdbc:mysql://127.0.0.1:3306/test?characterEncoding=UTF-8";
    		Properties info = new Properties();
    		info.setProperty("user", "root");
    		info.setProperty("password", "123456");
    
    		Connection conn = driver.connect(url, info);
    
    		System.out.println(conn);
    	}
    
    	// 方式二:对方式一的迭代,在如下程序中不出现第三方安装API,使程序具有更好的移植性
    	@Test
    	public void testConnectionTest_2() throws Exception {
    		// 通过 反射 获取Driver实现类对象
    		Class<?> clazz = Class.forName("com.mysql.jdbc.Driver");
    		Driver driver = (Driver) clazz.newInstance();
    
    		// 提供要连接的数据库
    		String url = "jdbc:mysql://127.0.0.1:3306/test?characterEncoding=UTF-8";
    
    		// 提供连接需要的用户名和密码
    		Properties info = new Properties();
    		info.setProperty("user", "root");
    		info.setProperty("password", "123456");
    
    		// 获取连接
    		Connection conn = driver.connect(url, info);
    		System.out.println(conn);
    	}
    
    	// 方式三:使用DriverManager替换Driver
    	@Test
    	public void testConnectionTest_3() throws Exception {
    		// 1.通过 反射 获取Driver实现类对象
    		Class<?> clazz = Class.forName("com.mysql.jdbc.Driver");
    		Driver driver = (Driver) clazz.newInstance();
    
    		// 2.提供另外三个连接的基本信息
    		String url = "jdbc:mysql://127.0.0.1:3306/test?characterEncoding=UTF-8";
    		String user = "root";
    		String password = "123456";
    
    		// 注册驱动
    		DriverManager.registerDriver(driver);
    		// 获取连接
    		Connection conn = DriverManager.getConnection(url, user, password);
    		System.out.println(conn);
    	}
    
    	// 方式四:
    	@Test
    	public void testConnectionTest_4() throws Exception {
    		// 1.提供另外三个连接的基本信息
    		String url = "jdbc:mysql://127.0.0.1:3306/test?characterEncoding=UTF-8";
    		String user = "root";
    		String password = "123456";
    
    		// 2.加载Driver
    		Class.forName("com.mysql.jdbc.Driver");
    
    		// 3.获取连接
    		Connection conn = DriverManager.getConnection(url, user, password);
    		System.out.println(conn);
    	}
    	
    	//方式五:通过读取配置文件的方式获取连接。部署服务器时,若要修改可避免程序重新打包。
    	@Test
    	public void testConnectionTest() throws Exception{
    		//1.读取配置文件中4个基本信息
    		InputStream is = ConnectionTest2.class.getClassLoader().getResourceAsStream("jdbc.properties");
    		Properties pros = new Properties();
    		pros.load(is);
    		
    		String url = pros.getProperty("url");
    		String user = pros.getProperty("user");
    		String password = pros.getProperty("password");
    		String driverClass = pros.getProperty("driverClass");
    		
    		//2.加载驱动
    		Class.forName(driverClass);
    		
    		//3.获取连接
    		Connection conn = DriverManager.getConnection(url, user, password);
    		System.out.println(conn);
    	}
    }
    

    三、使用PreparedStatement实现CRUD操作

    1.操作和访问数据库

    ●数据库连接被用于向数据库服务器发送命令和SQL语句,并接受数据库服务器返回的结果。其实一个数据库连接就是一个Socket连接。
    ●在java.sql包中有3个接口分别定义了对数据库的调用的不同方式:

    Statement:用于执行静态SQL语句并返回它所生成结果的对象。
    PreparedStatement:SQL语句被预编译并存储在此对象中,可以使用此对象多次高效地执行该语句。➢CallableStatement:用于执行SQL存储过程

    使用Statement操作数据表存在弊端:

    ➢问题一:存在拼串操作,繁琐
    ➢问题二:存在SQL注入问题
    SQL注入是利用某些系统没有对用户输入的数据进行充分的检查,而在用户输入数据中注入非法的SQL语句段或命令(如: SELECT user, password FROM user_table WHERE user='a' OR 1 = 'AND password= 'OR '1'='1') , 从而利用系统的SQL引擎完成恶意行为的做法。

    PreparedStatement的使用

    增删改

    package com.xudong.perparedstatement;
    
    import java.io.IOException;
    import java.io.InputStream;
    import java.sql.Connection;
    import java.sql.DriverManager;
    import java.sql.PreparedStatement;
    import java.sql.SQLException;
    import java.text.ParseException;
    import java.text.SimpleDateFormat;
    import java.util.Date;
    import java.util.Properties;
    
    import org.junit.Test;
    
    import com.xudong.connection.ConnectionTest2;
    
    public class PreparedStatementCRUDTest {
    	@Test
    	public void testInsert() {
    		// 3.获取连接
    		Connection conn = null;
    		PreparedStatement ps = null;
    		try {
    			// 1.读取配置文件中4个基本信息
    			InputStream is = ConnectionTest2.class.getClassLoader().getResourceAsStream("jdbc.properties");
    			Properties pros = new Properties();
    			pros.load(is);
    
    			String url = pros.getProperty("url");
    			String user = pros.getProperty("user");
    			String password = pros.getProperty("password");
    			String driverClass = pros.getProperty("driverClass");
    
    			// 2.加载驱动
    			Class.forName(driverClass);
    
    			conn = DriverManager.getConnection(url, user, password);
    
    			// 4.预编译SQL语句,返回prepareStatement实例
    			String sql = "INSERT INTO customers(id,nam,email,birth) VALUES(?,?,?,?)";// 占位符
    			ps = conn.prepareStatement(sql);
    
    			// 5.填充占位符
    			ps.setString(1, "11");
    			ps.setString(2, "曹洪");
    			ps.setString(3, "caohong@qq.com");
    			SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
    			java.util.Date date = sdf.parse("2000-01-11");
    			ps.setDate(4, new java.sql.Date(date.getTime()));
    
    			// 6.执行操作
    			ps.execute();
    		} catch (Exception e) {
    			e.printStackTrace();
    		} finally {
    			// 7.资源关闭
    			try {
    				if(ps != null)
    					ps.close();
    			} catch (SQLException e) {
    				e.printStackTrace();
    			}
    			try {
    				if(conn != null)
    					conn.close();
    			} catch (SQLException e) {
    				e.printStackTrace();
    			}
    		}
    	}
    
    }
    


    查询

    package com.xudong.perparedstatement;
    
    import java.lang.reflect.Field;
    import java.sql.Connection;
    import java.sql.Date;
    import java.sql.PreparedStatement;
    import java.sql.ResultSet;
    import java.sql.ResultSetMetaData;
    import java.sql.SQLException;
    import java.util.ArrayList;
    import java.util.List;
    
    import org.junit.Test;
    
    import com.xudong.bean.Customer;
    import com.xudong.util.JDBCUtils;
    
    public class CustomerForQuery {
    	/*@Test
    	public void testQuery(){
    		Connection conn = null;
    		PreparedStatement ps = null;
    		ResultSet resultSet = null;
    		try {
    			conn = JDBCUtils.getConnection();
    			String sql = "select nam,email,birth from customers where id = ?";
    			ps = conn.prepareStatement(sql);
    			ps.setObject(1, 5);
    			
    			//执行并返回结果集
    			resultSet = ps.executeQuery();
    			//处理结果集
    			if(resultSet.next()){
    				
    				String name = resultSet.getString(1);
    				String email = resultSet.getString(2);
    				Date birth = resultSet.getDate(3);
    				
    				Customer customer = new Customer(name, email, birth);
    				System.out.println(customer);
    			}
    		} catch (Exception e) {
    			e.printStackTrace();
    		} finally{
    			//关闭资源
    			JDBCUtils.closeResource(conn, ps, resultSet);
    		}
    		
    	}
    	*/
    	public <T> List<T> queryForCustomers(Class<T> clazz,String sql,Object ...args){
    		Connection conn = null;
    		PreparedStatement ps = null;
    		ResultSet rs = null;
    		try {
    			conn = JDBCUtils.getConnection();
    			ps = conn.prepareStatement(sql);
    			
    			for(int i = 0;i < args.length; i++){
    				ps.setObject(i + 1, args[i]);
    			}
    			
    			rs = ps.executeQuery();
    			//获取结果集的原数据
    			ResultSetMetaData rsmd = rs.getMetaData();
    			//获取结果集列数
    			int columnCount = rsmd.getColumnCount();
    			//创建集合对象
    			ArrayList<T> list = new ArrayList<>();
    			while(rs.next()){
    				T t = clazz.newInstance();
    				for(int i = 0;i < columnCount;i++){
    					Object columvalue = rs.getObject(i + 1);
    					//获取每个列的列名
    					//String columnName = rsmd.getColumnName(i + 1);
    					//获取每个列的别名
    					String columnLabel = rsmd.getColumnLabel(i + 1);
    					//给cust对象指定columnName属性,赋值columnLabel
    					Field field = clazz.getDeclaredField(columnLabel);
    					field.setAccessible(true);
    					field.set(t, columvalue);
    				}
    				list.add(t);
    			}
    			return list;
    		} catch (Exception e) {
    			e.printStackTrace();
    		} finally{
    			JDBCUtils.closeResource(conn, ps, rs);
    		}
    		
    		return null;
    	}
    	
    	@Test
    	public void testQueryForCustomers(){
    		String sql = "select name,email,birth from customers where id > ?";
    		List<Customer> list = queryForCustomers(Customer.class,sql, 6);
    		list.forEach(System.out::println);
    	}
    }
    

    javabean

    package com.xudong.bean;
    
    import java.sql.Date;
    
    /**
     * ORM编程思想(object relational mapping) 一个数据表对应一个java类 表中的一条记录对应java类的一个对象
     * 表中的一个字段对应java类的一个属性
     */
    public class Customer {
    
    	private String name;
    	private String email;
    	private Date birth;
    
    	public Customer() {
    		super();
    	}
    
    	public Customer( String name, String email, Date birth) {
    		super();
    
    		this.name = name;
    		this.email = email;
    		this.birth = birth;
    	}
    
    
    	public String getName() {
    		return name;
    	}
    
    	public void setName(String name) {
    		this.name = name;
    	}
    
    	public String getEmail() {
    		return email;
    	}
    
    	public void setEmail(String email) {
    		this.email = email;
    	}
    
    	public Date getBirth() {
    		return birth;
    	}
    
    	public void setBirth(Date birth) {
    		this.birth = birth;
    	}
    
    	@Override
    	public String toString() {
    		return "Customer [ name=" + name + ", email=" + email + ", birth=" + birth + "]";
    	}
    
    }
    

    工具

    package com.xudong.util;
    
    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;
    
    //操作数据库的工具类
    public class JDBCUtils {
    	// 获取数据库的连接
    	public static Connection getConnection() throws Exception {
    		// 1.读取配置文件中4个基本信息
    		InputStream is = ClassLoader.getSystemClassLoader().getResourceAsStream("jdbc.properties");
    		Properties pros = new Properties();
    		pros.load(is);
    
    		String url = pros.getProperty("url");
    		String user = pros.getProperty("user");
    		String password = pros.getProperty("password");
    		String driverClass = pros.getProperty("driverClass");
    
    		// 2.加载驱动
    		Class.forName(driverClass);
    
    		Connection conn = DriverManager.getConnection(url, user, password);
    
    		return conn;
    	}
    
    	// 关闭数据库连接
    	public static void closeResource(Connection conn, Statement ps) {
    		// 资源关闭
    		try {
    			if (ps != null)
    				ps.close();
    		} catch (SQLException e) {
    			e.printStackTrace();
    		}
    		try {
    			if (conn != null)
    				conn.close();
    		} catch (SQLException e) {
    			e.printStackTrace();
    		}
    	}
    
    	public static void closeResource(Connection conn, Statement ps, ResultSet rs) {
    		// 资源关闭
    		try {
    			if (ps != null)
    				ps.close();
    		} catch (SQLException e) {
    			e.printStackTrace();
    		}
    		try {
    			if (conn != null)
    				conn.close();
    		} catch (SQLException e) {
    			e.printStackTrace();
    		}
    		try {
    			if (rs != null)
    				rs.close();
    		} catch (SQLException e) {
    			e.printStackTrace();
    		}
    	}
    }
    

    PreparedStatement的好处:

    书写sql更方便、解决了sql注入问题、可以操作Blob数据,可实现更高效的批量操作

    四、操作BLOB类型字段

    1.MySQL BLOB类型

    ●MySQL中,BLOB是一个二进制大型对象,是一个可以存储大量数据的容器,它能容纳不同大小的数据。
    ●插入BLOB类型的数据必须使用PreparedStatement ,因为BLOB类型的数据无法使用字符串拼接写的。
    ●MySQL的四种BLOB类型(除了在存储的最大信息量上不同外,他们是等同的)

    ●实际使用中根据需要存入的数据大小定义不同的BLOB类型。
    ●需要注意的是:如果存储的文件过大,数据库的性能会下降。
    ●如果在指定了相关的Blob类型以后,还报错: xxx too large ,那么在mysq|的安装目录下,找my.ini文件加上如下的配置参数: max_allowed_packet=16M。同时注意:修改了my.ini文件之后,需要重新启动mysql服务

    批量插入

    修改url:
    url=jdbc:mysql://127.0.0.1:3306/test?characterEncoding=UTF-8&rewriteBatchedStatements=true

    package com.xudong.perparedstatement;
    
    import java.sql.Connection;
    import java.sql.PreparedStatement;
    
    import org.junit.Test;
    
    import com.xudong.util.JDBCUtils;
    
    public class InsertTest {
    	@Test
    	public void testInsert(){
    		Connection conn = null;
    		PreparedStatement ps = null;
    		try {
    			
    			long start = System.currentTimeMillis();
    			
    			conn = JDBCUtils.getConnection();
    			
    			conn.setAutoCommit(false);
    			
    			String sql = "insert into goods(name) values(?)";
    			ps = conn.prepareStatement(sql);
    		
    			for(int i = 1;i < 1000000;i++){
    				ps.setObject(1, "name_" + i);
    				ps.addBatch();//攒sql
    				if(i % 500 == 0){
    					ps.executeBatch();//执行
    					ps.clearBatch();//清空
    				}
    			}
    			conn.commit();
    			
    			long end = System.currentTimeMillis();
    			
    			System.out.println("花费时间:" + (end - start));
    			
    		} catch (Exception e) {
    			e.printStackTrace();
    		}finally{
    			JDBCUtils.closeResource(conn, ps);
    		}
    	
    	}
    }
    
  • 相关阅读:
    基于事件的异步编程
    基于任务的异步编程
    C#异步编程
    C#2.0
    Mac上安装Brew
    PHP中三维数组转二位数组,并且根据某个字段去重
    LNMP环境安装Laravel之后, 除了根目录下可以访问, 其他都是404页面
    LNMP一键安装包安装的mysql远程连接不上的问题
    CentOS7 安装Redis4.0
    CentOS 7 源码包安装SVN及使用
  • 原文地址:https://www.cnblogs.com/nnadd/p/13410786.html
Copyright © 2011-2022 走看看