简体   繁体   English

无法在 Spring 数据中实例化 DTO 投影

[英]Cannot instantiate DTO Projection in Spring Data

I am trying to return a custom object RecordData from my repository class, but it tries to instantiate my main Record class. I've tried using Interface Projections , but the result is the same.我试图从我的存储库 class 返回自定义 object RecordData ,但它试图实例化我的主Record class。我尝试使用Interface Projections ,但结果是一样的。

import org.springframework.data.cassandra.core.mapping.PrimaryKey;
import org.springframework.data.cassandra.core.mapping.Table;

@Table
public class Record {

    public record RecordData(long created_at, double value) {

    }

    @PrimaryKey
    private final long sensor_id;

    private final long created_at;

    private final double value;

    public Record(long sensor_id, long created_at, double value) {
        this.sensor_id = sensor_id;
        this.created_at = created_at;
        this.value = value;
    }

    public long getSensorId() {
        return sensor_id;
    }

    public long getCreatedAt() {
        return created_at;
    }

    public double getValue() {
        return value;
    }

}
@Repository
public interface RecordsRepository extends CassandraRepository<Record, String> {

    @Query("SELECT created_at, value FROM record WHERE sensor_id = ?0 and created_at > ?1")
    List<Record.RecordData> findBySensorIdAndCreatedAt(Long sensorId, Long createdAt);

}

Stack-trace:堆栈跟踪:

org.springframework.data.mapping.model.MappingInstantiationException: Failed to instantiate com.example.mainservice.models.entities.Record using constructor public com.example.mainservice.models.entities.Record(long,long,double) with arguments null,300,0.0

Caused by: java.lang.IllegalArgumentException: Parameter sensor_id must not be null!

Make these changes in your code:在您的代码中进行以下更改:

    @Entity
    public class Record {

    public record RecordData(long created_at, double value) {

    }

    @Id
    private final long sensor_id;

    private final long created_at;

    private final double value;

    public Record(long sensor_id, long created_at, double value) {
        this.sensor_id = sensor_id;
        this.created_at = created_at;
        this.value = value;
    }

    public long getSensorId() {
        return sensor_id;
    }

    public long getCreatedAt() {
        return created_at;
    }

    public double getValue() {
        return value;
    }

}

And


@Repository
public interface RecordsRepository extends CassandraRepository<Record, String> {

    @Query("SELECT r.created_at, r.value FROM Record r WHERE r.sensorId = :sensorId and r.createdAt > :createdAt")
    List<Record.RecordData> findBySensorIdAndCreatedAt(@Param("sensorId") Long sensorId, @Param("createdAt") Long createdAt);

}

Try making your table an entity so that it retrieves the data and map it with your object.尝试使您的表成为一个实体,以便它检索数据并使用您的 object 检索数据 map。

As a class which should be persisted in a database it must be annotated Use javax.persistence library for imports作为一个 class 应该保存在数据库中,它必须被注释 Use javax.persistence library for imports

User @Id as this will make your id a primary key as per JPA用户@Id,因为这将使您的 ID 成为 JPA 的主键

Add the @Entity annotation in your table like below and there is no need to write @Table if you are not giving a custom name to your table as @Table is used to name your table.如下所示在表中添加 @Entity 注释,如果您没有为表提供自定义名称,则无需编写 @Table,因为 @Table 用于命名表。 It is stored as that name in your database它作为该名称存储在您的数据库中

@Entity  //insert here
public class Record {

public record RecordData(long created_at, double value) {

}

@Id
private final long sensor_id;
....
}

Try this it should work试试这个它应该工作

you can try this你可以试试这个

@Entity
@Table(name="record")
public class Record {

    public record RecordData(long created_at, double value) {

    }

    @Id
    private final long sensor_id;

    private final long created_at;

    private final double value;

    public Record(long sensor_id, long created_at, double value) {
        this.sensor_id = sensor_id;
        this.created_at = created_at;
        this.value = value;
    }

    public long getSensorId() {
        return sensor_id;
    }

    public long getCreatedAt() {
        return created_at;
    }

    public double getValue() {
        return value;
    }

}
@Repository
public interface RecordsRepository extends CassandraRepository<Record, String> {

    @Query("SELECT created_at, value FROM record WHERE sensor_id = :sensor_id and created_at > :created_at")
    List<Record.RecordData> findBySensorIdAndCreatedAt(@Param("sensor_id")Long sensorId,@Param("created_at") Long createdAt);

}

I should think having a separate class would help我认为有一个单独的 class 会有所帮助

public class RecordData {
    private Long createdAt;
    private Double value;
    public RecordData(Long createdAt, Double value) {
        this.createdAt = createdAt;
        this.value = value;
    }
}

@Repository
public interface RecordsRepository extends CassandraRepository<Record, String> {

    @Query("SELECT new RecordData(r.created_at, r.value) FROM Record r WHERE r.sensorId = :sensorId and r.createdAt > :createdAt")
    List<RecordData> findBySensorIdAndCreatedAt(@Param("sensorId") Long sensorId, @Param("createdAt") Long createdAt);
}

All I needed to add was an empty argument constructor.我需要添加的只是一个空参数构造函数。

public Record() {
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM