关于Java:如何在不自动创建表的情况下生成实体类

How to generate entity class without create table automatic

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

我的问题是,对于每个域类,Hibernate正在创建一个表,该如何停止它?

我的域类:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
@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;
}

我的存储库:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
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);

//....

在@Zagarh回答之后,我做了一些关于DTO的搜索,但我想出了一个不太优雅的解决方案,但这是可行的:

Domain类:

1
2
3
4
5
6
7
8
public class WidgetDailyReportDomain{

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

}

我必须创建一个自定义结果映射,为了使JPA能够映射结果,我使用了注释@SqlResultSetMapping。但是由于某种原因,她只能在使用@ Entity注释的类中进行标识。为了不变得混乱,我创建了一个@ SqlResultSetMapping注释专用的类,因为我要做很多映射工作。该类如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
@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存储库的自定义实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
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翻译。


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

如果您使用的是Spring Boot,则可以添加

1
2
3
4
spring:
  jpa:
    hibernate:
      ddl-auto: none

到您的application.yml文件或

1
spring.jpa.hibernate.ddl-auto=none

到您的application.properties文件。

如果您使用的是persistence.xml文件,则也可以在其中添加一个属性以将其禁用:

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

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


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

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

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


您的WidgetDailyReportDomain实际上是投影。您无需将其标记为@Entity。
您的@Query可以属于任何其他实际存在的存储库。