Spring Boot“不是实体”

Posted

技术标签:

【中文标题】Spring Boot“不是实体”【英文标题】:SpringBoot "not an entity" 【发布时间】:2019-03-18 21:01:48 【问题描述】:

我是 Hibernate 和 SpringBoot 的新手。我的项目处理的搜索引擎由 2 个独立模块 + 1 个共同的基本模块(IndexSetup 类所在的位置)组成。

有一个模块用于索引(JavaFx),另一个模块用于通过网络浏览器进行搜索(Spring Boot)。

索引模块涉及一个“IndexSetup”类,其中包含有关如何/什么应该被索引的详细信息:

@Entity
@Table(name = "IndexSetups")
@Access(AccessType.PROPERTY)
public class IndexSetup 
  private final SimpleIntegerProperty id = new SimpleIntegerProperty();

  @Id
  @GeneratedValue(strategy = GenerationType.AUTO) // For H2 AUTO is required to auto increment the id
  public int getId() 
      return id.get();
  

  //... other properties, getters and setters

 

所以它工作得很好,数据被索引并且可以通过索引模块中的搜索方法检索。

但是,当我运行 Spring Boot 服务器并进行相同的搜索时,我得到了 java.lang.IllegalArgumentException:不是实体:类 my.package.IndexSetup

顺便说一句,没有构建错误,并且在模块成为父 pom 项目的一部分之前,它们与服务器类位于子文件夹中的同一个项目中,并且可以正常工作。我决定在开发过程中为了方便将它们分开,并在生产中提供两个独立的模块。

那么为什么当一切都在同一个 Netbeans 项目下并且现在模块位于 2 个不同的子文件夹中(但在同一个组 ID 包“my.package”中)时它会起作用,我得到这个“不是实体”和什么我应该怎么做才能解决这个问题,我应该在哪里看?

请注意:我已经尝试过this,但没有成功(“空指针异常,无法加载数据库”)。

编辑 1: 我还尝试在this 之后添加@EntityScan,但我仍然得到Not an entity: class my.package.IndexSetup

@SpringBootApplication
@EntityScan( basePackages = "my.package" )
public class ServerApplication 

public static void main(String[] args) 
    SpringApplication.run(ServerApplication.class, args);
 

编辑 2: 该项目的架构是这样的:

- Parent project (my.package)
  -Module Base (with IndexSetup class)
  -Module Indexing (that depends on Base)
  -Module Server (that also depends on Base)

父 pom.xml 如下所示:

    <?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>my.package</groupId>
<artifactId>MyApp</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>pom</packaging>
<properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<!--According to https://***.com/questions/10665936/maven-how-to-build-multiple-independent-maven-projects-from-one-project-->

<modules>
    <module>Base</module> <!-- Common resources which is a dependency in Indexer and Server -->
    <module>Indexer</module> <!-- Indexing part with JavaFx-->
    <module>Server</module> <!-- Server (spring boot) part of -->
</modules>
<name>MyApp</name>

<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <version>3.8.0</version>
            <configuration>
                <source>1.8</source>
                <target>1.8</target>
                <compilerArguments>
                    <bootclasspath>$sun.boot.class.path$path.separator$java.home/lib/jfxrt.jar</bootclasspath>
                </compilerArguments>
            </configuration>
        </plugin>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-surefire-plugin</artifactId>
            <version>2.16</version>
            <configuration>
                <additionalClasspathElements>
                    <additionalClasspathElement>$java.home/lib/jfxrt.jar</additionalClasspathElement>
                </additionalClasspathElements>
            </configuration>
        </plugin>
    </plugins>
</build>

编辑 3: 问题出在指定要查看的表时:

Root<IndexSetup> from = criteriaQuery.from(IndexSetup.class);

查看hibernate sources not an entityentityType == null 时抛出。 所以我不知道为什么实体类型在这里为 null 而它在 SpringBoot 之外工作?

编辑 4: 如果我从 Server 类的 main 方法中删除 SpringApplication.run(ServerApplication.class, args);,那么导致问题的同一个调用即:

LocalDatabase.getInstance(false) // no GUI
            .getAllIndexSetups();

现在可以使用 picobello。当然它不能解决任何问题,因为我仍然需要 SpringBoot 进行搜索!所以对我来说,这意味着 Spring Boot 不了解休眠配置。我开了new question更准确的介绍问题。

任何帮助表示赞赏,

【问题讨论】:

@Justas 你是对的,id 字段没有用@Id 标记。但是@Id 标记在getId 方法上,因为idSimpleIntegerProperty (JavaFx)。因此,将 SimpleIntegerProperty 与 hibernate 一起使用是诀窍。您认为这是造成问题的原因吗? 你试过删除@Entity吗?你为什么需要它?或者尝试在 id 上添加@Id。 每个实体都必须有标识符/主键:***.com/questions/30712842/… 为什么需要实体和休眠进行索引? Hibernate是ORM,方便访问关系型数据库,而不是查询索引。 @Justas 用户可以添加 IndexSetup(带有索引名称、要索引的数据、已启用...)。我将这些IndexSetups存储在数据库中,然后用solr一一处理。在搜索时,我在每个索引上调用我的搜索功能(通过 SolrJ):givenIndex.search(params)。这就是为什么我需要在搜索时获取 IndexSetups 列表。 【参考方案1】:

我认为您应该在第二个项目/模块中添加到您的实体的 @EntityScan 注释包中

【讨论】:

感谢@Emil Hotkowski,但它不起作用(请参阅我的编辑)。 在我更改了很多东西之后它确实起作用了,其中@EntityScan 我在回答中详细说明了这一点。还是谢谢。 很高兴它有帮助:)【参考方案2】:

首先,进行一些检查:

您的所有配置是仅使用 ServerApplication 或任何 Java 类中的注释构建的,还是在 XML / YML 文件中有任何其他外部配置?也许寻找冲突。如果可能,我们不希望将 XML 与注释配置混合使用。 尝试删除@Serializable(不是必须的)。 尝试在根包中移动实体(仅作为测试)。 检查导出@Entity的包是否正确。

问题:你所说的“模块”是什么,它是一个子包还是 Maven 模块或其他东西?我们可以配置一下这个包名吗?

编辑

对于多模块项目,您是否遵循spring.io 关于多模块项目的建议?您是否在子模块中导入了 Spring BOM(或启动器)并测试了 Spring Boot Maven Plugin ? 您能否提供您的application.properties(或application.yml)与您的数据源配置?您应该检查您的数据源(和 JPA、驱动程序类...)是否正确定义;见spring.io

【讨论】:

谢谢@cactuschibre,我会尝试你的建议。模块是 Maven 模块(请参阅我在编辑中添加的父 pom.xml)。 我删除了implements serializable,正如here所解释的那样,没有改变。 我将 IndexSetup 类移动到名为 Entities 的子文件夹中,相应地更新了 hibernate.cfg.xml(否则我会得到 NPE)但我仍然得到 Not an entity。索引器模块没有问题,可以完美地使用这个实体。 很棒的链接@cactuschibre!不,我还没有关注这些链接,但我现在就去做,然后重试! application.properties 中只有 server.port=8081 最终我得到了它的工作。我将写下我是如何做到的,其中结合了您的一些其他人的提示和许多其他 SO 问题!学到了很多,谢谢!【参考方案3】:

所以碰巧我没有正确使用 SpringBoot 功能。这是我遵循的步骤。请记住项目的架构:

- Parent maven project (my.package)
 |-Module Base (with IndexSetup class and [initialy] hibernate.cfg.xml in /resources. It also had in the beginning LocalDatabase class to access to the local db via hibernate)
 |-Module Indexing (that depends on Base)
 |-Module Server (that also depends on Base)
 |-Database file (myLocalDB)

1) 首先,我从 Base 中删除了 hibernate.cfg.xml 并将其放入 Indexing 模块的资源中。我这样做是因为 SpringBoot 有自己的配置机制。我还从 Base 中删除了 LocalDatabase 类(因为 SpringBoot 不需要它)并将其也放到 Indexing Module 中(确实使用它的地方)。

2) 在 [this](https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-sql.html] 之后,我将 spring-boot-starter-data-jpa 添加到服务器模块 pom.xml。

3) 在 this tutorial 之后,我创建了一个 JPA 存储库 IndexSetupRepository,几乎没有一行代码:

public interface IndexSetupRepository extends CrudRepository<IndexSetup, Integer> 

4) 在服务器 application.properties 我添加了这些行:

# Embedded database configuration
# The embedded database file is one level above the Server folder (ie directly within the parent project)
# we use the auto server mode to be able to use the database simultaneously in the indexer and the server
spring.datasource.url=jdbc:h2:file:../myLocalDB;AUTO_SERVER=TRUE
spring.datasource.username=myName
# This parameter helped me discover that SpringBoot was not targetting the right table name.
spring.jpa.hibernate.ddl-auto=validate

5) 由于 SpringBoot 告诉我它找不到名为 index_setup 的表(请参阅 camel case converted to _),我必须将此行添加到 application.properties :

spring.jpa.hibernate.naming.physical-strategy=org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl

6) 现在,当我得到“实体不受管理”时,我最终按照你们中许多人的建议在 Server 主类中添加了 @EntityScan 注释。

@EntityScan("my.package.Entities")

请注意@EntityScan 应该指向包含实体类的文件夹而不是实体类本身,即@EntityScan("my.package.Entities.IndexSetup") 不起作用。

【讨论】:

以上是关于Spring Boot“不是实体”的主要内容,如果未能解决你的问题,请参考以下文章

Spring Boot 2Spring Boot CLI

将已有的spring app迁移到spring-boot,手动配置spring-boot?

为啥 Spring Boot 应用程序 pom 同时需要 spring-boot-starter-parent 和 spring-boot-starter-web?

《02.Spring Boot连载:Spring Boot实战.Spring Boot核心原理剖析》

spring-boot-quartz, 依赖spring-boot-parent

spring-boot系列:初试spring-boot