如何在不自动创建 table 的情况下生成实体 class

How to generate entity class without create table automatic

我为我的系统创建了一些报告,该报告由许多 table 组成。为此,我创建了一个带有@Entity 注释的域class 并实现了一个JpaRepository 存储库,我使用带有@Query 的本机查询,如下所示。

我的问题是休眠正在为每个域 class 创建一个 table,我该如何停止它?

我的域名class:

@Entity
@Immutable
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@IdClass(WidgetDailyReportCompositeKey.class)
public class WidgetDailyReportDomain{

    @Id
    @Column(updatable = false, insertable = false)
    private UUID id_construction;

    @Id
    @Column(updatable = false, insertable = false)
    private String name;

    @Id
    @Column(updatable = false, insertable = false)
    private Date dt_cost;

    @Column(updatable = false, insertable = false)
    private Double total;
}

我的存储库:

public interface WidgetRepository extends JpaRepository<WidgetDailyReportDomain, UUID>{

    @Query(value =  "     SELECT ct.id AS id_construction,                                                                                              " +
                    "            ct.name,                                                                                                               " +
                    "            sm.dt_service AS dt_cost,                                                                                              " +
                    "            sum(smi.nu_value * stiv.amount) AS total                                                                               " +
                    "       FROM service_measurement sm                                                                                                 " +
                    " INNER JOIN service_measurement_item smi   ON smi.id_service_measurement = sm.id                                                   " +
                    " INNER JOIN service s                      ON s.id                       = sm.id_service                                           " +
                    " INNER JOIN service_type_item_service stiv ON stiv.id_service            = sm.id_service                                           " +
                    "                                          AND stiv.id_service_type_item = smi.id_service_item                                      " +
                    " INNER JOIN construction ct                ON ct.id                      = s.id_construction                                       " +
                    "      WHERE s.id_construction IN (                                                                                                 " +
                    "                                   select s.id_construction                                                                        " +
                    "                                   from service_measurement sm                                                                     " +
                    "                                   INNER JOIN service_measurement_item smi   ON smi.id_service_measurement = sm.id                 " +
                    "                                   INNER JOIN service s                      ON s.id                       = sm.id_service         " +
                    "                                   INNER JOIN service_type_item_service stiv ON stiv.id_service            = sm.id_service         " +
                    "                                                                            AND stiv.id_service_type_item  = smi.id_service_item   " +
                    "                                   INNER JOIN construction ct                on ct.id                      = s.id_construction     " +
                    "                                   WHERE sm.dt_service BETWEEN :minDate AND :maxDate                                               " +
                    "                                   GROUP BY s.id_construction                                                                      " +
                    "                                   ORDER BY sum(smi.nu_value * stiv.value) DESC                                                    " +
                    "                                   limit :limit                                                                                    " +
                    "       )                                                                                                                           " +
                    "       AND sm.dt_service BETWEEN :minDate AND :maxDate                                                                             " +
                    "  GROUP BY ct.id, sm.dt_service                                                                                                    " +
                    "    HAVING sum(smi.nu_value * stiv.amount) > 0                                                                                     " +
                    "  ORDER BY sm.dt_service;", nativeQuery = true)
    List<WidgetDailyReportDomain> findTopExpensiveConstruction(@Param("minDate") Date minDate, @Param("maxDate") Date maxDate, @Param("limit") int limit);

//....

你的WidgetDailyReportDomain其实就是投影。您不需要将其标记为@Entity。 并且您的@Query 可以属于任何其他真正存在的存储库。

您可以删除所有 javax.persistence 注释,例如 @Column@Id@Entity。这些注释表示 table 的属性,您似乎不希望它是这样。

然后您可以使用 WidgetDailyReportDomain 对象作为 DTO 作为您的投影,而不是将其附加到 EntityManager: https://docs.spring.io/spring-data/jpa/docs/current/reference/html/#projections.dtos

编辑:另外,不要忘记为该对象构建构造函数,以便 Spring JPA 将值加载到对象中(如文档中所述)。 如果您不想构建构造函数,也许您可​​以将其更改为接口并将其用作您的投影:https://docs.spring.io/spring-data/jpa/docs/current/reference/html/#projections.interfaces

由于您问题中的 JpaRepository,您似乎正在使用 Spring。

如果你使用Spring启动,那么你可以添加

spring:
  jpa:
    hibernate:
      ddl-auto: none

到您的 application.yml 文件,或

spring.jpa.hibernate.ddl-auto=none

到您的 application.properties 文件。

如果您使用的是 persistence.xml 文件,您也可以添加 属性 来禁用它:

<property name="hibernate.hbm2ddl.auto" value="none"/>

不过,像这样禁用模式表的生成意味着您必须确保它们是通过其他方式创建的,然后您的应用程序才能运行。

在@Zagarh 回答后,我对 DTO 进行了一些搜索,我想出了一个不太优雅的解决方案,但这是有效的:

域 class :

public class WidgetDailyReportDomain{

    private UUID id_construction;
    private String name;
    private Date dt_cost;
    private Double total;

}

我必须创建自定义结果映射,为了让 JPA 能够映射结果,我使用注释 @SqlResultSetMapping。但出于某种原因,她只在一个 class 中被识别,该 class 被注释为 @ Entity。为了不混乱,我创建了一个 class 专用于注释 @ SqlResultSetMapping,因为我有很多映射要做。 class 看起来像这样:

@MappedSuperclass
@SqlResultSetMapping(
        name = "widget_daily_mapping",
        classes = {
                @ConstructorResult(
                        targetClass = WidgetDailyReportDomain.class,
                        columns = {
                                @ColumnResult(name="id_construction", type = UUID.class),
                                @ColumnResult(name = "name", type = String.class),
                                @ColumnResult(name = "dt_cost", type = Date.class),
                                @ColumnResult(name = "total", type = Double.class)
                        }

                )
        }
)
public abstract class ResultSetMappingConfig {
}

然后我创建 Jpa 存储库的自定义实现

public interface WidgetRepositoryCustom {
    List<WidgetDailyReportDomain> findTopExpensiveConstruction(Date minDate, Date maxDate, int limit);

}


@Repository
@Transactional(readOnly = true)
public class AR_serviceRepositoryImpl implements AR_serviceRepositoryCustom{

    @PersistenceContext
    private EntityManager em;

    @Override
    public List<AR_serviceDomain> getListOfService(UUID id_construction) {
        Query query = em.createNativeQuery("
          //Native Query Here...
        ", "widget_daily_mapping");// Put the result mapping Here
        query.setParameter(1, id_construction //..Parameters Here);
        return query.getResultList();
    }
}

Ps: 1) 如果有人有更好的解决方案请告诉我。 2) 抱歉我的英语不好,我正在使用 google 翻译。