当前位置: 首页 > 知识库问答 >
问题:

使用Spring存储库填充实体中的非列字段

费凯康
2023-03-14

我想使用数据库中的本机查询来检索给定记录的更多数据,我正在寻找如何声明容纳这些数据的字段的解决方案。

如果我不注释该字段,在更新期间JPA认为该字段应该映射到同名列(当然表中不存在);如果我用@瞬态对其进行注释,则该字段在更新时被忽略,但在选择时也被忽略(为什么?)。

我们用一个例子来澄清一下。我有实体< code >折扣

class Discount {
    @Column(name = "ID")
    private long id;

    @Column(name = "PRODUCT_ID")
    private long productId;

    // private String productName; <-- Uncommented, error on save; with @Transient empty on read
}

当我从数据库中检索折扣时,我还希望使用相同的查询返回整个记录以及来自product表的产品名称。

使用Spring存储库,我设置查询如下:

public interface DiscountRepo extends Repository<Discount, Long> {
    @Query(nativeQuery = true, value = "select d.*,p.name as productName from discount d join product p on d.product_id = d.id")
    List<Discount> getAll();
}

我不想在折扣实体中拥有类似私人产品的属性的原因是,在select上,会从数据库传输太多数据,而我只需要产品名称。


共有2个答案

谷梁英资
2023-03-14

您可以使用JdbcTempate,然后将返回值映射到Discount.class

  1. String sqlQuery="选择d.ID作为id,d.PRODUCT_ID作为productIdp.name作为productName from折扣d加入产品pd.product_id=d.id";
  2. 地图

常哲彦
2023-03-14

使用@Transient标记字段与为 Java 序列化进程标记瞬态内容具有相同的效果 - 它在两个方向上都完全被排除在数据库持久性之外。无论如何,您都不希望尝试将其作为常规属性读取,因为这会干扰所有 Discount 读取操作 - 如果这是您想要的,则可能应该在实体中映射此字段。

我建议您为此数据操作使用其他一些非实体对象,以便您的业务逻辑不会将此折扣对象数据与额外的“productName”混淆或混合在一起,这些操作将与其他折扣上的 JPA 操作一起填充,而这些操作将被省略。

也就是说,您可以使用JPA构造函数查询或构造函数操作让它从数据中构建任何pojo。您只需要对象上的构造函数来接受相同的参数和类型。

@Entity
class Discount {
    @Column(name = "ID")
    private long id;

    @Column(name = "PRODUCT_ID")
    private long productId;

    @Transient
    private String productName;

    public AbstractDomainObject(Long id, Long productId, String productName)  {
      this.id = id;
      this.productId = productId;
      this.productName = productName;
    }
}

然后你可以用

public interface DiscountRepo extends Repository<Discount, Long> {
    @Query("select new your.package.Discount(d.id, d.productId, p.productName) from discount d join product p on d.productId = p.id"
    List<Discount> getAll();
}

如果您的提供商不支持这样的联接(有些提供商允许),您仍然可以获得产品参考折扣。只需确保将其标记为懒惰 - 在查询中使用它不会强制获取所有数据。只需确保您的提供者支持懒惰关系,因为许多需要额外的东西,例如增强类:

 public interface DiscountRepo extends Repository<Discount, Long> {
    @Query("select new your.package.Discount(d.id, d.productId, p.productName) from discount d join d.product p"
    List<Discount> getAll();
}

或者,您仍然可以使用本机查询,但可能希望在实体中使用定义结果生成方式的SqlResultSetMapping来定义它:

@Entity
@SqlResultSetMappings(
    SqlResultSetMapping(
            name = "summary",
            classes = [
                ConstructorResult(
                        targetClass = Discount.class,
                        columns = [
                            ColumnResult(name = "id", type = Long::class),
                            ColumnResult(name = "productId", type = Long::class),
                            ColumnResult(name = "productName", type = String::class)
                        ]
                )
            ]
    )
)
@NamedNativeQueries(
    NamedNativeQuery(name = "Discount.getAll",
            query = "select d.*,p.name as productName from discount d join product p on d.product_id = p.id", resultSetMapping = "summary")
)
class Discount {
..

然后,Spring在repo中执行getAll时应该查找该查询名称:

public interface DiscountRepo extends Repository<Discount, Long> {
    List<Discount> getAll();
}
 类似资料:
  • 我在一个spring webmvc项目上使用spring-data-jpa。我在使用我的一个实体的存储库创建查询时遇到了一个问题。下面您可以看到我的实体、我的存储库和异常。 我的实体: 我的存储库: 而例外, 最后,我将重命名为(删除下划线),并重命名getters/setters和存储库(),问题得到解决。 我的问题是为什么会发生这种情况?

  • 虽然这是我配置的用户名,但YES不是我在application.properties文件中提供的密码,也不是我的MySQL工作台密码。如何正确配置Spring Boot应用程序来识别我的MySQL工作台,并用User@Entity JPA注释自动填充TestSchema数据库?

  • 我想使用SpringDataRepository接口来执行本机查询——我认为这种方式最简单,因为复杂性较低。 但是当扩展接口时。

  • 我正在尝试实现一个简单的REST服务,该服务基于具有Spring启动和Spring数据Rest的JPA存储库。(请参阅此教程)如果将以下代码与 gradle 一起使用,则运行良好: 为了让事情变得更简单,我使用Spring boot CLI(“Spring run”命令)尝试了相同的代码。 不幸的是,这似乎不起作用@RepositoryRestResource似乎无法像@RestControlle

  • 我希望像查询NodeEntity一样查询RelationshipEntity。 软件包信息: 此存储库不工作。 getEmployeeWorkingOnProject(String,String)返回NULL 我在关键字之后进行了修改,例如将其从修改为像这样的别名,并且还尝试更改了返回中别名的顺序。 我希望获得与特定员工和特定项目相关联的所有状态(边缘)。 或 或其他类型的类似结果,其中关系实体持

  • 问题内容: 我在spring webmvc项目上使用spring-data- jpa。我在一个实体的存储库上使用查询创建时遇到问题。在下面,您可以看到我的实体,我的存储库和异常。 我的实体: 我的资料库: 和例外, 我试图将Intory上的参数设置为int,然后设置为和,但是都没有设置。另外,我将存储库重命名为,但也没有用。 最后,我 改名 了以(下划线删除),也改名为getter / sette