JDBC:连接和对数据的 *** 作

JDBC:连接和对数据的 *** 作,第1张

JDBC:连接和对数据的 *** 作

文章目录
  • 一、JDBC概述
    • 1.软件架构
    • 2.数据的持久化
    • 3. Java中的数据存储技术
    • 4.JDBC介绍
    • 5. JDBC体系结构
  • 二、获取数据库连接
    • 1.连接的方式
    • 2.通用方式
    • 3.Statement *** 作数据表的弊端
  • 三、实现表数据的添加 *** 作
    • 1.Java与SQL对应数据类型转换表
    • 2.PreparedStatement的使用
      • (1)实现增、删、改 *** 作
      • (2)实现查询 *** 作
  • 总结


一、JDBC概述 1.软件架构
  • B/S:Browser Server(浏览器/服务器模式)
  • C/S:Client Server(服务器/客户机)
2.数据的持久化

把数据保存到可掉电式存储设备中以供之后使用

3. Java中的数据存储技术
  • 在Java中,数据库存取技术可分为如下几类:

    • JDBC直接访问数据库

    • JDO (Java Data Object )技术

    • 第三方O/R工具,如Hibernate, Mybatis 等

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

4.JDBC介绍
  • JDBC(Java Database Connectivity)是一个独立于特定数据库管理系统、通用的SQL数据库存取和 *** 作的公共接口

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

JDBC是sun公司提供一套用于数据库 *** 作的接口,java程序员只需要面向这套接口编程即可。

不同的数据库厂商,需要针对这套接口,提供不同实现。不同的实现的集合,即为不同数据库的驱动。 ————面向接口编程

二、获取数据库连接 1.连接的方式

代码如下(示例):

//方式一
@Test
    public void testConnection1() throws SQLException {
        Driver driver = new com.mysql.jdbc.Driver();
        // url:http://localhost:8080/gmall/keyboard.jpg
        // jdbc:mysql:协议
        // localhost:ip地址
        // 3306:默认mysql的端口号
        // test:test数据库
        String url="jdbc:mysql://localhost:3306/test";
        // 将用户名和密码封装在Properties中
        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 testConnection2() throws Exception {
        //获取Driver实现类的对象:使用反射
        Class clazz = Class.forName("com.mysql.jdbc.Driver");
        Driver driver = (Driver) clazz.newInstance();
        //提供要连接的数据库
        String url="jdbc:mysql://localhost:3306/test";
        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 testConnection3() throws Exception{
        //获取Driver实现类的对象:使用反射
        Class clazz = Class.forName("com.mysql.jdbc.Driver");
        Driver driver = (Driver) clazz.newInstance();
        //注册驱动
        DriverManager.registerDriver(driver);
        String url="jdbc:mysql://localhost:3306/test";
        String user="root";
        String password = "123456";
        Connection conn = DriverManager.getConnection(url,user,password);
        System.out.println(conn);
    }

//方式四
@Test
	public void testConnection4() throws Exception {
		// 1.提供三个连接的基本信息:
		String url = "jdbc:mysql://localhost:3306/test";
		String user = "root";
		String password = "abc123";
		
		// 2.加载Driver
		Class.forName("com.mysql.jdbc.Driver");//这个也可以省略,但是最好不要省略,因为只有mysql好使,其他不行
		//相较于方式三,可以省略如下的 *** 作:
//		Driver driver = (Driver) clazz.newInstance();
//		// 注册驱动
//		DriverManager.registerDriver(driver);
		//为什么可以省略上述 *** 作呢?
		

		// 3.获取连接
		Connection conn = DriverManager.getConnection(url, user, password);
		System.out.println(conn);
	}
2.通用方式

代码如下(示例):

//方式五(final版):将数据库连接需要的4个基本信息声明在配置文件中,通过读取配置文件的方式,获取连接
	
	@Test
	public void getConnection5() throws Exception{
		//1.读取配置文件中的4个基本信息
		InputStream is = ConnectionTest.class.getClassLoader().getResourceAsStream("jdbc.properties");
		
		Properties pros = new Properties();
		pros.load(is);
		
		String user = pros.getProperty("user");
		String password = pros.getProperty("password");
		String url = pros.getProperty("url");
		String driverClass = pros.getProperty("driverClass");
		
		//2.加载驱动
		Class.forName(driverClass);
		
		//3.获取连接
		Connection conn = DriverManager.getConnection(url, user, password);
		System.out.println(conn);
	}
3.Statement *** 作数据表的弊端
  • 问题一:存在拼串 *** 作,繁琐
  • 问题二:存在SQL注入问题
  • SQL 注入是利用某些系统没有对用户输入的数据进行充分的检查,而在用户输入数据中注入非法的 SQL 语句段或命令:(如:SELECt user, password FROM user_table WHERe user=‘a’ OR 1 = ’ AND password = ’ OR ‘1’ = ‘1’) ,从而利用系统的 SQL 引擎完成恶意行为的做法。
三、实现表数据的添加 *** 作 1.Java与SQL对应数据类型转换表 Java类型SQL类型booleanBITbyteTINYINTshortSMALLINTintINTEGERlongBIGINTStringCHAR,VARCHAR,LONGVARCHARbyte arrayBINARY , VAR BINARYjava.sql.DateDATEjava.sql.TimeTIMEjava.sql.TimestampTIMESTAMP 2.PreparedStatement的使用 (1)实现增、删、改 *** 作

通用:

@Test
	public void testCommonUpdate(){
//		String sql = "delete from customers where id = ?";
//		update(sql,3);
		
		String sql = "update `order` set order_name = ? where order_id = ?";
		update(sql,"DD","2");
		
	}
	
	//通用的增删改 *** 作
	public void update(String sql,Object ...args){//sql中占位符的个数与可变形参的长度相同!
		Connection conn = null;
		PreparedStatement ps = null;
		try {
			//1.获取数据库的连接
			conn = JDBCUtils.getConnection();
			//2.预编译sql语句,返回PreparedStatement的实例
			ps = conn.prepareStatement(sql);
			//3.填充占位符
			for(int i = 0;i < args.length;i++){
				ps.setObject(i + 1, args[i]);//小心参数声明错误!!
			}
			//4.执行
			ps.execute();
		} catch (Exception e) {
			e.printStackTrace();
		}finally{
			//5.资源的关闭
			JDBCUtils.closeResource(conn, ps);	
		}
	}
(2)实现查询 *** 作

针对于表的字段名与类的属性名不相同的情况:

  • 必须声明sql时,使用类的属性名来命名字段的别名
  • 使用ResultSetmetaData时,需要使用getColumnLabel()来替换getColumnName(), 获取列的别名。

说明:如果sql中没有给字段其别名,getColumnLabel()获取的就是列名

工具类

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 user = pros.getProperty("user");
		String password = pros.getProperty("password");
		String url = pros.getProperty("url");
		String driverClass = pros.getProperty("driverClass");

		// 2.加载驱动
		Class.forName(driverClass);

		// 3.获取连接
		Connection conn = DriverManager.getConnection(url, user, password);
		return conn;
	}
	//关闭连接和Statement的 *** 作
	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();
		}
	}
}

通用(单行数据):

@Test
	public void testGetInstance(){
		String sql = "select id,name,email from customers where id = ?";
		Customer customer = getInstance(Customer.class,sql,12);
		System.out.println(customer);
		
		String sql1 = "select order_id orderId,order_name orderName from `order` where order_id = ?";
		Order order = getInstance(Order.class, sql1, 1);
		System.out.println(order);
	}
	//针对于不同的表的通用的查询 *** 作,返回表中的一条记录
	public  T getInstance(Class 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
			ResultSetmetaData rsmd = rs.getmetaData();
			// 通过ResultSetmetaData获取结果集中的列数
			int columnCount = rsmd.getColumnCount();

			if (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);

					// 给t对象指定的columnName属性,赋值为columValue:通过反射
					Field field = clazz.getDeclaredField(columnLabel);
					field.setAccessible(true);
					field.set(t, columValue);
				}
				return t;
			}
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			JDBCUtils.closeResource(conn, ps, rs);

		}

		return null;
	}

通用(多行数据):

@Test
	public void testGetForList(){
		
		String sql = "select id,name,email from customers where id < ?";
		List list = getForList(Customer.class,sql,12);
		list.forEach(System.out::println);
		
		String sql1 = "select order_id orderId,order_name orderName from `order`";
		List orderList = getForList(Order.class, sql1);
		orderList.forEach(System.out::println);
	}
	
	public  List getForList(Class 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
			ResultSetmetaData rsmd = rs.getmetaData();
			// 通过ResultSetmetaData获取结果集中的列数
			int columnCount = rsmd.getColumnCount();
			//创建集合对象
			ArrayList list = new ArrayList();
			while (rs.next()) {
				T t = clazz.newInstance();
				// 处理结果集一行数据中的每一个列:给t对象指定的属性赋值
				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);

					// 给t对象指定的columnName属性,赋值为columValue:通过反射
					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;
	}

总结

ORM编程思想:

  • 一个数据表对应一个java类
  • 表中的一条记录对应java类的一个对象
  • 表中的一个字段对应java类的一个属性

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/zaji/5685936.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-17
下一篇 2022-12-17

发表评论

登录后才能评论

评论列表(0条)

保存