Apache-DButils以及Druid(德鲁伊) 多表连接查询的解决方案:两种

导读:本篇文章讲解 Apache-DButils以及Druid(德鲁伊) 多表连接查询的解决方案:两种,希望对大家有帮助,欢迎收藏,转发!站点地址:www.bmabk.com

Apache-DButils以及Druid(德鲁伊) 多表连接查询的问题

在这里插入图片描述


每博一文案

张爱玲说,于千万人之中,遇到你所要遇到的人,于千万年之中,时间的无涯的荒野里,没有
早一步,也没有晚一步,刚巧赶上了。
人生海海,相遇别离自有时,自然会有人陪你走到最后,但更多的只能陪你走一段路罢了。
你的一生,我只接一程,再多一分也不能了。王家卫曾说:爱情这东西,时间很关键,认识的太早,或者太晚
都不行,缘分是很奇妙的东西,有的人明明遇见得很早,却不能一起走到最后。有的人出现时,
斜风带雨,乱了四季,却早就不是适合相遇的季节了,只能眼睁睁的错过,他早一步春芽不发。
晚一步错过,正如恰逢其时,这个词,初看温柔又浪漫,再细看还有寻觅和牡丹,要经历
过多少次的生不逢时,才能换来。如今一生恰逢其时的感慨,每一次的遇见,都是来自上苍的礼物。
每一份相遇相知,都是属于命运的馈赠,面对离开,只要不辜负相遇就可以了。
你陪我一程,我念你一生,不管结局如何,至少我们都是真心相待过,这份温度足慰藉余生。
                                       ——————   一禅心灵庙语


1. 问题描述

对于多表连接查询,存储多表连接查询的结果集,将 select 查询的结果集,存储到对应的JavaBean 中去的话是不行的 。因为你的查询是基于多张数据表得到的结果集,而对应 映射存储 到只有一张数据表的 一个 JavaBean 当中去,是不行的,该 JavaBean当中只有一张数据表的字段属性值,是无法将 select 基于多张数据表查询到的所有字段值内容,存储到的。

在这里插入图片描述

所以我们就可以使用如下两种方式,存储对于 select 多表查询的结果集。

  • 方式一:通过一个JavaBean中附加定义另外一个多表查询的表的 JavaBean 对象
  • 方式二:创建一个新的 JavaBean,该类包含 多表查询的所有字段的属性。

具体实现如下:解决方案。

2. 解决方案

用于方案的讲解,我们需要先创建如下两张数据表 department,employee。执行如下 SQL语句

CREATE TABLE department(
    dept_id INT PRIMARY KEY AUTO_INCREMENT,
    dept_name VARCHAR(30) NOT NULL DEFAULT '',
    emp_id INT NOT NULL
);

INSERT INTO department(dept_name,emp_id)
VALUES('财务部',1),('销售部',2),('研发部',3);

------------------------------------------

CREATE TABLE employee(
    emp_id INT PRIMARY KEY AUTO_INCREMENT,
    emp_name VARCHAR(30) NOT NULL DEFAULT '',
    email VARCHAR(50) NOT NULL DEFAULT '',
    gender VARCHAR(2) NOT NULL DEFAULT ''
)


INSERT INTO employee(emp_name,email,gender)
VALUES('张三','zhangsan@126.com','男'),
      ('李四','lisi@126.com','男'),
      ('王五','wangwu@126.com','男');

在这里插入图片描述

在这里插入图片描述

处理存储如下 SQL语句的 select 多表查询的结果集

SELECT dept_id AS deptId,dept_name AS deptName,employee.emp_id AS empId, 
                     emp_name AS empName,email,gender  
                     FROM department 
                     JOIN employee 
                     ON employee.emp_id = department.emp_id;

在这里插入图片描述


2.1 方案一

通过创建一个JavaBean 附加上另外一张数据表的 JavaBean 类作为 类属性存在如下:

在这里插入图片描述

对于多表连接查询,如果使用BeanListHandler,则会出现其中的一个JavaBean引用类型为 null (如果访问会出现 null引用异常)。也就是这里的 dept 引用类属性的值是 null
例如 DepartmentDeptAndEmp分类封装为 javabean。DeptAndEmp中声明一个Department的对象。如下图所示:

在这里插入图片描述

package Blogs.blogs6;

public class Department {
    private int deptId;
    private String deptName;
    private int empId;



    public Department() {
        // 无参构造器必须,创建用于 apache-dbutls 底层调用使用
    }



    // set/get必须创意用于 apache-dbutls底层反射赋值,取值
   public int getDeptId() {
        return deptId;
    }

    public void setDeptId(int deptId) {
        this.deptId = deptId;
    }

    public String getDeptName() {
        return deptName;
    }

    public void setDeptName(String deptName) {
        this.deptName = deptName;
    }

    public int getEmpId() {
        return empId;
    }

    public void setEmpId(int empId) {
        this.empId = empId;
    }


    @Override
    public String toString() {
        return "Department{" +
                "deptId=" + deptId +
                ", deptName='" + deptName + '\'' +
                ", empId=" + empId +
                '}';
    }
}

package Blogs.blogs6;

public class DeptAndEmp {
    private int empId;
    private String empName;
    private String email;
    private String gender;

    private Department dept;



    public DeptAndEmp() {
        // 无参构造器必须,创建用于 apache-dbutls 底层调用使用
    }


    // set/get必须创意用于 apache-dbutls底层反射赋值,取值
    public int getEmpId() {
        return empId;
    }

    public void setEmpId(int empId) {
        this.empId = empId;
    }

    public String getEmpName() {
        return empName;
    }

    public void setEmpName(String empName) {
        this.empName = empName;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public String getGender() {
        return gender;
    }

    public void setGender(String gender) {
        this.gender = gender;
    }

    public Department getDept() {
        return dept;
    }

    public void setDept(Department dept) {
        this.dept = dept;
    }

    @Override
    public String toString() {
        return "DeptAndEmp{" +
                "empId=" + empId +
                ", empName='" + empName + '\'' +
                ", email='" + email + '\'' +
                ", gender='" + gender + '\'' +
                ", dept=" + dept +
                '}';
    }
}

演示BeanListHandler 存储多表查询中出现的 null空指针

import com.alibaba.druid.pool.DruidDataSourceFactory;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.BeanListHandler;

import javax.sql.DataSource;
import java.io.File;
import java.io.FileInputStream;
import java.sql.Connection;
import java.util.List;
import java.util.Properties;

public class MultiListSelect {
    public static void main(String[] args) {
        try {
            FileInputStream is = new FileInputStream(new File("src/druid.properties"));
            Properties properties = new Properties();
            properties.load(is);

            // 创建 druid 数据库连接池
            DataSource dataSource = DruidDataSourceFactory.createDataSource(properties);

            // 获取到数据库当中的连接
            Connection connection = dataSource.getConnection();


            QueryRunner queryRunner = new QueryRunner();
            // 存储方式: BeanListHandler 将查询的结果集存储到javaBean当中,再将所有的javaBean对象存储到list链表当中
            BeanListHandler<DeptAndEmp> beanListHandler = new BeanListHandler<DeptAndEmp>(DeptAndEmp.class);

            // 多表连接查询SQL语句
        String sql = "select dept_id as deptId,dept_name as deptName,employee.emp_id as empId, " +
                     "emp_name as empName,email,gender  " +
                     "from department " +
                     "join employee " +
                     "on employee.emp_id = department.emp_id";

            List<DeptAndEmp> deptAndEmpList = queryRunner.query(connection, sql, beanListHandler);

            for(DeptAndEmp deptAndEmp : deptAndEmpList) {
                System.out.println(deptAndEmp);
            }


        } catch (Exception e) {
            throw new RuntimeException(e);  // 将编译异常转换为运行异常抛出
        }


    }

在这里插入图片描述

从运行结果上看,我们可以发现,其中 select 语句多表查询的结果集并没有赋值到 Department 类对象当中,其中的属性倒是赋值了。

我们可以使用 MapListHandle存储形式,解决这个使用BeanListHandler出现空指针异常的现象。

MapListHandler的使用(具体使用方式查看官方文档https://commons.apache.org/proper/commons-dbutils/apidocs/index.html
在这里插入图片描述

key——SQL语句查询的字段
value——数据库中查询得到的结果

使用 MapListHandle最终返回 List<map<String,Object>>,使用 迭代循环foreach 的方式通过查询字段(注意这里的查询字段指的是 数据表结构中的字段名,使用别名是无效的)取出 value,首先根据 Department 类中的 keymap 中取出对应的 value ,并将其封装为 Department 对象中。最后再封装 DeptAndEmp对象到链表当中,这样就解决了 使用 BeanListHandler出现空指针异常的现象。

具体代码实现如下:

package Blogs.blogs6;

import com.alibaba.druid.pool.DruidDataSourceFactory;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.MapListHandler;

import javax.sql.DataSource;
import java.io.File;
import java.io.FileInputStream;
import java.sql.Connection;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Properties;

public class MultiListSelect {
    public static void main(String[] args) {
        try {
            FileInputStream is = new FileInputStream(new File("src/druid.properties"));
            Properties properties = new Properties();
            properties.load(is);

            // 创建 druid 数据库连接池
            DataSource dataSource = DruidDataSourceFactory.createDataSource(properties);

            // 获取到数据库当中的连接
            Connection connection = dataSource.getConnection();


            QueryRunner queryRunner = new QueryRunner();
            // 存储方式: BeanListHandler 将查询的结果集存储到javaBean当中,再将所有的javaBean对象存储到list链表当中
            BeanListHandler<DeptAndEmp> beanListHandler = new BeanListHandler<DeptAndEmp>(DeptAndEmp.class);

            // 多表连接查询SQL语句
            String sql = "select dept_id as deptId,dept_name as deptName,employee.emp_id as empId, " +
                    "emp_name as empName,email,gender  " +  // 注意最后的空格,分隔
                    "from department " +
                    "join employee " +
                    "on employee.emp_id = department.emp_id";

            // 存储形式为 :  MapListHandler
            MapListHandler mapListHandler = new MapListHandler();
            List<Map<String, Object>> query = queryRunner.query(connection, sql, mapListHandler);  // 执行sql语句
            List<DeptAndEmp> list = new ArrayList<DeptAndEmp>();  // 定义集合链表存储 DeptAndEmp 多对象值

            for(Map<String,Object> map : query) {

                Department department = new Department();  // 定义存储对象
                DeptAndEmp deptAndEmp = new DeptAndEmp();

                // Department: 调用 set方法赋值
                department.setDeptId((int)map.get("dept_id"));
                department.setDeptName((String)map.get("dept_name"));

                // DeptAndEmp: 调用 set方法赋值
                deptAndEmp.setDept(department);
                deptAndEmp.setEmpId((int)map.get("emp_id"));   // 注意是查询中的字段名,使用别名没有用
                deptAndEmp.setEmail((String)map.get("email"));
                deptAndEmp.setEmpName((String) map.get("emp_name"));
                deptAndEmp.setGender((String) map.get("gender"));

                // 最后封装到链表当中
                list.add(deptAndEmp);
            }

            for(DeptAndEmp deptAndEmp : list) {
                System.out.println(deptAndEmp);

            }

        } catch (Exception e) {
            throw new RuntimeException(e);  // 将编译异常转换为运行异常抛出
        }


    }

}

在这里插入图片描述

在这里插入图片描述


2.2 方案二

创建一个新的 JavaBean,该类包含多表查询的所有字段的属性。 这种方式使用 BeanListHandler 存储形式。没有 null 空指针的存在。

如下创建的 JavaBean 包含 该SQL 多表查询的中所有的字段值,如下 EmpAndDept 类。

在这里插入图片描述

package Blogs.blogs6;

public class EmpAndDept {
    private int deptId;
    private String deptName;
    private int empId;
    private String empName;
    private String email;
    private String gender;

    public EmpAndDept() {
        // 无参构造器,必须定义,用于 apache-dbtlis底层的调用
    }

    // 同样set/get 也是必须定义的用于 apache-dbtils底层反射赋值,取值


    public int getDeptId() {
        return deptId;
    }

    public void setDeptId(int deptId) {
        this.deptId = deptId;
    }

    public String getDeptName() {
        return deptName;
    }

    public void setDeptName(String deptName) {
        this.deptName = deptName;
    }

    public int getEmpId() {
        return empId;
    }

    public void setEmpId(int empId) {
        this.empId = empId;
    }

    public String getEmpName() {
        return empName;
    }

    public void setEmpName(String empName) {
        this.empName = empName;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public String getGender() {
        return gender;
    }

    public void setGender(String gender) {
        this.gender = gender;
    }

    @Override
    public String toString() {
        return "EmpAndDept{" +
                "deptId=" + deptId +
                ", deptName='" + deptName + '\'' +
                ", empId=" + empId +
                ", empName='" + empName + '\'' +
                ", email='" + email + '\'' +
                ", gender='" + gender + '\'' +
                '}';
    }
}

具体代码如下:

import com.alibaba.druid.pool.DruidDataSourceFactory;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.BeanListHandler;
import org.apache.commons.dbutils.handlers.MapListHandler;

import javax.sql.DataSource;
import java.io.File;
import java.io.FileInputStream;
import java.sql.Connection;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Properties;

public class MultiListSelect {
    public static void main(String[] args) {
        try {
            FileInputStream is = new FileInputStream(new File("src/druid.properties"));
            Properties properties = new Properties();
            properties.load(is);

            // 创建 druid 数据库连接池
            DataSource dataSource = DruidDataSourceFactory.createDataSource(properties);

            // 获取到数据库当中的连接
            Connection connection = dataSource.getConnection();


            QueryRunner queryRunner = new QueryRunner();
            // 存储方式: BeanListHandler 将查询的结果集存储到javaBean当中,再将所有的javaBean对象存储到list链表当中
            BeanListHandler<EmpAndDept> beanListHandler = new BeanListHandler<>(EmpAndDept.class);

            // 多表连接查询SQL语句
            String sql = "select dept_id as deptId,dept_name as deptName,employee.emp_id as empId, " +
                    "emp_name as empName,email,gender  " +
                    "from department " +
                    "join employee " +
                    "on employee.emp_id = department.emp_id";

            List<EmpAndDept> query = queryRunner.query(connection, sql, beanListHandler);

            for(EmpAndDept empAndDept : query) {
                System.out.println(empAndDept);
            }

        } catch (Exception e) {
            throw new RuntimeException(e);  // 将编译异常转换为运行异常抛出
        }
        
    }
}

在这里插入图片描述

在这里插入图片描述


3. 总结

  1. select 多表查询存储其结果集的数据信息。两种方案:
    1. 第一种方案:创建一个JavaBean 附加上另外一张数据表的 JavaBean 类作为 类属性存在
    2. 该方案不可以使用 BeanListHandler 存储形式,存在 null 空指针异常的问题,而是替换使用 MapListHandle 的方式,通过 循环迭代foreach() 通过 key(注意是数据表结构的字段名,别名没有用),获取到对应的 value 值,再通过 set 方法赋值到对应的类属性中去。从而解决了 使用 BeanListHandler出现空指针异常的现象。
    3. 第二种方案:创建一个新的 JavaBean,该类包含多表查询的所有字段的属性。 这种方式使用 BeanListHandler 存储形式。没有 null 空指针的存在。
  2. 处理多表查询的结果集,这两种方案都可以,各有千秋。
    1. 第一种方案,创建的 JavaBean类少,但是实现起来比较复杂一点,
    2. 第二种方案,创建的 JavaBean 类多,定义的属性多,但是实现起来比较简单。
  3. 具体使用其中的哪一种方案处理都可以,大家可以根据需要自行选择。

4. 最后

限于自身水平,其中存在的错误,希望大家给予指教,韩信点兵——多多益善,谢谢大家,后会有期,江湖再见 !!!

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-U3j6sAVK-1669713513978)(E:\博客\JDBC博客库\image-20221129084353242.png)]

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之家整理,本文链接:https://www.bmabk.com/index.php/post/83004.html

(0)
小半的头像小半

相关推荐

极客之家——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!