小能豆

ibernate原生SQL只查询个别字段转实体类时报错:ERROR org.hibernate.util.JDBCExceptionReporter - 列名 name 无效。

javascript

Java hibernate代码:

StringBuilder sb = new StringBuilder();
sb.append("SELECT u.ID ID FROM dbo.USER u ");
List<User> list = this.getSession().createSQLQuery(sb.toString()).addEntity(User.class).list();

错误信息:
[catalina-exec-1-1]WARN org.hibernate.util.JDBCExceptionReporter - SQL Error: 0, SQLState: S1093
[catalina-exec-1-1] ERROR org.hibernate.util.JDBCExceptionReporter - 列名 name 无效。

错误原因:
User实体中有name字段,而查询SQL没有name字段。

问题:
我就只想查询ID字段,不想查询NAME字段,怎么办呢?
主要我现在即使在SQL中加上了NAME字段,万一后续USER表又加了个AGE字段,岂不是这个SQL又要报错了?
如何才能只查询某几个字段呢?


阅读 39

收藏
2024-06-22

共1个答案

小能豆

在 Hibernate 中,如果你只想查询某几个字段而不是整个实体,可以使用 createSQLQuerycreateQuery 方法,并将结果映射到一个 DTO(数据传输对象)或使用投影。下面是几种常见的方法:

方法 1:使用投影(Projection)

投影可以让你只选择特定的字段,并将结果映射到一个 DTO 或其他合适的数据结构。

StringBuilder sb = new StringBuilder();
sb.append("SELECT u.ID AS id FROM dbo.USER u");

List<Object[]> result = this.getSession().createSQLQuery(sb.toString()).list();
List<Long> ids = result.stream()
                       .map(row -> (Long) row[0])
                       .collect(Collectors.toList());

方法 2:使用自定义 DTO

你可以创建一个专门的 DTO 类来持有查询结果,并使用 createSQLQuery 方法来进行查询。

首先,创建一个 DTO 类:

public class UserDTO {
    private Long id;

    public UserDTO(Long id) {
        this.id = id;
    }

    // Getter and Setter
    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }
}

然后,使用自定义查询并将结果映射到 DTO:

StringBuilder sb = new StringBuilder();
sb.append("SELECT u.ID AS id FROM dbo.USER u");

List<Object[]> result = this.getSession().createSQLQuery(sb.toString()).list();
List<UserDTO> users = result.stream()
                            .map(row -> new UserDTO((Long) row[0]))
                            .collect(Collectors.toList());

方法 3:使用 Hibernate 原生查询和 ResultTransformer

你也可以使用 Hibernate 的 ResultTransformer 来将结果映射到自定义对象。

StringBuilder sb = new StringBuilder();
sb.append("SELECT u.ID AS id FROM dbo.USER u");

List<UserDTO> users = this.getSession().createSQLQuery(sb.toString())
                           .setResultTransformer(Transformers.aliasToBean(UserDTO.class))
                           .list();

方法 4:使用 JPQL 或 HQL 查询

如果你更喜欢使用 JPQL 或 HQL 查询,你可以使用 createQuery 方法来实现。

String hql = "SELECT new com.yourpackage.UserDTO(u.id) FROM User u";
List<UserDTO> users = this.getSession().createQuery(hql).list();

在上述示例中,UserDTO 是你自定义的 DTO 类,其构造函数接受 id 参数。

总结

为了避免将来数据库表结构变化导致的问题,最好使用专门的 DTO 类来接收查询结果,并且只查询你需要的字段。这样不仅提高了查询效率,还减少了因表结构变化导致的代码维护问题。

2024-06-22