java全栈数据库技术:4.数据库之jdbc下(代码片段)

newnm个对象 newnm个对象     2022-12-10     121

关键词:

第四章 封装Druid

1.封装Druid

配置文件:src/druid.properties

#key=value
driverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/test
username=root
password=123456
initialSize=5
maxActive=10
maxWait=1000

JDBCTools工具类:

package com.atguigu.util;

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

import javax.sql.DataSource;

import com.alibaba.druid.pool.DruidDataSourceFactory;

/*
 * 获取连接或释放连接的工具类
 */
public class JDBCTools 
	// 1、数据源,即连接池
	private static DataSource dataSource;
	
	// 2、ThreadLocal对象
	private static ThreadLocal<Connection> threadLocal = new ThreadLocal<>();

	static 
		try 
			//1、读取druip.properties文件
			Properties pro = new Properties();
			pro.load(JDBCTools2.class.getClassLoader().getResourceAsStream("druid.properties"));
			
			//2、创建数据连接池
            // DruidDataSourceFactory.createDataSource(Properties properties): 可以根据Properties对象来生成一个DataSource连接池对象
            // 注意:这时Properties对象中的key不能随意更改,也就要求druid.properties配置文件中的key不能随意更改
			dataSource = DruidDataSourceFactory.createDataSource(pro); 
		 catch (Exception e) 
			e.printStackTrace();
		
	

	/**
	 * 获取连接的方法
	 * 
	 * @return
	 * @throws SQLException
	 */
	public static Connection getConnection() 
		// 从当前线程中获取连接
		Connection connection = threadLocal.get();
		if (connection == null) 
			// 从连接池中获取一个连接
			try 
				connection = dataSource.getConnection();
				// 将连接与当前线程绑定
				// 执行完这行代码后,threadLocal.get()就会返回connection对象
				threadLocal.set(connection);
			 catch (SQLException e) 
				e.printStackTrace();
			
		
		return connection;
	

	/**
	 * 释放连接的方法
	 * 
	 * @param connection
	 */
	public static void releaseConnection() 
		// 获取当前线程中的连接
		Connection connection = threadLocal.get();
		if (connection != null) 
			try 
				connection.close();
			 catch (SQLException e) 
				e.printStackTrace();
			finally
				// 将已经关闭的连接从当前线程中移除
				// 执行完这行代码后threadLocal.get()就会返回null
				threadLocal.remove();
			
		
	

2.ThreadLocal:

JDK 1.2的版本中就提供java.lang.ThreadLocal,为解决多线程程序的并发问题提供了一种新的思路。使用这个工具类可以很简洁地编写出优美的多线程程序。通常用来在在多线程中管理共享数据库连接、Session等

ThreadLocal用于保存某个线程共享变量,原因是在Java中,每一个线程对象中都有一个ThreadLocalMap<ThreadLocal, Object>,其key就是一个ThreadLocal,而Object即为该线程的共享变量。而这个map是通过ThreadLocal的set和get方法操作的。对于同一个static ThreadLocal,不同线程只能从中get,set,remove自己的变量,而不会影响其他线程的变量。

1、ThreadLocal.get: 获取ThreadLocal中当前线程共享变量的值。

2、ThreadLocal.set: 设置ThreadLocal中当前线程共享变量的值。

3、ThreadLocal.remove: 移除ThreadLocal中当前线程共享变量的值。

3.测试一下

class Demo8 extends Thread
    public static void main(String[] args) throws SQLException 
        for (int i = 0; i < 20; i++) 
            new Demo8().start();
        
    

    @Override
    public void run() 
        try 
            System.out.println("线程+"+this.getName()+"开始连接数据库");
            // 获取连接
            Connection connection = DruidTools.getConnection();
            PreparedStatement preparedStatement = null;
            // 生成命令发射器
            preparedStatement = connection.prepareStatement("select * from employ3");
            // 执行sql
            ResultSet resultSet = preparedStatement.executeQuery();
            // 处理结果
            while (resultSet.next())
                String name = resultSet.getString("ename");
                String salary = resultSet.getString("salary");
                System.out.println("姓名:"+name+"\\t薪资:"+salary);
            
            // 释放连接
            DruidTools.releaseConnection();
            System.out.println("线程+"+this.getName()+"连接数据库结束");
         catch (SQLException e) 
            e.printStackTrace();
        

    

第五章 更深层次的封装增删改查

前面我们对数据库的连接,资源的关闭进行了封装。实际上我们还可以进行更深层次的封装。将数据的增删改查封装为更加通用简洁的方法。

1.封装通用的增删改方法

package com.oy.jdbctest.jdbcutils;


import java.lang.reflect.Field;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.util.ArrayList;



public class BasicDaoImpl 
    /*
     * 通用的增、删、改的方法
     */
    public int update(String sql,Object... args) throws SQLException
        //1、获取链接对象
        Connection conn = DruidTools.getConnection();

        //2、编写sql,用形参传入的方式代替

        //3、获取Statement或PreparedStatement对象
        PreparedStatement pst = conn.prepareStatement(sql);

        //设置?的值
        //因为不知道sql中是否有?,以及?设置为什么值,通过形参来传入
        //Object... args可变形参,可以传入0~n个值
        //如果没有传入,说明没有?需要设置
        //如果传入了n个值,那么说明sql中有n个?需要设置
        if(args!=null  && args.length>0)
            for (int i = 0; i < args.length; i++) 
                //数组的下标从0开始,pst的?的序号是从1开始,所以这里用i+1
                pst.setObject(i+1, args[i]);
            
        

        //4、执行sql
        int len = pst.executeUpdate();
        //5、关闭
        pst.close();
        //这里不关闭conn,因为它在同一个事务的其他地方还要使用
        return len;
    

    /*
     * 通用查询多个Javabean对象的方法
     */
    public <T>  ArrayList<T> getList(Class<T> clazz,String sql,Object... args) throws Exception
        //1、获取链接对象
        Connection conn = DruidTools.getConnection();
        //2、编写sql,由形参传入

        //3、获取PreparedStatement对象
        PreparedStatement pst = conn.prepareStatement(sql);

        //4、设置?,由形参传入
        if(args!=null  && args.length>0)
            for (int i = 0; i < args.length; i++) 
                //数组的下标从0开始,pst的?的序号是从1开始,所以这里用i+1
                pst.setObject(i+1, args[i]);
            
        

        //5、执行sql
        ResultSet rs = pst.executeQuery();
        /*
         * 如何把ResultSet结果集中的数据变成一个一个的Javabean对象,放到ArrayList对象,并且返回
         */
        ArrayList<T> list = new ArrayList<>();
        /*
         * 要从ResultSet结果集中获取一共有几行,决定要创建几个对象
         * 要从ResultSet结果集中获取一共有几列,决定要为几个属性赋值
         * ResultSet结果集对象中,有一个方法ResultSetMetaData getMetaData()获取结果集的元数据
         * 元数据就是描述结果集中的数据的数据,例如:列数,列名称等
         */
        ResultSetMetaData metaData = rs.getMetaData();
        int count = metaData.getColumnCount();//获取列数

        while(rs.next())//循环一次代表一行,就要创建一个Javabean对象
            //(1)创建一个Javabean对象
            T t  = clazz.newInstance();//这个方法有要求,要求Javabean这个类要有无参构造

            //(2)设置对象的属性值
            /*
             * 反射操作属性的步骤:
             * ①获取Class对象,现在有了
             * ②获取属性对象Field
             * 		Field f = clazz.getDeclaredField("属性名");
             * ③创建Javabean对象,已经创建
             * ④设置属性的可访问性  setAccessible(true)
             * ⑤设置属性的值
             */
            for (int i = 0; i < count; i++) //一共要为count个属性赋值
//				Field f = clazz.getDeclaredField("属性名");
                String fieldName = metaData.getColumnLabel(i+1);//获取第几列的字段名
                Field f = clazz.getDeclaredField(fieldName);

                f.setAccessible(true);

                f.set(t, rs.getObject(i+1));//rs.getObject(i+1)获取第几列的值
            

            //(3)把Javabean对象放到list中
            list.add(t);
        
        pst.close();
        rs.close();
        //这里不关闭conn,因为它在同一个事务的其他地方还要使用
        return list;
    

    protected <T> T getBean(Class<T> clazz,String sql,Object... args) throws Exception
        return getList(clazz,sql,args).get(0);
    


练习:使用使用通用的增删改查方法实现Employee的增删改查

示例代码:EmployeeDAO.java

public interface EmployeeDAO 
	void addEmployee(Employee emp);
	void updateEmployee(Employee emp);
	void deleteByEid(int eid);
	Employee getByEid(int eid);
	ArrayList<Employee> getAll();

示例代码:EmployeeDAOImpl.java

package com.atguigu.test08.dao;

import java.sql.SQLException;
import java.util.ArrayList;

import com.atguigu.bean.Employee;

public class EmployeeDAOImpl extends BasicDAOImpl implements EmployeeDAO 

	@Override
	public void addEmployee(Employee emp) 
		//`ename`,`tel`,`gender`,`salary`,`commission_pct`,`birthday`,
		//`hiredate`,`job_id`,`email`,`mid`,`address`,`native_place`,`did`
		String sql = "insert into t_employee values(null,?,?,?,?,?,?,?,?,?,?,?,?,?)";
		
		try 
			update(sql, emp.getEname(),emp.getTel(),emp.getGender(),emp.getSalary(),emp.getCommissionPct(),
					emp.getBirthday(),emp.getHiredate(),emp.getJobId(),emp.getEmail(),emp.getMid(),emp.getAddress(),
					emp.getNativePlace(),emp.getDid());
		 catch (SQLException e) 
			throw new RuntimeException(e);
		
	

	@Override
	public void updateEmployee(Employee emp) 
		String sql = "update t_employee set `ename`=?,`tel`=?,`gender`=?,`salary`=?,`commission_pct`=?,`birthday`=?,`hiredate`=?,`job_id`=?,`email`=?,`mid`=?,`address`=?,`native_place`=?,`did`=? where eid=?";
		try 
			update(sql, emp.getEname(),emp.getTel(),emp.getGender(),emp.getSalary(),emp.getCommissionPct(),
					emp.getBirthday(),emp.getHiredate(),emp.getJobId(),emp.getEmail(),emp.getMid(),emp.getAddress(),
					emp.getNativePlace(),emp.getDid(),emp.getEid());
		 catch (SQLException e) 
			throw new RuntimeException(e);
		
	

	@Override
	public void deleteByEid(int eid) 
		String sql = "delete from t_employee where eid=?";
		try 
			update(sql, eid);
		 catch (SQLException e) 
			throw new RuntimeException(e);
		
	

	@Override
	public Employee getByEid(int eid) 
		//这里sql中通过取别名的方式,来指定对应的Javabean的属性名
		String sql = "select `eid`,`ename`,`tel`,`gender`,`salary`,`commission_pct` commissionPct ,`birthday`,`hiredate`,`job_id` jobId,`email`,`mid`,`address`,`native_place` nativePlace,`did` from t_employee where eid=?";
		Employee emp = null;
		try 
			emp = getBean(Employee.class, sql, eid);
		 catch (Exception e) 
			throw new RuntimeException(e);
			
		return emp;
	

	@Override
	public ArrayList<Employee> getAll() 
		//这里sql中通过取别名的方式,来指定对应的Javabean的属性名
		String sql = "select `eid`,`ename`,`tel`,`gender`,`salary`,`commission_pct` commissionPct ,`birthday`,`hiredate`,`job_id` jobId,`email`,`mid`,`address`,`native_place` nativePlace,`did` from t_employee";
		ArrayList<Employee>  list = new ArrayList<Employee>();
		try 
			list = getList(Employee.class, sql);
		 catch (Exception e) 
			throw new RuntimeException(e);
		
		return list;
	

第六章 Apache的DBUtils

commons-dbutils 是 Apache 组织提供的一个开源 JDBC工具类库,它是对JDBC的简单封装,学习成本极低,并且使用dbutils能极大简化jdbc编码的工作量,同时也不会影响程序的性能。

其中QueryRunner类封装了SQL的执行,是线程安全的。

(1)可以实现增、删、改、查、批处理、

(2)考虑了事务处理需要共用Connection。

(3)该类最主要的就是简单化了SQL查询,它与ResultSetHandler组合在一起使用可以完成大部分的数据库操作,能够大大减少编码量。

(1)更新

public int update(Connection conn, String sql, Object… params) throws SQLException:用来执行一个更新(插入、更新或删除)操作。

(2)插入

public T insert(Connection conn,String sql,ResultSetHandler rsh, Object… params) throws SQLException:只支持INSERT语句,其中 rsh - The handler used to create the result object from the ResultSet of auto-generated keys. 返回值: An object generated by the handler.即自动生成的键值

(3)批处理

public int[] batch(Connection conn,String sql,Object[][] params)throws SQLException: INSERT, UPDATE, or DELETE语句

public T insertBatch(Connection conn,String sql,ResultSetHandler rsh,Object[][] params)throws SQLException:只支持INSERT语句

(4)使用QueryRunner类实现查询

public Object query(Connection conn, String sql, ResultSetHandler rsh,Object… params) throws SQLException:执行一个查询操作,在这个查询中,对象数组中的每个元素值被用来作为查询语句的置换参数。该方法会自行处理 PreparedStatement 和 ResultSet 的创建和关闭。

***ResultSetHandler***接口用于处理 java.sql.ResultSet,将数据按要求转换为另一种形式。ResultSetHandler 接口提供了一个单独的方法:Object handle (java.sql.ResultSet rs)该方法的返回值将作为QueryRunner类的query()方法的返回值。

该接口有如下实现类可以使用:

  • BeanHandler:将结果集中的第一行数据封装到一个对应的JavaBean实例中。
  • BeanListHandler:将结果集中的每一行数据都封装到一个对应的JavaBean实例中,存放到List里。
  • ScalarHandler:查询单个值对象
  • MapHandler:将结果集中的第一行数据封装到一个Map里,key是列名,value就是对应的值。
  • MapListHandler:将结果集中的每一行数据都封装到一个Map里,然后再存放到List
  • ColumnListHandler:将结果集中某一列的数据存放到List中。
  • KeyedHandler(name):将结果集中的每一行数据都封装到一个Map里,再把这些map再存到一个map里,其key为指定的key。
  • ArrayHandler:把结果集中的第一行数据转成对象数组。
  • ArrayListHandler:把结果集中的每一行数据都转成一个数组,再存放到List中。

示例代码:BasicDAOImpl.java

package com.atguigu.test09.dbutil;

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

import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.BeanHandler;
import org.apache.commons.dbutils.handlers.BeanListHandler;
import org.apache.commons.dbutils.handlers.MapListHandler;
import org.apache.commons.dbutils.handlers.ScalarHandler;

import com.atguigu.util.JDBCTools;

//在这里都不关闭连接,统一关闭,因为Connection对象需要共享使用
public class BasicDAOImpl4 
	private QueryRunner qr =

java全栈数据库技术:3.数据库之jdbc上(代码片段)

...方便管理数据以及维护数据的关系;后来我们学习了数据库管理软件MySQL,可以方便的管理数据。那么如何将它俩结合起来呢?即Java程序< 查看详情

java全栈数据库技术:2.数据库之mysql下(代码片段)

第七章关联查询(联合查询,多表联查)7.0笛卡尔积运算表和表之间是如何关联的?——》通过笛卡儿积运算(将两张表里任意两条记录组合在一起形成新的记录,最终生成一张大的表的过程)而mysql中的关... 查看详情

java全栈javase:3.数据库之jdbc上(代码片段)

...方便管理数据以及维护数据的关系;后来我们学习了数据库管理软件MySQL,可以方便的管理数据。那么如何将它俩结合起来呢?即Java程序<==>MySQL,实现数据的存储和处理。那么就可以使用JDBC技术。1.1JDBC... 查看详情

java全栈数据库技术:1.数据库之mysqll上(代码片段)

第一章数据库概述1.1数据库概述DBMS:数据库管理系统(DatabaseManagementSystem)是一种操纵和管理数据库的大型软件,例如建立、使用和维护数据库。DB:数据库(Database)SQL:结构化查询语言,... 查看详情

java全栈web网页技术:8.servlet(代码片段)

...rvlet?已注册为例,前端提交的数据不能直接传到数据库中,需要先传到Java中,然后再通过jdbc技术传入数据库中。而Java程序要获取前端的数据或者发送数据给前端页面可以使用servlet技术。servlet:可以理解为... 查看详情

java全栈javase:2.数据库之mysql下(代码片段)

第七章关联查询(联合查询,多表联查)7.1关联查询的七种结果(1)A∩B(2)A(3)A-A∩B(4)B(5)B-A∩B(6)A∪B(7)A∪B-A∩B或者(A-A∩B)∪(B-A∩B)7.2如何... 查看详情

mysql数据库jdbc编程之java连接mysql

文章目录1.数据库编程的基础条件2.Java的数据库编程:JDBC3.JDBC访问数据库的层次结构4.MySQL数据库操作介绍5.MySQL驱动包的下载及添加到项目6.JDBC使用步骤6.1创建数据库源,连接Connection6.2构造SQL语句,为执行的操作做准... 查看详情

javaee框架整合技术之spring03-springjdbctemplate模板技术和事务处理(代码片段)

...之前我们先来讨论一个问题,以下这是一段常见的往数据库写入数据的JDBC代 查看详情

javaweb需要会啥技术

...!1、Java是基础,学习Java基础知识和基本技能。2、MySQL:数据库概念、MySQL安装与使用、SQL基本概念与通用语法、数据库的CRUD操作、数据库表的CRUD操作等。3、JDBC:JDBC快速入门、JDBC各个类详解、JDBC之CRUD练习、ResultSet类详解、JD... 查看详情

java之jdbc

JDBC的全称为:JavaDataBaseConnectivity(Java数据库连接)。是一种执行SQL语句的JavaAPI,可以为多种关系型数据库提供统一的访问。 1.JDBC的API(1)JDBC入门packagecom.imooc.jdbc.demo1;importcom.mysql.cj.jdbc.Driver;importjava.sql.*;publicclassJDBCD 查看详情

jdbc基础&crud操作(代码片段)

...换表5、两种思想6、两种技术二、程序编写步骤三、获取数据库连接四、CRUD操作一、概述1、JDBC介绍        Java数据库连接,(JavaDatabaseConnectivity,简称JDBC)是Java语言中用来规范客户端程序如何来访问数据库... 查看详情

java之jdbc(代码片段)

一.JDBC基础1.1数据库驱动我们安装好数据库后,我们的应用程序是不能直接使用数据库的,需要通过相应的数据库驱动程序,然后通过驱动程序才可以和数据库沟通,即JAVA应用程序--ORACLE/MYSQL/SQLSERVER驱动--ORACLE/MYSQL/SQLSERVER数据库... 查看详情

java之jdbc连接mysql数据库

packagejdbc;importjava.io.InputStream;importjava.sql.Connection;importjava.sql.DriverManager;importjava.sql.SQLException;importjava.sql.Statement;importjava.util.Properties;publicclassJdbcUtils{privat 查看详情

java全栈web网页技术:8.servlet(代码片段)

...rvlet?已注册为例,前端提交的数据不能直接传到数据库中,需要先传到Java中,然后再通过jdbc技术传入数据库中。而Java程序要获取前端的数据或者发送数据给前端页面可以使用servlet技术。servlet:可以理解为... 查看详情

jdbc------之结果集元数据的操作02

当数据库中的列名和我们java类中的属性名不相同的时候怎么实现对象的自动封装呢?查看下面的代码:packagecom.itheima.hui;importcom.itheima.hui.beans.User;importcom.itheima.hui.utils.JDBCUtils;importjdk.internal.org.objectweb.asm.tree.FieldInsnNode;im 查看详情

张晨光-java零基础保姆式jdbc技术教程(代码片段)

JDBC文档JDBC概述JDBC概述JavaDataBaseConnectivityJava数据库连接技术JDBC的作用通过Java语言操作数据库,操作表中的数据SUN公司为**了简化、**统一对数据库的操作,定义了一套Java操作数据库的规范,称之为JDBCJDBC的本质是官... 查看详情

springboot实战之使用jdbc和spring访问数据库

...是h2databse示例,所以简单的介绍普及下h2database相关知识H2数据库是一个开源的关系型数据库。H2是一个嵌入式数据库引擎,采用java语言编写,不受平台的限制,同时H2提供了一个十分方便的web控制台用于操作和管理数据库内容。... 查看详情

springboot实战之使用jdbc和spring访问数据库

...是h2databse示例,所以简单的介绍普及下h2database相关知识H2数据库是一个开源的关系型数据库。H2是一个嵌入式数据库引擎,采用java语言编写,不受平台的限制,同时H2提供了一个十分方便的web控制台用于操作和管理数据库内容。... 查看详情