【问题标题】:Hibernate table not mapped error in query查询中的休眠表未映射错误
【发布时间】:2021-09-24 03:37:42
【问题描述】:

我知道这个问题反复出现,但我还没有找到解决方案。我的带有 Hibernate 的 Web 应用程序在查询中返回此错误:

org.springframework.web.util.NestedServletException: Request processing failed; nested exception is java.lang.IllegalArgumentException: org.hibernate.hql.internal.ast.QuerySyntaxException: Prodotti is not mapped [SELECT p FROM Prodotti p]

这是我的 pom 配置:

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-jdbc</artifactId>
    <version>${springframework.version}</version>
</dependency>
<dependency>
    <groupId>org.springframework.data</groupId>
    <artifactId>spring-data-jpa</artifactId>
    <version>2.5.0</version>
</dependency>
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-orm</artifactId>
    <version>${springframework.version}</version>
</dependency>
<dependency>
    <groupId>org.hibernate</groupId>
    <artifactId>hibernate-entitymanager</artifactId>
    <version>5.4.30.Final</version>
</dependency>
<dependency>
    <groupId>org.hibernate.javax.persistence</groupId>
    <artifactId>hibernate-jpa-2.1-api</artifactId>
    <version>1.0.2.Final</version>
</dependency>
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>8.0.25</version>
</dependency>

这是我的配置类:

package it.prova.web.config;

import javax.sql.DataSource;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.core.env.Environment;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.orm.jpa.vendor.Database;
import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer;
import org.springframework.web.servlet.view.freemarker.FreeMarkerViewResolver;

import it.prova.web.dao.ProdottoService;
import it.prova.web.dao.ProdottoServiceImpl;

@EnableWebMvc
@Configuration
@ComponentScan(basePackages = "it.prova.web.controller")
@PropertySource("classpath:my-catalogue.properties")
@EnableTransactionManagement
public class MyCatalogueConfig {
    @Autowired
    private Environment env;
    
    @Bean
    public FreeMarkerViewResolver getFreeMarkerResolver() {
        FreeMarkerViewResolver resolver = new FreeMarkerViewResolver();
        resolver.setPrefix("");
        resolver.setSuffix(".ftl");
        
        return resolver;
    }
    
    @Bean
    public FreeMarkerConfigurer getFreeMarkerConfigurer() {
        FreeMarkerConfigurer config = new FreeMarkerConfigurer();
        config.setTemplateLoaderPath("/WEB-INF/view/");
        
        return config;
    }
    
    @Bean
    public DataSource getDataSource() {
        DriverManagerDataSource ds = new DriverManagerDataSource();
        ds.setDriverClassName(env.getRequiredProperty("my-catalogue.db.driver"));
        ds.setUrl(env.getRequiredProperty("my-catalogue.db.url"));
        ds.setUsername(env.getRequiredProperty("my-catalogue.db.username"));
        ds.setPassword(env.getRequiredProperty("my-catalogue.db.password"));
        
        return ds;
    }
    
    @Bean
    public LocalContainerEntityManagerFactoryBean getEntityManagerFactory() {
        HibernateJpaVendorAdapter adapter = new HibernateJpaVendorAdapter();
        adapter.setDatabase(Database.MYSQL);
        adapter.setGenerateDdl(true);

        LocalContainerEntityManagerFactoryBean bean = new LocalContainerEntityManagerFactoryBean();
        bean.setDataSource(getDataSource());
        bean.setJpaVendorAdapter(adapter);
        bean.setPackagesToScan(getClass().getPackage().getName());
        
        return bean;
    }
    
    @Bean
    public PlatformTransactionManager getTransactionManager() {
        return new JpaTransactionManager(getEntityManagerFactory().getObject());
    }
    
    @Bean
    public ProdottoService getProdottoService() {
        return new ProdottoServiceImpl();
    }
}

这是我的控制器:

package it.prova.web.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.ModelAndView;

import it.prova.web.dao.ProdottoService;
import it.prova.web.model.Prodotto;

@Controller
@RequestMapping("/")
public class ProdottoController {
    @Autowired
    private ProdottoService service;
    
    @GetMapping("/")
    public ModelAndView index() {
        
        return new ModelAndView("index", "listaProdotti", service.getAll());
    }
    
    @PostMapping("/add")
    public String add(@ModelAttribute("datiProdotto") Prodotto p) {
        
        service.add(p);
        
        return "redirect:/";
    }
    
    @PostMapping("/update")
    public String update(@ModelAttribute("datiProdotto") Prodotto p) {
        service.update(p);
        
        return "redirect:/";
    }
    
    @GetMapping("/delete")
    public String delete(@RequestParam("id") String idProdotto) {
        if(idProdotto != null)
            service.delete(Integer.parseInt(idProdotto));
        
        return "redirect:/";
    }
}

这是我的服务实现(避免接口...):

package it.prova.web.dao;

import java.util.List;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;
import javax.transaction.Transactional;

import it.prova.web.model.Prodotto;

public class ProdottoServiceImpl implements ProdottoService {
    @PersistenceContext
    private EntityManager em;
    
    @Override
    @Transactional
    public void add(Prodotto p) {
        em.persist(p);
    }

    @Override
    @Transactional
    public void update(Prodotto p) {
        em.merge(p);
    }

    @Override
    @Transactional
    public void delete(int id) {
        em.remove(getById(id));
    }

    @Override
    public Prodotto getById(int id) {
        return em.find(Prodotto.class, id);
    }

    @Override
    public List<Prodotto> getAll() {
        Query q = em.createQuery("SELECT p FROM Prodotto p");
        return q.getResultList();
    }

}

最后是模型:

package it.prova.web.model;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;

@Entity
@Table(name = "prodotti")
public class Prodotto {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer id;
    
    @Column(name = "descrizione")
    private String descrizione;
    
    @Column(name = "prezzo")
    private Integer prezzo;
    
    public Integer getId() {
        return id;
    }
    public void setId(Integer id) {
        this.id = id;
    }
    public String getDescrizione() {
        return descrizione;
    }
    public void setDescrizione(String descrizione) {
        this.descrizione = descrizione;
    }
    public Integer getPrezzo() {
        return prezzo;
    }
    public void setPrezzo(Integer prezzo) {
        this.prezzo = prezzo;
    }
    public Prodotto(String descrizione, Integer prezzo) {
        super();
        this.descrizione = descrizione;
        this.prezzo = prezzo;
    }
    public Prodotto() {
        super();
    }
    
}

我不明白:Prodotto 已映射...请帮助我。

【问题讨论】:

  • 你能在数据库中检查你的表名吗?你如何创建你的表?另一个问题:为什么你的实体被命名为Prodotto 而你的表被命名为prodotti
  • 表的名称是“prodotti”,但我没有理由给出除类以外的名称。这很奇怪。新手问题:它们必须是同名的类和表吗?
  • 不,他们没有,你可以有不同的名字。您如何创建表格?
  • 我看到你的依赖中有spring-data-jpa,你为什么要使用EntityManager来查询你的数据库。 Spring Data 的主要目标是避免这种情况。
  • 好的。新手问题:我可以使用存储库吗?

标签: hibernate spring-mvc


【解决方案1】:

阅读您的配置后,您的 EntityManager 配置错误。你有这个:

    @Bean
    public LocalContainerEntityManagerFactoryBean getEntityManagerFactory() {
        HibernateJpaVendorAdapter adapter = new HibernateJpaVendorAdapter();
        adapter.setDatabase(Database.MYSQL);
        adapter.setGenerateDdl(true);

        LocalContainerEntityManagerFactoryBean bean = new LocalContainerEntityManagerFactoryBean();
        bean.setDataSource(getDataSource());
        bean.setJpaVendorAdapter(adapter);
        bean.setPackagesToScan(getClass().getPackage().getName()); // This line scan the package of your configuration class not the package containing your entities
        
        return bean;
    }

你应该有类似的东西:

    @Bean
    public LocalContainerEntityManagerFactoryBean getEntityManagerFactory() {
        HibernateJpaVendorAdapter adapter = new HibernateJpaVendorAdapter();
        adapter.setDatabase(Database.MYSQL);
        adapter.setGenerateDdl(true);

        LocalContainerEntityManagerFactoryBean bean = new LocalContainerEntityManagerFactoryBean();
        bean.setDataSource(getDataSource());
        bean.setJpaVendorAdapter(adapter);
        bean.setPackagesToScan(Prodotto.class.getPackageName);
        
        return bean;
    }

此外,您的配置还可以改进。

【讨论】:

  • 欢迎您。你不是唯一一个需要学习的人,任何开发人员都需要学习很多东西,这是我们工作中有趣的部分。
【解决方案2】:

此外,如果您的数据库中有多个表,那么也可能是由于其中的映射不正确(OnetoMany 和 ManyToOne ...)。你也可以检查一下。

【讨论】:

  • 您的答案可以通过额外的支持信息得到改进。请edit 添加更多详细信息,例如引用或文档,以便其他人可以确认您的答案是正确的。你可以找到更多关于如何写好答案的信息in the help center
猜你喜欢
  • 2013-01-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-02-05
  • 1970-01-01
相关资源
最近更新 更多