带有命名列的 Spring 数据 JPA @Query 映射

sza*_*kel 0 java spring jdbctemplate spring-data-jpa spring-boot

我在 MySQL 中使用 Spring Boot 1.5 和 Spring Data JPA。我试图在单个表上运行一个简单的计数查询,但找不到比这更好的映射查询结果的方法。:

存储库:

public interface VehicleRepository extends JpaRepository<Vehicle, String> {
    @Query("select v.sourceModule as sourceModule, count(v) as vehicleCount from Vehicle v group by v.sourceModule")
    List<Object[]> sourceModuleStats();
}
Run Code Online (Sandbox Code Playgroud)

服务:

@Override
public List<SourceModuleStatDTO> getSourceModuleStats() {
    List<Object[]> objects = vehicleRepository.sourceModuleStats();

    return objects.stream()
            .map(o->SourceModuleStatDTO.from((String)o[0], (Long)o[1]))
            .collect(Collectors.toList());
}
Run Code Online (Sandbox Code Playgroud)

我使用org.immutables,所以 DTO.:

@Value.Immutable
@JsonSerialize(as = ImmutableSourceModuleStatDTO.class)
@JsonDeserialize(as = ImmutableSourceModuleStatDTO.class)
public abstract class SourceModuleStatDTO {
    public abstract String sourceModule();
    public abstract long vehicleCount();

    public static SourceModuleStatDTO from(String sm, long c) {
        return ImmutableSourceModuleStatDTO.builder()
                .sourceModule(sm)
                .vehicleCount(c)
                .build();
    }
}
Run Code Online (Sandbox Code Playgroud)

这里的问题是映射,我需要转换结果或手动检查所有内容。即使JdbcTemplate有更好的映射能力,我也不敢相信没有更好的方法来做到这一点。

我也试过这个:https : //stackoverflow.com/a/36329166/840315,但是你需要将类路径硬编码到查询中才能让它工作,而且我仍然需要将对象映射到不可变对象。

使用 JdbcTemplate,您可以使用RowMapper( src ) :

private static final class EmployeeMapper implements RowMapper<Employee> {
    @Override
    public Employee mapRow(ResultSet rs, int rowNum) throws SQLException {
        Employee employee = new Employee();
        employee.setCountry(rs.getString("country"));
        employee.setEmployeeName(rs.getString("employee"));
        return employee;
    }
}
Run Code Online (Sandbox Code Playgroud)

弹簧数据 JPA 有类似的东西@Query吗?

Ram*_*Ram 7

如何使用投影如下?

static interface VehicleStats { 
    public String getSourceModule();
    public Long getVehicleCount();
}
Run Code Online (Sandbox Code Playgroud)

你的存储库方法是

@Query("select v.sourceModule as sourceModule, count(v) as vehicleCount from Vehicle v group by v.sourceModule")
List<VehicleStats> sourceModuleStats();
Run Code Online (Sandbox Code Playgroud)

在您的 Service 类中,您可以使用如下接口方法。

List<VehicleStats> objects = vehicleRepository.sourceModuleStats();
return objects.stream()
        .map(o->SourceModuleStatDTO.from(getSourceModule(),getVehicleCount() )
        .collect(Collectors.toList());
Run Code Online (Sandbox Code Playgroud)

  • 谢谢!也许它比使用映射器更容易。 (2认同)