hibernate查询返回DTO对象,DTO封装了多个pojo对象的属性

本文介绍如何使用Hibernate查询DTO对象,并通过原生SQL结合Transformers.aliasToBean方法将查询结果映射到DTO对象中,实现业务数据的有效传递。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

      DTO-数据传输对象;pojo-最纯粹的java对象与数据库中的表一一对应。

      简单讲:DTO起到业务数据的传递作用,pojo则与持久层数据库打交道。

 

      有时候我们需要查询返回DTO对象,因为DTO封装我们操作此对象的业务方法;而这些业务方法从分层的思想上看不能封装到pojo中,因为这违背了hibernate编程规范,pojo(Plain Ordinary Java Object是一个简单的普通Java对象,它不包含业务逻辑或持久逻辑。

       hibernate查询返回DTO对象,DTO可能封装了多个pojo对象的属性和自己的业务方法;比如一个购物车的DTO可能封装了与购物车添加商品、移除商品等的方法。

 

       上代码:

public AccountDTO getAccountByUsernameAndPassword(AccountDTO accountDTO) {
		String sql = "SELECT"
		      + " SIGNON.USERNAME,"
		      + " ACCOUNT.EMAIL,"
		      + " ACCOUNT.FIRSTNAME,"
		      + " ACCOUNT.LASTNAME,"
		      + " ACCOUNT.STATUS,"
		      + " ACCOUNT.ADDR1,"
		      + " ACCOUNT.ADDR2,"
		      + " ACCOUNT.CITY,"
		      + " ACCOUNT.STATE,"
		      + " ACCOUNT.ZIP,"
		      + " ACCOUNT.COUNTRY,"
		      + " ACCOUNT.PHONE,"
		      + " PROFILE.LANGPREF,"
		      + " PROFILE.FAVCATEGORY,"
		      + " PROFILE.MYLISTOPT,"
		      + " PROFILE.BANNEROPT,"
		      + " BANNERDATA.BANNERNAME"
		      + " FROM ACCOUNT, PROFILE, SIGNON, BANNERDATA"
		      + " WHERE ACCOUNT.USERID = ?"
		      + " AND SIGNON.PASSWORD = ?"
		      + " AND SIGNON.USERNAME = ACCOUNT.USERID"
		      + " AND PROFILE.USERID = ACCOUNT.USERID"
		      + " AND PROFILE.FAVCATEGORY = BANNERDATA.FAVCATEGORY";
//		Query query = this.getSession().createQuery(hql);
		//此方法有transaction的异常,因为我这里不是手动管理hibernate的事物,hibernate事物交给spring管理,此问题没能解决
//		Query query = this.getSessionFactory().getCurrentSession().createSQLQuery(sql).setResultTransformer(Transformers.aliasToBean(aDTO.class));
		Query query = this.getSession().createSQLQuery(sql).setResultTransformer(Transformers.aliasToBean(AccountDTO.class));
		query.setString(0, accountDTO.getUsername());
		query.setString(1, accountDTO.getPassword());
		return (AccountDTO) query.uniqueResult();
	}

 这里的重点方法:

Query query = this.getSession().createSQLQuery(sql).setResultTransformer(Transformers.aliasToBean(AccountDTO.class));

 原生sql的查询,返回结果设置到DTO,hibernate给我们做了处理,类似与jdbc的查询这里可能用到了反射,所以要求DTO中的属性要与表字段名称相同,并且为全都小写。(我试图在sql中使用别名,而且DTO中属性使用了驼峰命名,但结果出错。网上有文章说:只需别名和属性名称一致即可;但我测试未成功。有经验的朋友请指教!)

 

搞完!

<think>嗯,用户问的是关于VO、DTOPOJO这些对象类型,他们一般是什么。我需要先回忆一下这些术语的定义和常见的应用场景。首先,这些都属于Java开发中常用的数据对象,用于不同层次之间的数据传输和封装。 首先,POJO,全称是Plain Old Java Object,也就是普通的Java对象,没有继承特定的类或实现特定的接口,主要用来承载数据,通常有getter和setter方法。POJO是一个比较通用的概念,可能在不同的上下文中被具体化,比如PO、DTO、VO等。 然后是PO,可能是指Persistent Object,也就是持久化对象。这类对象通常和数据库的表结构直接对应,每个字段对应数据库表中的一列。比如Hibernate中的实体类就是PO,它们可能会有JPA的注解,如@Entity,@Table等。 接下来是DTO,Data Transfer Object,数据传输对象。它的主要作用是在不同层之间传输数据,尤其是在远程调用时,减少网络调用次数。比如,在服务层和控制器层之间传输数据时,可能会用DTO封装多个POJO的数据,避免暴露数据库结构或传输过多的数据。 VO,View Object,视图对象。通常用于展示层,比如前端页面需要的数据结构可能与数据库中的结构不同,这时候可以用VO来封装适配后的数据。例如,一个用户信息页面可能需要组合用户的基本信息、地址信息等,VO可以将这些数据整合成一个对象传递给前端。 BO,Business Object,业务对象。它封装了业务逻辑,可能包含业务方法,处理复杂的业务规则。BO通常由Service层使用,聚合多个PO或DTO,进行业务处理。 DO,Domain Object,领域对象。在领域驱动设计(DDD)中,DO代表业务领域中的实体,包含数据和业务行为,更侧重于业务模型的表达。 用户可能是在实际开发中遇到了层次划分的问题,或者在项目中看到这些不同的对象类型,想要了解它们的区别和使用场景。可能用户对如何在不同层之间传递数据,如何设计对象模型有疑问,或者想要优化现有的代码结构,避免对象混用导致的耦合问题。 需要进一步考虑的是,用户是否有具体的应用场景,比如是否在使用Spring框架,或者进行微服务开发,不同的架构可能会对这些对象的使用有不同的约定。例如,在Spring MVC中,Controller层通常使用DTO与前端交互,Service层使用BO处理业务,DAO层使用PO与数据库交互。VO可能用于前端展示,特别是当需要组合多个数据源的数据时。 另外,用户可能混淆了这些概念,或者在实际开发中遇到了命名不统一的问题,需要明确每个对象的职责和适用场景,以便在团队协作中保持代码的一致性和可维护性。 总结一下,回答需要分点解释每个对象的定义、用途和典型场景,比较它们的区别,帮助用户理解何时该使用哪种对象类型。同时,可能需要举例说明,比如在MVC架构中各层之间的对象传递,或者微服务中DTO的作用,这样用户更容易理解。</think>在分层架构设计中,不同对象类型有明确的职责划分,以下是常见对象的定义和典型应用场景: --- ### 一、基础概念 1. **POJO (Plain Old Java Object)** - 普通Java对象 - **特征**:无强制继承/实现,仅有属性和getter/setter - **作用**:通用数据载体,可衍生为其他具体对象(如DTO/VO/PO) 2. **PO (Persistent Object)** - 持久化对象 - **特征**:与数据库表结构严格对应,含JPA/Hibernate注解(如`@Entity`) - **场景**:DAO层操作数据库时使用 - 示例: ```java @Entity @Table(name = "user") public class UserPO { @Id private Long id; private String username; } ``` --- ### 二、传输与业务对象 3. **DTO (Data Transfer Object)** - 数据传输对象 - **特征**:跨进程/网络传输,字段可能聚合多个PO的数据 - **场景**:Service层与Controller层之间传输数据 - 示例: ```java public class OrderDTO { private String orderId; private List<Product> products; // 聚合多个PO数据 } ``` 4. **VO (View Object)** - 视图对象 - **特征**:适配前端展示需求,字段可包含格式化数据(如日期转字符串) - **场景**:Controller层返回给前端的数据结构 - 示例: ```java public class UserVO { private String name; private String formattedBirthday; // "yyyy-MM-dd"格式 } ``` --- ### 三、复杂业务场景对象 5. **BO (Business Object)** - 业务对象 - **特征**:封装业务逻辑,包含状态和行为 - **场景**:Service层处理复杂业务逻辑 - 示例: ```java public class ShoppingCartBO { private List<Item> items; public BigDecimal calculateTotal() { ... } // 业务方法 } ``` 6. **DO (Domain Object)** - 领域对象(DDD概念) - **特征**:聚焦业务核心模型,包含领域规则 - **场景**:领域驱动设计中的核心模型 - 示例: ```java public class BankAccount { private BigDecimal balance; public void withdraw(Money amount) { ... } // 领域行为 } ``` --- ### 四、核心区别总结 | 对象类型 | 层级 | 核心目的 | 典型特征 | |----------|---------------|------------------------------|--------------------------| | PO | DAO层 | 直接映射数据库表结构 | 含JPA注解,与表字段对应 | | DTO | Service/Controller层 | 跨层数据传输 | 扁平化结构,无业务逻辑 | | VO | Controller层 | 适配前端展示需求 | 包含格式化/聚合数据 | | BO | Service层 | 封装复杂业务逻辑 | 包含状态和行为 | | DO | 领域层 | 表达业务领域模型 | 聚焦领域规则和核心逻辑 | --- ### 五、实际应用示例 假设开发电商系统: 1. **DAO层**:用`OrderPO`操作数据库订单表 2. **Service层**:通过`OrderBO`计算订单总价,调用`OrderDTO`向Controller传输数据 3. **Controller层**:将`OrderDTO`转换为`OrderVO`,添加前端需要的格式化字段 4. **前端**:接收`OrderVO`渲染页面 通过明确对象职责,可避免以下问题: - 数据库结构直接暴露给前端 - 业务逻辑污染Controller层 - 传输冗余数据导致性能下降
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值