JPA 实体未映射

JPA Entity is not mapped

我有 Spring 个使用六边形架构的微服务应用程序。 当尝试使用 hql 查询从我的 H2 数据库中获取数据时,出现异常,提示我的实体未映射。我的实体是另一个具有公共属性的实体的子class。

package com.package.infrastructure.repository.jpa.entity.nomenclature;

import lombok.Data;

import javax.persistence.*;

@Data
@MappedSuperclass
public class NomenclatureEntity {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(length = 50)
    private String label;
}

Activity

package com.package.company.infrastructure.repository.jpa.entity.nomenclature;

import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;

import javax.persistence.Entity;

@Data
@EqualsAndHashCode
@ToString
@Entity(name = "N_ACTIVITY")
public class ActivityEntity extends NomenclatureEntity {
}

存储库

package com.package.company.infrastructure.repository.jpa;

import com.package.company.infrastructure.repository.jpa.entity.nomenclature.NomenclatureEntity;
import org.springframework.data.repository.CrudRepository;
import org.springframework.stereotype.Repository;

@Repository
public interface NomenclatureSpringDataRepository extends CrudRepository<NomenclatureEntity, Long> {
}

Spring数据实现

package com.package.company.infrastructure.repository.jpa;

import com.package.company.core.NomenclatureRepository;
import com.package.company.core.model.nomenclature.*;
import com.package.company.infrastructure.repository.jpa.entity.nomenclature.*;
import com.package.company.infrastructure.repository.jpa.mapping.nomenclature.*;
import org.mapstruct.factory.Mappers;
import org.springframework.transaction.annotation.Transactional;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;
import java.util.List;
import java.util.stream.Collectors;

@Transactional(readOnly = true)
public class NomenclatureRepositorySpringDataWrapper implements NomenclatureRepository {

    NomenclatureSpringDataRepository nomenclatureSpringDataRepository;

    @PersistenceContext
    private EntityManager entityManager;

    public NomenclatureRepositorySpringDataWrapper(NomenclatureSpringDataRepository nomenclatureSpringDataRepository) {
        this.nomenclatureSpringDataRepository = nomenclatureSpringDataRepository;
    }

    @Override
    public List<Activity> getAllActivity() {
        Query query = entityManager.createQuery("SELECT a FROM ActivityEntity a");
        List<ActivityEntity> activityEntities = query.getResultList();
        ActivityEntityMapper mapper = Mappers.getMapper(ActivityEntityMapper.class);
        List<Activity> activities = activityEntities.stream().map(ae->mapper.toNomenclature(ae)).collect(Collectors.toList());
        return activities;
    }
}

开始class

package com.package;

import com.package.core.NomenclatureRepository;
import com.package.core.model.nomenclature.*;
import com.package.infrastructure.config.CompanyApplicationConfig;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.actuate.autoconfigure.security.servlet.ManagementWebSecurityAutoConfiguration;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Import;

@SpringBootApplication(exclude={SecurityAutoConfiguration.class, ManagementWebSecurityAutoConfiguration.class})
@Import(value = MyApplicationConfig.class)
public class MyApplication {

    @Autowired
    private NomenclatureRepository nomenclatureRepository;

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

    @Bean
    public CommandLineRunner init(){
        return (String... args)->{
            nomenclatureRepository.saveActivity(new Activity(1L, "Activity 1"));
            nomenclatureRepository.saveActivity(new Activity(2L, "Activity 2"));
        };
    }
}

结果

2021-07-01 10:29:08.118 ERROR 9224 --- [nio-8080-exec-1] o.a.c.c.C.[.[.[/].[dispatcherServlet]    : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is java.lang.IllegalArgumentException: org.hibernate.hql.internal.ast.QuerySyntaxException: ActivityEntity is not mapped [SELECT a FROM ActivityEntity a]] with root cause

org.hibernate.hql.internal.ast.QuerySyntaxException: ActivityEntity is not mapped
    at org.hibernate.hql.internal.ast.util.SessionFactoryHelper.requireClassPersister(SessionFactoryHelper.java:169) ~[hibernate-core-5.4.12.Final.jar:5.4.12.Final]
    at org.hibernate.hql.internal.ast.tree.FromElementFactory.addFromElement(FromElementFactory.java:91) ~[hibernate-core-5.4.12.Final.jar:5.4.12.Final]

您已经使用了@Entity(name = "N_ACTIVITY")到classActivityEntity@Entity 中的 name 用于 JPA-QL 查询,如果未提供值,则默认为 class 名称,但由于您更改了它,因此您必须确保在构建查询时使用此名称。

所以您的查询应该更新如下:

SELECT a FROM N_ACTIVITY a

或者您可以删除名称并使用 class 名称 ActivityEntity

正如@deepakchethan所说,实体名称是用于JPA-QL查询的,而您将其更改为N_ACTIVITY,因此您应该使用:

Query query = entityManager.createQuery("SELECT a FROM N_ACTIVITY a");

另一种方法是使用@Entity定义实体,使用@Table更改默认的table名称:

@Entity
@Table(name = "N_ACTIVITY")
public class ActivityEntity extends NomenclatureEntity {
}