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

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
RDS MySQL Serverless 高可用系列,价值2615元额度,1个月
云数据库 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);
   }
相关实践学习
每个IT人都想学的“Web应用上云经典架构”实战
本实验从Web应用上云这个最基本的、最普遍的需求出发,帮助IT从业者们通过“阿里云Web应用上云解决方案”,了解一个企业级Web应用上云的常见架构,了解如何构建一个高可用、可扩展的企业级应用架构。
MySQL数据库入门学习
本课程通过最流行的开源数据库MySQL带你了解数据库的世界。 &nbsp; 相关的阿里云产品:云数据库RDS MySQL 版 阿里云关系型数据库RDS(Relational Database Service)是一种稳定可靠、可弹性伸缩的在线数据库服务,提供容灾、备份、恢复、迁移等方面的全套解决方案,彻底解决数据库运维的烦恼。 了解产品详情:&nbsp;https://www.aliyun.com/product/rds/mysql&nbsp;
目录
相关文章
|
2月前
|
SQL 关系型数据库 数据库
Python SQLAlchemy模块:从入门到实战的数据库操作指南
免费提供Python+PyCharm编程环境,结合SQLAlchemy ORM框架详解数据库开发。涵盖连接配置、模型定义、CRUD操作、事务控制及Alembic迁移工具,以电商订单系统为例,深入讲解高并发场景下的性能优化与最佳实践,助你高效构建数据驱动应用。
344 7
|
2月前
|
存储 人工智能 NoSQL
AI大模型应用实践 八:如何通过RAG数据库实现大模型的私有化定制与优化
RAG技术通过融合外部知识库与大模型,实现知识动态更新与私有化定制,解决大模型知识固化、幻觉及数据安全难题。本文详解RAG原理、数据库选型(向量库、图库、知识图谱、混合架构)及应用场景,助力企业高效构建安全、可解释的智能系统。
|
5月前
|
存储 关系型数据库 数据库
附部署代码|云数据库RDS 全托管 Supabase服务:小白轻松搞定开发AI应用
本文通过一个 Agentic RAG 应用的完整构建流程,展示了如何借助 RDS Supabase 快速搭建具备知识处理与智能决策能力的 AI 应用,展示从数据准备到应用部署的全流程,相较于传统开发模式效率大幅提升。
附部署代码|云数据库RDS 全托管 Supabase服务:小白轻松搞定开发AI应用
|
3月前
|
存储 弹性计算 Cloud Native
云原生数据库的演进与应用实践
随着企业业务扩展,传统数据库难以应对高并发与弹性需求。云原生数据库应运而生,具备计算存储分离、弹性伸缩、高可用等核心特性,广泛应用于电商、金融、物联网等场景。阿里云PolarDB、Lindorm等产品已形成完善生态,助力企业高效处理数据。未来,AI驱动、Serverless与多云兼容将推动其进一步发展。
203 8
|
3月前
|
存储 弹性计算 安全
现有数据库系统中应用加密技术的不同之处
本文介绍了数据库加密技术的种类及其在不同应用场景下的安全防护能力,包括云盘加密、透明数据加密(TDE)和选择列加密。分析了数据库面临的安全威胁,如管理员攻击、网络监听、绕过数据库访问等,并通过能力矩阵对比了各类加密技术的安全防护范围、加密粒度、业务影响及性能损耗。帮助用户根据安全需求、业务改造成本和性能要求,选择合适的加密方案,保障数据存储与传输安全。
|
4月前
|
存储 人工智能 数据库
视图是什么?为什么要用视图呢?数据库视图:定义、特点与应用
本文三桥君深入探讨数据库视图的概念与应用,从定义特点到实际价值全面解析。视图作为虚拟表具备动态更新、简化查询、数据安全等优势,能实现多角度数据展示并保持数据库重构的灵活性。产品专家三桥君还分析了视图与基表关系、创建维护要点及性能影响,强调视图是提升数据库管理效率的重要工具。三桥君通过系统讲解,帮助读者掌握这一常被忽视却功能强大的数据库特性。
1131 0
|
3月前
|
缓存 关系型数据库 BI
使用MYSQL Report分析数据库性能(下)
使用MYSQL Report分析数据库性能
156 3
|
3月前
|
关系型数据库 MySQL 数据库
自建数据库如何迁移至RDS MySQL实例
数据库迁移是一项复杂且耗时的工程,需考虑数据安全、完整性及业务中断影响。使用阿里云数据传输服务DTS,可快速、平滑完成迁移任务,将应用停机时间降至分钟级。您还可通过全量备份自建数据库并恢复至RDS MySQL实例,实现间接迁移上云。
|
3月前
|
关系型数据库 MySQL 分布式数据库
阿里云PolarDB云原生数据库收费价格:MySQL和PostgreSQL详细介绍
阿里云PolarDB兼容MySQL、PostgreSQL及Oracle语法,支持集中式与分布式架构。标准版2核4G年费1116元起,企业版最高性能达4核16G,支持HTAP与多级高可用,广泛应用于金融、政务、互联网等领域,TCO成本降低50%。

热门文章

最新文章