SQLGrammerException:无法在 em.persist() 上获取 ResultSet

SQLGrammerException: could not get ResultSet on em.persist()

我正在学习 JPA 并且想要在我的 table 上使用 JPA 创建一个新条目,级联子元素。

在我想要保留一个新条目之前,代码工作正常。我最初认为这是一个映射错误,但我没有发现我的数据库结构有任何问题(或者我产生了幻觉 bc of the heat)

那我为什么不能坚持呢?

客户端

package client;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

import dao.GeneralDAO;
import entity.Artemis;
import entity.Welt;

public class client {

    public static void main(String[] args) {

        GeneralDAO artemis = new GeneralDAO("JPA_REAL", Artemis.class);
        System.out.println(artemis);
        GeneralDAO welt = new GeneralDAO("JPA_REAL", Welt.class);
        System.out.println(welt);

        System.out.println("Artemis Liste: " + artemis.list());
        System.out.println("Artems by PK: " + artemis.findByPrimaryKey(1));
        System.out.println("Welt by PK: " + welt.findByPrimaryKey(2));
        System.out.println("Welt Liste: " + welt.list());

        Collection<?> objs;
        Collection<?> objs1;

        objs = artemis.list();
        objs1 = welt.list();

        Artemis art1 = null;

        System.out.println("Field: " + artemis.getField());


  Artemis a2 = new Artemis("Zeus");

          Artemis a3 = new Artemis();

          a3.setName("Jupiter");

          List<Welt> a2_welt = new ArrayList<Welt>();

          a2_welt.add(new Welt("Earth"));

          a2_welt.add(new Welt("Mars"));

          a2.setWelts(a2_welt);

          artemis.store(a2);





        for (Object s : objs) {
            System.out.println("s=" + ((Artemis) s).getName());
            System.out.println("id=" + ((Artemis) s).getId());
            for (Welt w : ((Artemis) s).getWelts())
                System.out.println("w=" + w.getName());
        }

        artemis.close();
        welt.close();
    }
}

DAO

package dao;

import java.lang.reflect.Field;
import java.util.Collection;

import javax.persistence.*;



public class GeneralDAO {

    EntityManager em;
    private Field[] field;
    private int primaryKeyIndex;



    private Class <?> clazz;

    public GeneralDAO(String PersistenceUnit, Class <?> clazz) {
    EntityManagerFactory emf = Persistence.createEntityManagerFactory(PersistenceUnit);
    em = emf.createEntityManager();
    this.clazz=clazz;   
    }


    public Field[] getField() {
        field = clazz.getDeclaredFields();

        return field;
    }

    public Collection <?> list(){
        String Statement = "Select q from " + clazz.getSimpleName() + " q";
        return em.createQuery(Statement).getResultList();
    }

    public Object findByPrimaryKey(int pk) {
        Object returnObject = em.find(clazz, pk);
        return returnObject;
    }

    public void store(Object s) {
        EntityTransaction ta = em.getTransaction();
        ta.begin();
        em.persist(s);
        ta.commit();

    }

    public void remove(int pk) {
        Object returnObject = em.find(clazz, pk);
        EntityTransaction ta = em.getTransaction();
        ta.begin();
        em.remove(returnObject);
        ta.commit();
    }

    public void close() {
        em.clear();
        em.close();


    }

    public void refresh(Object s) {
        em.refresh(s);
    }
    /*
     * public Collection <?> executeQuery() { System.out.println("Query Start");
     * Query Query = em.createQuery("Select e from Artemis e join e.id t");
     * List<Artemis> resultList = Query.getResultList(); for (Artemis s: resultList)
     * System.out.println(Artemis.getName() "+" Artemis.getWorld()); }
     */

}

贴边实体

package entity;

import java.io.Serializable;
import javax.persistence.*;


/**
 * The persistent class for the WELT database table.
 * 
 */
@Entity
@NamedQuery(name="Welt.findAll", query="SELECT w FROM Welt w")
public class Welt implements Serializable {
    private static final long serialVersionUID = 1L;

    @Id
    @GeneratedValue
    @Column(name="id")
    int id;

    @Column(name="name")
    private String name;

    //bi-directional many-to-one association to Artemis
    @ManyToOne(fetch=FetchType.LAZY)
    @JoinColumn(name="fk_artemis")
    private Artemis artemis;

    public Welt() {

    }

    public Welt(int i, String string, int j) {

    }

    public Welt(int i, String string) {
    }

    public Welt(String string) {
    }

    public long getId() {
        return this.id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return this.name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Artemis getArtemis() {
        return this.artemis;
    }

    public void setArtemis(Artemis artemis) {
        this.artemis = artemis;
    }

}

阿尔忒弥斯实体

package entity;

import java.io.Serializable;
import javax.persistence.*;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;


/**
 * The persistent class for the ARTEMIS database table.
 * 
 */
@Entity
@NamedQuery(name="Artemis.findAll", query="SELECT a FROM Artemis a")
public class Artemis implements Serializable {
    private static final long serialVersionUID = 1L;

    @Id
    @GeneratedValue
    @Column(name="id")
    private int id;

    @Column(name="name")
    private String name;

    //bi-directional many-to-one association to Welt
    @OneToMany(mappedBy="artemis", fetch=FetchType.LAZY, cascade=CascadeType.PERSIST)
    private List<Welt> welts = new ArrayList<Welt>();

    public Artemis() {
    }

    public Artemis(int id, String name) {
        this.id=id;
        this.name=name;
    }

    public Artemis(String name) {
        this.name=name;
    }

    public long getId() {
        return this.id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return this.name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public List<Welt> getWelts() {
        return welts;
    }

    public Collection<Welt> getWeltName() {
        return welts;
    }

    public void setWelts(List<Welt> welts) {
        this.welts = welts;
    }

    public Welt addWelt(Welt welt) {
        getWelts().add(welt);
        welt.setArtemis(this);

        return welt;
    }

    public Welt removeWelt(Welt welt) {
        getWelts().remove(welt);
        welt.setArtemis(null);

        return welt;
    }

    @Override
    public String toString() {
        return "Artemis [id=" + id + ", name=" + name + ", welts=" + welts + "]";
    }


}

堆栈跟踪

//other console output
    dao.GeneralDAO@77c1e611
    Artemis Liste: []
    Artems by PK: null
    Welt by PK: null
    Welt Liste: []
    Field: [Ljava.lang.reflect.Field;@17fede14
    Juni 27, 2019 9:06:16 NACHM. org.hibernate.engine.jdbc.spi.SqlExceptionHelper logExceptions
    WARN: SQL Error: 2289, SQLState: 42000
    Juni 27, 2019 9:06:16 NACHM. org.hibernate.engine.jdbc.spi.SqlExceptionHelper logExceptions
    ERROR: ORA-02289: sequence does not exist

    Exception in thread "main" javax.persistence.PersistenceException: org.hibernate.exception.SQLGrammarException: could not extract ResultSet
        at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:154)
        at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:181)
        at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:188)
        at org.hibernate.internal.SessionImpl.firePersist(SessionImpl.java:811)
        at org.hibernate.internal.SessionImpl.persist(SessionImpl.java:789)
        at dao.GeneralDAO.store(GeneralDAO.java:46)
        at client.client.main(client.java:77)
    Caused by: org.hibernate.exception.SQLGrammarException: could not extract ResultSet
        at org.hibernate.exception.internal.SQLExceptionTypeDelegate.convert(SQLExceptionTypeDelegate.java:63)
        at org.hibernate.exception.internal.StandardSQLExceptionConverter.convert(StandardSQLExceptionConverter.java:42)
        at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:113)
        at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:99)
        at org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.extract(ResultSetReturnImpl.java:69)
        at org.hibernate.id.enhanced.SequenceStructure.getNextValue(SequenceStructure.java:95)
        at org.hibernate.id.enhanced.NoopOptimizer.generate(NoopOptimizer.java:40)
        at org.hibernate.id.enhanced.SequenceStyleGenerator.generate(SequenceStyleGenerator.java:519)
        at org.hibernate.event.internal.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:119)
        at org.hibernate.event.internal.DefaultPersistEventListener.entityIsTransient(DefaultPersistEventListener.java:192)
        at org.hibernate.event.internal.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:135)
        at org.hibernate.event.internal.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:62)
        at org.hibernate.internal.SessionImpl.firePersist(SessionImpl.java:804)
        ... 3 more
    Caused by: java.sql.SQLSyntaxErrorException: ORA-02289: sequence does not exist

        at oracle.jdbc.driver.T4CTTIoer11.processError(T4CTTIoer11.java:494)
        at oracle.jdbc.driver.T4CTTIoer11.processError(T4CTTIoer11.java:446)
        at oracle.jdbc.driver.T4C8Oall.processError(T4C8Oall.java:1052)
        at oracle.jdbc.driver.T4CTTIfun.receive(T4CTTIfun.java:537)
        at oracle.jdbc.driver.T4CTTIfun.doRPC(T4CTTIfun.java:255)
        at oracle.jdbc.driver.T4C8Oall.doOALL(T4C8Oall.java:610)
        at oracle.jdbc.driver.T4CPreparedStatement.doOall8(T4CPreparedStatement.java:253)
        at oracle.jdbc.driver.T4CPreparedStatement.doOall8(T4CPreparedStatement.java:86)
        at oracle.jdbc.driver.T4CPreparedStatement.executeForDescribe(T4CPreparedStatement.java:765)
        at oracle.jdbc.driver.OracleStatement.executeMaybeDescribe(OracleStatement.java:921)
        at oracle.jdbc.driver.OracleStatement.doExecuteWithTimeout(OracleStatement.java:1099)
        at oracle.jdbc.driver.OraclePreparedStatement.executeInternal(OraclePreparedStatement.java:3640)
        at oracle.jdbc.driver.T4CPreparedStatement.executeInternal(T4CPreparedStatement.java:1384)
        at oracle.jdbc.driver.OraclePreparedStatement.executeQuery(OraclePreparedStatement.java:3687)
        at oracle.jdbc.driver.OraclePreparedStatementWrapper.executeQuery(OraclePreparedStatementWrapper.java:1165)
        at org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.extract(ResultSetReturnImpl.java:60)
        ... 11 more
    Caused by: Error : 2289, Position : 7, Sql = select hibernate_sequence.nextval from dual, OriginalSql = select hibernate_sequence.nextval from dual, Error Msg = ORA-02289: sequence does not exist

        at oracle.jdbc.driver.T4CTTIoer11.processError(T4CTTIoer11.java:498)
        ... 26 more

@JoinColumn 注释指定用作目标实体外键的列的名称。

在上面的 Welt class 上,连接列的名称设置为 "fk_artemis"。

@ManyToOne(fetch=FetchType.LAZY)
@JoinColumn(name="fk_artemis")
private Artemis artemis;

因此,如果产品 table 上的外键被命名为不同于 class 中给出的其他名称,则通常会出现此错误,在这种情况下:"fk_artemis".

您需要更改 table 中的列名称或您在 @JoinColumn 中使用的名称,以便它们匹配。

导致此错误的原因较多。但是,主要是由于名称不匹配。

失败的原因是我的数据库没有在@Generated Value

中使用的序列

Sidenote: If I would drop @GeneratedValue and make entries with primary keys (1,"Whatever") it would work.

@GeneratedValue 在 Oracle 中按标准使用 SEQUENCE,但我没有生成一个。我为每个 table 制作了两个带有 create sequence ... 的序列,并使用类型、序列名称修改了 @GeneratedValue 并添加了 @SequenceGenerator.

我不得不删除 drop sequence dual 的序列,并且自动生成键、持久键和外键起作用。