JDBC技术【分页查询、数据库连接池、应用程序分层、封装通用的BaseDao】(四)-全面详解(学习总结---从入门到深化)

本文涉及的产品
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS MySQL,高可用系列 2核4GB
简介: JDBC技术【分页查询、数据库连接池、应用程序分层、封装通用的BaseDao】(四)-全面详解(学习总结---从入门到深化)



分页查询

分页查询简介

当一个操作数据库进行查询的语句返回的结果集内容如果过多,那 么内存极有可能溢出,所以在查询中含有大数据的情况下分页是必 须的。

分页查询分类:

物理分页:

在数据库执行查询时(实现分页查询),查询需要的数据—依赖数据库的SQL语句

在SQL查询时,从数据库只检索分页需要的数据

通常不同的数据库有着不同的物理分页语句

MySql物理分页采用limit关键字

逻辑分页:

在sql查询时,先从数据库检索出所有数据的结果集,在程序内,通过逻辑语句获得分页需要的数 据

如何在MySql中实现物理分页查询

使用limit方式。

limit的使用

select * from tableName limit m,n

其中m与n为数字。n代表需要获取多少行的数据项,而m代表从哪 开始(以0为起始)。

例如我们想从users表中先获取前两条数据SQL为:

select * from users limit 0,2;

那么如果要继续看下两条的数据则为:

select * from users limit 2,2;

以此类推 分页公式:(当前页-1)*每页大小

创建Page模型

Page

/**
* 分页查询实体类
*/
public class Page<T> {
    //当前页
    private int currentPage;
    //每页显示的条数
    private int pageSize;
    //总条数
    private int totalCount;
    //总页数
    private int totalPage;
    //结果集
    private List<T> result;
    public int getCurrentPage() {
        return currentPage;
   }
   public void setCurrentPage(int currentPage) {
        this.currentPage = currentPage;
   }
   public int getPageSize() {
        return pageSize;
   }
   public void setPageSize(int pageSize) {
        this.pageSize = pageSize;
   }
   public int getTotalCount() {
        return totalCount;
   }
   public void setTotalCount(int totalCount) {
        this.totalCount = totalCount;
   }
   public int getTotalPage() {
        return totalPage;
   }
   public void setTotalPage(int totalPage){
        this.totalPage = totalPage;
   }
   public List<T> getResult() {
        return result;
   }
   public void setResult(List<T> result) {
        this.result = result;
   }
}

实现分页查询

分页实现

/**
* 分页查询测试类
*/
public class PageTest {
    /**
     * 分页查询Users
     */
    public Page<Users> selectPage(Page page)
     {
        Connection conn =null;
        PreparedStatement ps = null;
        ResultSet rs = null;
        List<Users> list = new ArrayList<>();
        try{
            //获取连接对象
            conn = JdbcUtils.getConnection();
            //创建PrepareStatement对象
            ps = conn.prepareStatement("select * from users limit ?,?");
            //绑定m参数 m的值 = (当前页-1)*每页显示的条数
            ps.setInt(1, (page.getCurrentPage()-1)*page.getPageSize());
            //绑定n参数 n的值为每页显示的条数
            ps.setInt(2,page.getPageSize());
            //执行查询
            rs = ps.executeQuery();
            //处理结果集
            while(rs.next()){
                //完成ORM映射
                Users  users = new Users();
              users.setUserid(rs.getInt("userid"));
              users.setUsername(rs.getString("username"));
              users.setUserage(rs.getInt("userage"));
                list.add(users);
           }
            //讲结果集存放到Page对象中。
            page.setResult(list);
            //查询总条数
            ps =conn.prepareStatement("select count(*) from users");
            //执行查询
            rs = ps.executeQuery();
            while(rs.next()){
                //总条数
              int count =  rs.getInt(1);
               //保存总条数
                page.setTotalCount(count);
                //换算总页数 = 总条数 / 每页显示的条数 向上取整
               int totalPage = (int)Math.ceil(1.0*count/page.getPageSize());
               //保存总页数
              page.setTotalPage(totalPage);
           }
       }catch(Exception e){
            e.printStackTrace();
       }finally{
          JdbcUtils.closeResource(rs,ps,conn);
       }
        return page;
   }
 public static void main(String[] args) {
        PageTest pt = new PageTest();
        Page page = new Page();
        page.setCurrentPage(2);
        page.setPageSize(2);
        Page page1 = pt.selectPage(page);
        System.out.println("总条数:"+page1.getTotalCount());
        System.out.println("总页数:"+page1.getTotalPage());
        System.out.println("当前页:"+page1.getCurrentPage());
        System.out.println("每页显示的条数:"+page1.getPageSize());
        List<Users> list =page1.getResult();
        for(Users user:list){
          System.out.println(user.getUserid()+ " "+user.getUsername()+" "+user.getUserage());
       }
   }
}

数据库连接池

数据库连接池简介

什么是数据库连接池

数据库连接池(Connection pooling)是程序启动时建立足够的数 据库连接,并将这些连接组成一个连接池,由程序动态地对池中的 连接进行申请,使用,释放。 它允许应用程序重复使用一个现有的数据库连接,而不是再重新建 立一个;释放空闲时间超过最大空闲时间的数据库连接来避免因为 没有释放数据库连接而引起的数据库连接遗漏。这项技术能明显提 高对数据库操作的性能。

不使用数据库连接池存在的问题

1、普通的JDBC数据库连接使用 DriverManager 来获取,每次向数 据库建立连接的时候都要将 Connection加载到内存中,再验证 用户名和密码,所以整个过程比较耗时。

2、需要数据库连接的时候,就向数据库要求一个,执行完成后再断 开连接。这样的方式将会消耗大量的资源和时间。数据库的连接 资源并没有得到很好的重复利用。若同时有几百人甚至几千人在 线,频繁的进行数据库连接操作将占用很多的系统资源,严重的甚至会造成服务器的崩溃。

3、对于每一次数据库连接,使用完后都得断开。否则,如果程序出 现异常而未能关闭,将会导致数据库系统中的内存泄漏,最终将 导致重启数据库。

JDBC数据库连接池的必要性

数据库连接池的基本思想:为数据库连接建立一个“缓冲池”。预先在缓冲池中放入一定数量的连 接,当需要建立数据库连接时,只需从“缓冲池”中取出一个,使用完毕之后再放回去。

数据库连接池负责分配、管理和释放数据库连接,它允许应用程序重复使用一个现有的数据库连 接,而不是重新建立一个。

数据库连接池在初始化时将创建一定数量的数据库连接放到连接池中,这些数据库连接的数量是由 最小数据库连接数来设定的。无论这些数据库连接是否被使用,连接池都将一直保证至少拥有这么 多的连接数量。连接池的最大数据库连接数量限定了这个连接池能占有的最大连接数,当应用程序 向连接池请求的连接数超过最大连接数量时,这些请求将被加入到等待队列中。

数据库连接池的优点

1、资源重用:由于数据库连接得以重用,避免了频繁创建,释放连接引起的大量性能开销。在减少系 统消耗的基础上,另一方面也增加了系统运行环境的平稳性。

2、更快的系统反应速度:数据库连接池在初始化过程中,往往已经创建了若干数据库连接置于连接池 中备用。此时连接的初始化工作均已完成。对于业务请求处理而言,直接利用现有可用连接避免了 数据库连接初始化和释放过程的时间开销,从而减少了系统的响应时间。

3、新的资源分配手段:对于多应用共享同一数据库的系统而言,可在应用层通过数据库连接池的配置 实现某一应用最大可用数据库连接数的限制避免某一应用独占所有的数据库资源。

4、统一的连接管理:避免数据库连接泄露在较为完善的数据库连接池实现中,可根据预先的占用超时 设定,强制回收被占用连接,从而避免了常规数据库连接操作中可能出现的资源泄露。

常用的数据库连接池

c3p0:是一个开源组织提供的数据库连接池,速度相对较慢,稳定性还可以。

DBCP:是Apache提供的数据库连接池。速度相对c3p0较快,但自身存在bug。

Druid:是阿里提供的数据库连接池,据说是集DBCP、c3p0优点于一身的数据库连接池,目前经 常使用。

Druid连接池

Druid简介

Druid是阿里提供的数据库连接池,它结合了C3P0、DBCP等DB池 的优点,同时加入了日志监控,可以很好的监控DB池连接和SQL的 执行情况。

Druid使用步骤

1 导入druid-1.2.8.jar包到lib目录下,并引入到项目中

2 在src下创建一个druid.properties类型的文件,并写入

3 加载配置文件

4 获取连接池对象

5 通过连接池对象获取连接

url=jdbc:mysql://localhost:3306/itbz
driverClassName=com.mysql.jdbc.Driver
username=root
password=。。。。
initialSize=10
maxActive=20

druid配置信息:

通过数据库连接池获取连接

/**
* Druid连接池测试类
*/
public class DruidTest {
    public static void main(String[] args) throws Exception {
        //获取读取druid配置的字节输入流
        InputStream is = DruidTest.class.getClassLoader().getResourceAsStream("druid.properties");
        //创建Properties对象
        Properties pos = new Properties();
        //加载配置文件
        pos.load(is);
        //获取连接池对象
        DataSource ds = DruidDataSourceFactory.createDataSource(pos);
        //获取连接
        Connection connection = ds.getConnection();
        System.out.println(connection);
   }
}

封装工具类

/**
* 基于Druid连接池获取数据库连接工具类
*/
public class JdbcDruidUtil {
     //数据库连接池对象
     private static DataSource dataSource;
     static{
         try {
             //获取读取配置文件的字节输入流对象
             InputStream is = JdbcDruidUtil.class.getClassLoader().getResourceAsStream("druid.properties");
             //创建Properties对象
             Properties pop = new Properties();
             //加载配置文件
             pop.load(is);
             //创建连接池对象
             dataSource = DruidDataSourceFactory.createDataSource(pop);
         }catch(Exception e){
             e.printStackTrace();
         }
     }
    //获取数据库连接对象
    public static Connection getConnection()
     {
        Connection connection = null;
        try {
            connection = dataSource.getConnection();
       } catch (SQLException throwables) {
            throwables.printStackTrace();
       }
        return connection;
   }
    //关闭连接对象
    public static void closeConnection(Connection connection){
        try {
              connection.close();
       } catch (SQLException throwables) {
            throwables.printStackTrace();
       }
   }
    //提交事务
    public static void commit(Connection connection){
        try {
            connection.commit();
       } catch (SQLException throwables) {
            throwables.printStackTrace();
       }
   }
    //事务回滚
    public static void rollback(Connection connection){
        try {
            connection.rollback();
       } catch (SQLException throwables) {
            throwables.printStackTrace();
       }
   }
    //关闭Statement对象
    public static void closeStatement(Statement statement){
        try {
            statement.close();
       } catch (SQLException throwables) {
            throwables.printStackTrace();
       }
   }
 //关闭ResultSet
    public static void closeResultSet(ResultSet resultSet) {
        try {
            resultSet.close();
       } catch (SQLException throwables) {
            throwables.printStackTrace();
       }
   }
    //DML操作时关闭资源
    public static void closeResource(Statement statement,Connection connection){
        //先关闭Statement对象
        closeStatement(statement);
        //在关闭Connection对象
        closeConnection(connection);
   }
    //查询时关闭资源
    public static void closeResource(ResultSet resultSet,Statement statement,Connection connection){
        //先关闭ResultSet
        closeResultSet(resultSet);
        //在闭Statement对象
        closeStatement(statement);
        //最后关闭Connection对象
        closeConnection(connection);
   }
}

通过druid重构JDBCUtils

1 创建JDBCUtilsDruid类

2 使用静态块初始化连接池

public class JDBCUtilsDruid {
    private static DataSource ds = null;
    static{
        try {
            InputStream is = JDBCUtilsDruid.class.getClassLoader().getResourceAsStream("druid.properties");
            Properties properties = new Properties();
            pros.load(is);
            ds = DruidDataSourceFactory.createDataSource(properties);
       } catch (Exception e) {
            e.printStackTrace();
       }
   }

3 获取数据库连接方法

public static Connection getConnection() throws Exception {
        Connection conn = null;
        conn = ds.getConnection();
        return conn;
}

4 释放数据库连接方法

public static void close(Connection conn,Statement statement) throws Exception
   {
      try {
           if (statement!=null) {
                 statement.close();
               }
           } catch (SQLException e) {
                e.printStackTrace();
           }finally {
            if (conn!=null) {
              try {
                  conn.close();
                  } catch (SQLException e) {
                     e.printStackTrace();
               }
           }
       }

应用程序分层

应用程序分层简介

应用程序分层是指通过创建不同的包来实现项目的分层,将项目中 的代码根据功能做具体划分,并存放在不同的包下。

三层结构

三层结构就是将整个业务应用划分为:表述层、业务逻辑层 、数据访问层。区分层次的目的即为了“高内 聚低耦合”的思想。在软件体 系架构设计中,分层式结构是最常见,也是最重要的一种结构。

分层优点

1 分层结构将应用系统划分为若干层,每一层只解决问题的一部 分,通过各层的协作提供整体解决方案。大的问题被分解为一系 列相对独立的子问题,局部化在每一层中,这样就有效的降低了 单个问题的规模和复杂度,实现了复杂系统的第一步也是最为关 键的一步分解。

2 分层结构具有良好的可扩展性,为应用系统的演化增长提供了一 个灵活的支持,具有良好的可扩展性。增加新的功能时,无须对 现有的代码做修改,业务逻辑可以得到最大限度的重用。

3 分层结构易于维护。在对系统进行分解后,不同的功能被封装在 不同的层中,层与层之间的耦合显著降低。因此在修改某个层的 代码时,只要不涉及层与层之间的接口,就不会对其他层造成严 重影响。

分层命名

表述层:web或controller

业务层:service

数据访问层:dao (Data Access Object)

应用程序分层实现

在分层项目中实现查询业务

UserDao接口

public interface UsersDao {
    /**
     * 根据用户ID查询用户
     *
     */
    Users selectUsersById(int userid);
}

UserDaoImpl接口实现类

public class UsersDaoImpl implements UsersDao {
    /**
     * 根据用户ID查询用户
     * @param userid
     * @return
     */
    @Override
    public Users selectUsersById(int userid)
      {
        Connection conn =null;
        PreparedStatement ps = null;
        ResultSet rs = null;
        Users users = null;
        try{
            conn = JdbcDruidUtil.getConnection();
            ps = conn.prepareStatement("select * from users where userid = ?");
            ps.setInt(1,userid); 
            rs = ps.executeQuery();
            while(rs.next()){
                //手动orm映射
                users = new Users();
              users.setUserid(rs.getInt("userid"));
              users.setUsername(rs.getString("username"));
              users.setUserage(rs.getInt("userage"));
           }
       }catch(Exception e){
            e.printStackTrace();
            //通过自定义异常解决异常耦合问题
            throw new ApplicationException(e.getMessage());
       }finally{
          JdbcDruidUtil.closeResource(rs,ps,conn);
       }
        return users;
   }
}

UserService接口

public interface UsersService {
    Users findUsersById(int userid);
}

UserServiceImpl接口实现类

public class UsersServiceImpl implements UsersService {
    /**
     * 根据用户ID查询用户业务
     * @param userid
     * @return
     */
    @Override
    public Users findUsersById(int userid) {
        UsersDao ud = new UsersDaoImpl();
        return ud.selectUsersById(userid);
   }
}

web

public class Test {
    public static void main(String[] args) {
        UsersService us = new UsersServiceImpl();
        Users u = us.findUsersById(1);
        System.out.println(u);
   }
}

封装通用的BaseDao

封装通用的DML操作

BaseDao接口

/**
* 通用接口
*/
public interface BaseDao {
    /**
     * 通用的DML操作方法
     */
    int executeUpdate(String sql,Object[] param);
}

BaseDaoImpl接口实现类

/**
* 通用接口实现类
*/
public class BaseDaoImpl implements BaseDao
{
    /**
     * 通用的DML操作方法
     */
    @Override
    public int executeUpdate(String sql, Object[] param) {
        Connection conn = null;
        PreparedStatement ps = null;
        int row;
        try{
            conn = JdbcDruidUtil.getConnection();
            ps = conn.prepareStatement(sql);
            //得到参数的个数
            ParameterMetaData pd = ps.getParameterMetaData();
            for(int i =0;i<pd.getParameterCount();i++){
                ps.setObject(i+1,param[i]);
           }
            row = ps.executeUpdate();
       }catch (Exception e){
            e.printStackTrace();
            //通过自定义异常解决异常耦合问题
            throw new ApplicationException(e.getMessage());
       }finally{
          JdbcDruidUtil.closeResource(ps,conn);
       }
        return row;
   }
}

UsersDao接口

public interface UsersDao extends BaseDao {
    /**
     * 根据用户ID查询用户
     *
     */
    Users selectUsersById(int userid);
    /**
     * 修改用户信息
     */
    int updateUsersById(Users users);
}

UsersDaoImpl接口实现类

public class UsersDaoImpl extends BaseDaoImpl implements UsersDao {
    /**
     * 根据用户ID查询用户
     * @param userid
     * @return
     */
    @Override
    public Users selectUsersById(int userid)
     {
        Connection conn =null;
        PreparedStatement ps = null;
        ResultSet rs = null;
        Users users = null;
        try{
         conn = JdbcDruidUtil.getConnection();
            ps = conn.prepareStatement("select * from users where userid = ?");
            ps.setInt(1,userid);
            rs = ps.executeQuery();
            while(rs.next()){
                //手动orm映射
                users = new Users();
              users.setUserid(rs.getInt("userid"));
              users.setUsername(rs.getString("username"));
              users.setUserage(rs.getInt("userage"));
           }
       }catch(Exception e){
            e.printStackTrace();
            //通过自定义异常解决异常耦合问题
            throw new ApplicationException(e.getMessage());
       }finally{
          JdbcDruidUtil.closeResource(rs,ps,conn);
       }
        return users;
   }
    /**
     * 修改用户信息
     */
 @Override
    public int updateUsersById(Users users)
     {
        String sql = "update users set userage = ? where userid = ? ";
        Object[] param = new Object[] {users.getUserage(),users.getUserid()};
        return this.executeUpdate(sql,param);
   }
}

封装通用的查询操作

BaseDao接口

/**
* 通用接口
*/
public interface BaseDao {
    /**
     * 通用的DML操作方法
     */
    int executeUpdate(String sql,Object[] param);
    /**
     * 通用查询方法
     * 要求:实体类的属性名必须要与表的列名相同。
     */
    <T> List<T> select(String sql,Object[] param,Class<T> clazz);
}

BaseDaoImpl接口实现类

/**
* 通用接口实现类
*/
public class BaseDaoImpl implements BaseDao
{
    /**
     * 通用的DML操作方法
     */
    @Override
    public int executeUpdate(String sql, Object[] param) {
        Connection conn = null;
        PreparedStatement ps = null;
        int row;
        try{
            conn = JdbcDruidUtil.getConnection();
            ps = conn.prepareStatement(sql);
            //得到参数的个数
            ParameterMetaData pd = ps.getParameterMetaData();
            for(int i =0;i<pd.getParameterCount();i++){
                ps.setObject(i+1,param[i]);
           }
               row = ps.executeUpdate();
       }catch (Exception e){
            e.printStackTrace();
            //通过自定义异常解决异常耦合问题
            throw new ApplicationException(e.getMessage());
       }finally{
          JdbcDruidUtil.closeResource(ps,conn);
       }
        return row;
   }
    /**
     * 通用查询方法
     */
    @Override
    public <T> List<T> select(String sql, Object[] param, Class<T> clazz) {
        Connection conn = null;
        PreparedStatement ps = null;
        ResultSet rs = null;
        List<T> list = new ArrayList<>();
        try{
            conn = JdbcDruidUtil.getConnection();
            ps = conn.prepareStatement(sql);
            //得到参数的个数
            ParameterMetaData pd = ps.getParameterMetaData();
            for(int i =0;i<pd.getParameterCount();i++){
                 ps.setObject(i+1,param[i]);
           }
            rs = ps.executeQuery();
            //获取结果集信息
            ResultSetMetaData rm = rs.getMetaData();
            while(rs.next()){
                //OMR映射
                //通过反射实例化实体类对象
              T bean = clazz.newInstance();
              //实体类的属性名必须要和表的列名相同。
                for(int i=0;i<rm.getColumnCount();i++){
                    //得到列名
                    String columnName = rm.getColumnName(i+1);
                    //获取列的值
                    Object value = rs.getObject(columnName);
                    //通过BeanUtil工具类讲值映射到对象中
                  BeanUtils.setProperty(bean,columnName,value);
               }
                list.add(bean);
           }
       }catch (Exception e){
            e.printStackTrace();
            //通过自定义异常解决异常耦合问题 
            throw new ApplicationException(e.getMessage());
       }finally{
          JdbcDruidUtil.closeResource(rs,ps,conn);
       }
        return list;
   }
}

UsersDao接口

public interface UsersDao extends BaseDao {
    /**
     * 根据用户ID查询用户
     *
     */
    Users selectUsersById(int userid);
    /**
     * 修改用户信息
     */
    int updateUsersById(Users users);
    /**
     * 根据用户姓名模糊查询
     */
    List<Users> selectUsersByLikeName(String username);
}

UsersDaoImpl接口实现类

public class UsersDaoImpl extends
BaseDaoImpl implements UsersDao {
    /**
     * 根据用户ID查询用户
     * @param userid
     * @return
     */
    @Override
    public Users selectUsersById(int userid){
        Connection conn =null;
        PreparedStatement ps = null;
        ResultSet rs = null;
        Users users = null;
        try{
            conn = JdbcDruidUtil.getConnection();
            ps = conn.prepareStatement("select * from users where userid = ?");
            ps.setInt(1,userid);
            rs = ps.executeQuery();
            while(rs.next()){
                //手动orm映射
                users = new Users();
              users.setUserid(rs.getInt("userid"));
              users.setUsername(rs.getString("username"));
              users.setUserage(rs.getInt("userage"));
           }
       }catch(Exception e){
            e.printStackTrace();
            //通过自定义异常解决异常耦合问题
            throw new ApplicationException(e.getMessage());
       }finally{
          JdbcDruidUtil.closeResource(rs,ps,conn);
       }
        return users;
   }
    /**
     * 修改用户信息
     */
    @Override
    public int updateUsersById(Users users){
        String sql = "update users set userage = ? where userid = ? ";
        Object[] param = new Object[] {users.getUserage(),users.getUserid()};
        return this.executeUpdate(sql,param);
   }
    @Override
    public List<Users> selectUsersByLikeName(String username) {
        String sql = "select * from users where username like ?";
        Object[] param = new Object[] {"%"+username+"%"};
        return this.select(sql,param,Users.class);
   }
}

对象的关联关系

关联关系简介

关联关系(Association),是一种拥有的关系,它使一个对象知道另 一个对象的属性和方法。关联可以是双向的,也可以是单向的。在 Java语言中,关联关系一般使用成员变量来实现。

对象的关联关系解决了什么问题

在多表查询时,使用对象关联关系能够更合理的存放查询到的结果集数据。

关联关系的方向性

单向 只在一侧关联了对方。

双向 两侧相互关联了对方。

创建对象的关联关系

创建表

orders表

CREATE TABLE `orders` (
  `orderid` int(11) NOT NULL AUTO_INCREMENT,
  `orderprice` float(11,2) DEFAULT NULL,
  `user_id` int(11) DEFAULT NULL,
  PRIMARY KEY (`orderid`),
  KEY `orders_fk` (`user_id`),
  CONSTRAINT `orders_fk` FOREIGN KEY
(`user_id`) REFERENCES `users` (`userid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

items表

CREATE TABLE `items` (
  `itemid` int(11) NOT NULL,
  `itemname` varchar(30) DEFAULT NULL,
  `itemprice` float(11,2) DEFAULT NULL,
  `itemnum` int(11) DEFAULT NULL,
  PRIMARY KEY (`itemid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

orders_itmes表

CREATE TABLE `orders_items` (
  `order_id` int(11) NOT NULL,
  `item_id` int(11) NOT NULL,
  PRIMARY KEY (`order_id`,`item_id`),
  KEY `orders_items_fk2` (`item_id`),
  CONSTRAINT `orders_items_fk` FOREIGN KEY
(`order_id`) REFERENCES `orders` (`orderid`),
  CONSTRAINT `orders_items_fk2` FOREIGN KEY
(`item_id`) REFERENCES `items` (`itemid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

对象的关联关系

Users对象

public class Users {
    private int userid;
    private String username;
    private int userage;
    //创建与Orders的关联关系
    private List<Orders> orders = new ArrayList<>();
    public List<Orders> getOrders() {
        return orders;
   }
    public void setOrders(List<Orders> orders) {
        this.orders = orders;
   }
  @Override
    public String toString() {
        return "Users{" +
                "userid=" + userid +
                ", username='" + username +'\'' +
                ", userage=" + userage +
                '}';
   }
    public int getUserid() {
        return userid;
   }
    public void setUserid(int userid) {
        this.userid = userid;
   }
    public String getUsername() {
        return username;
   }
    public void setUsername(String username)
   {
        this.username = username;
   }
    public int getUserage() {
        return userage;
   }
   public void setUserage(int userage) {
        this.userage = userage;
   }
}

Orders对象

public class Orders {
    private int orderid;
    private double orderprice;
    //关联Users
    private Users users;
    //关联Items
    private List<Items> items =new ArrayList<>();
    public int getOrderid() {
        return orderid;
   }
    public void setOrderid(int orderid) {
        this.orderid = orderid;
   }
    public double getOrderprice() {
        return orderprice;
   }
    public void setOrderprice(double orderprice) {
        this.orderprice = orderprice;
 }
    public Users getUsers() {
        return users;
   }
    public void setUsers(Users users) {
        this.users = users;
   }
    public List<Items> getItems() {
        return items;
   }
    public void setItems(List<Items> items)
   {
        this.items = items;
   }
}

Items对象

public class Items {
    private int itemid;
    private String itemname;
    private double itemprice;
    private int itemnum;
    //关联Orders
    private List<Orders> orders = new ArrayList<>();
    public int getItemid() {
        return itemid;
   }
    public void setItemid(int itemid) {
        this.itemid = itemid;
   }
    public String getItemname() {
        return itemname;
   }
    public void setItemname(String itemname)
   {
        this.itemname = itemname;
   }
    public double getItemprice() {
        return itemprice;
   }
    public void setItemprice(double itemprice) {
        this.itemprice = itemprice;
   }
    public int getItemnum() {
        return itemnum;
   }
    public void setItemnum(int itemnum) {
        this.itemnum = itemnum;
   }
    public List<Orders> getOrders() {
        return orders;
   }
    public void setOrders(List<Orders> orders) {
        this.orders = orders;
   }
}

使用对象关联关系存放查询数据

需求:查询用户ID为1的用户信息他的订单信息,以及订单中所包含 的商品信息。

SQL语句

select * from users u,orders o, orders_items oi, items i WHERE u.userid = o.user_id and o.orderid = oi.order_id and oi.item_id = i.itemid and u.userid =1

UserDao接口

/**
     * 查询用户ID为1的用户信息他的订单信息,
     * 以及订单中所包含的商品信息。
     */
    Users selectUsers(int userid);

UsersDaoImpl接口实现类

/**
     * 查询用户ID为1的用户信息他的订单信息,
     * 以及订单中所包含的商品信息。
     */
    @Override
    public Users selectUsers(int userid) {
        Connection conn = null;
        PreparedStatement ps = null;
        ResultSet rs = null;
        Users users =new Users();
        try{
            conn = JdbcDruidUtil.getConnection();
            ps = conn.prepareStatement("select * from users u,orders o, orders_items oi, items i WHERE\n" + "u.userid = o.user_id and o.orderid = oi.order_id and oi.item_id = i.itemid \n" + "and u.userid =?");
            ps.setInt(1,userid);
            rs = ps.executeQuery();
        while(rs.next()){
                //Users对象的ORM映射
              users.setUserid(rs.getInt("userid"));
              users.setUsername(rs.getString("username"));
              users.setUserage(rs.getInt("userage"));
                //Orders对象的ORM映射
                Orders orders = new Orders();
                orders.setOrderid(rs.getInt("orderid"));
                orders.setOrderprice(rs.getDouble("orderprice"));
                users.getOrders().add(orders);
                //Items对象的ORM映射
                Items items = new Items();
                items.setItemid(rs.getInt("itemid"));
                items.setItemname(rs.getString("itemname"));
                items.setItemprice(rs.getDouble("itemprice"));
                items.setItemnum(rs.getInt("itemnum"));
                orders.getItems().add(items);
           }
       }catch (Exception e){
            e.printStackTrace();
            //通过自定义异常解决异常耦合问题
            throw new ApplicationException(e.getMessage());
       }finally{
           JdbcDruidUtil.closeResource(rs,ps,conn);
       }
        return users;
   }

UsersService接口

Users findUsers(int userid);

UsersService接口实现类

@Override
    public Users findUsers(int userid) {
        UsersDao ud = new UsersDaoImpl();
        return ud.selectUsers(userid);
   }
相关实践学习
如何在云端创建MySQL数据库
开始实验后,系统会自动创建一台自建MySQL的 源数据库 ECS 实例和一台 目标数据库 RDS。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助 &nbsp; &nbsp; 相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
目录
相关文章
|
2月前
|
存储 Oracle 关系型数据库
Oracle数据库的应用场景有哪些?
【10月更文挑战第15天】Oracle数据库的应用场景有哪些?
192 64
|
1月前
|
架构师 数据库
大厂面试高频:数据库乐观锁的实现原理、以及应用场景
数据库乐观锁是必知必会的技术栈,也是大厂面试高频,十分重要,本文解析数据库乐观锁。关注【mikechen的互联网架构】,10年+BAT架构经验分享。
大厂面试高频:数据库乐观锁的实现原理、以及应用场景
|
1月前
|
缓存 NoSQL 数据库
运用云数据库 Tair 构建缓存为应用提速,完成任务得苹果音响、充电套装等好礼!
本活动将带大家了解云数据库 Tair(兼容 Redis),通过体验构建缓存以提速应用,完成任务,即可领取罗马仕安卓充电套装,限量1000个,先到先得。邀请好友共同参与活动,还可赢取苹果 HomePod mini、小米蓝牙耳机等精美好礼!
|
1月前
|
SQL Java 数据库连接
在Java应用中,数据库访问常成为性能瓶颈。连接池技术通过预建立并复用数据库连接,有效减少连接开销,提升访问效率
在Java应用中,数据库访问常成为性能瓶颈。连接池技术通过预建立并复用数据库连接,有效减少连接开销,提升访问效率。本文介绍了连接池的工作原理、优势及实现方法,并提供了HikariCP的示例代码。
53 3
|
1月前
|
存储 Java 关系型数据库
在Java开发中,数据库连接是应用与数据交互的关键环节。本文通过案例分析,深入探讨Java连接池的原理与最佳实践
在Java开发中,数据库连接是应用与数据交互的关键环节。本文通过案例分析,深入探讨Java连接池的原理与最佳实践,包括连接创建、分配、复用和释放等操作,并通过电商应用实例展示了如何选择合适的连接池库(如HikariCP)和配置参数,实现高效、稳定的数据库连接管理。
65 2
|
2月前
|
XML 存储 数据库
XML在数据库中有哪些应用?
【10月更文挑战第17天】XML在数据库中有哪些应用?
51 2
|
2月前
|
供应链 数据库
数据库事务安全性控制有什么应用场景吗
【10月更文挑战第15天】数据库事务安全性控制有什么应用场景吗
|
13天前
|
关系型数据库 MySQL 数据库
Python处理数据库:MySQL与SQLite详解 | python小知识
本文详细介绍了如何使用Python操作MySQL和SQLite数据库,包括安装必要的库、连接数据库、执行增删改查等基本操作,适合初学者快速上手。
87 15
|
6天前
|
SQL 关系型数据库 MySQL
数据库数据恢复—Mysql数据库表记录丢失的数据恢复方案
Mysql数据库故障: Mysql数据库表记录丢失。 Mysql数据库故障表现: 1、Mysql数据库表中无任何数据或只有部分数据。 2、客户端无法查询到完整的信息。
|
13天前
|
关系型数据库 MySQL 数据库
数据库数据恢复—MYSQL数据库文件损坏的数据恢复案例
mysql数据库文件ibdata1、MYI、MYD损坏。 故障表现:1、数据库无法进行查询等操作;2、使用mysqlcheck和myisamchk无法修复数据库。
下一篇
DataWorks