【问题标题】:Mapping objects in database映射数据库中的对象
【发布时间】:2022-12-10 10:27:46
【问题描述】:

我正在尝试学习休眠并完成我试图实现 OneToOne 映射的教程。我有一个问题和一个答案类/实体。我已经映射了一个问题的答案,下面是源代码。

问题.java

package com.map;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.OneToOne;

@Entity
public class Question {

    @Id
    @Column(name="question_id")
    private int questionId;
    private String question;
    @OneToOne
    private Answer answer;
    
    public int getQuestionId() {
        return questionId;
    }
    public void setQuestionId(int questionId) {
        this.questionId = questionId;
    }
    public String getQuestion() {
        return question;
    }
    public void setQuestion(String question) {
        this.question = question;
    }
    public Answer getAnswer() {
        return answer;
    }
    public void setAnswer(Answer answer) {
        this.answer = answer;
    }
    public Question(int questionId, String question, Answer answer) {
        super();
        this.questionId = questionId;
        this.question = question;
        this.answer = answer;
    }
    public Question() {
        super();
        // TODO Auto-generated constructor stub
    }
    @Override
    public String toString() {
        return "Question [questionId=" + questionId + ", question=" + question + ", answer=" + answer + "]";
    }
    
    
    
}

答案.java

package com.map;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;

@Entity
public class Answer {

    @Id
    @Column(name="answer_id")
    private int answerId;
    private String answer;
    public int getAnswerId() {
        return answerId;
    }
    public void setAnswerId(int answerId) {
        this.answerId = answerId;
    }
    public String getAnswer() {
        return answer;
    }
    public void setAnswer(String answer) {
        this.answer = answer;
    }
    public Answer() {
        super();
        // TODO Auto-generated constructor stub
    }
    public Answer(int answerId, String answer) {
        super();
        this.answerId = answerId;
        this.answer = answer;
    }
    @Override
    public String toString() {
        return "Answer [answerId=" + answerId + ", answer=" + answer + "]";
    }
    
    
}

下面是运行程序的 MapDemo 类。

package com.map;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;

public class MapDemo {
    public static void main(String[] args) {
        Configuration cfg = new Configuration();
        cfg.configure("hibernate.cfg.xml");
        SessionFactory factory = cfg.buildSessionFactory();
        
        Question q1 = new Question();
        q1.setQuestionId(1212);
        q1.setQuestion("What is Java");
        Answer answer = new Answer();
        answer.setAnswerId(343);
        answer.setAnswer("Java is programming laguage");
        q1.setAnswer(answer);
        
        Session s = factory.openSession();
        Transaction t = s.beginTransaction();
        s.save(q1);
        t.commit();
        s.close(); 
        
        
        factory.close();
    }
}

休眠-cfg.xml

<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE hibernate-configuration PUBLIC 
    "-//Hibernate/Hibernate Configuration DTD//EN"
    "http://hibernate.sourceforge.net/hibernate-configuration.dtd">
    <hibernate-configuration>
        <session-factory>
            <property name="connection.driver_class">oracle.jdbc.driver.OracleDriver</property>
            <property name="connection.url">jdbc:oracle:thin:@localhost:1521:xe</property>
            <property name="connection.username">system</property>
            <property name="connection.password">system</property>
            <property name="hbm2ddl.auto">create</property>
            <property name="show_sql">true</property>
            <mapping class="com.tut.Student"></mapping>
            <mapping class="com.tut.Address"></mapping>     
            <mapping class="com.map.Question"></mapping>
            <mapping class="com.map.Answer"></mapping>      
        </session-factory>
    </hibernate-configuration>

当我尝试运行该程序时,我在日志中看到的错误是外键在引用 Answer 的 Question 实体中被违反,但在尝试保留它之前,我在 Question 类对象中设置了 Answer 对象。休眠是否理解它首先需要在答案表中创建条目然后在问题表中引用它?我不确定它是如何工作的,我收到了这个错误,但在教程中讲师没有。他用的是 MySQL,我用的是 Oracle 数据库。请指教。

异常日志:

Dec 09, 2022 4:50:48 PM org.hibernate.Version logVersion
INFO: HHH000412: Hibernate ORM core version 5.6.10.Final
Dec 09, 2022 4:50:48 PM org.hibernate.boot.jaxb.internal.stax.LocalXmlResourceResolver resolveEntity
WARN: HHH90000012: Recognized obsolete hibernate namespace http://hibernate.sourceforge.net/hibernate-configuration. Use namespace http://www.hibernate.org/dtd/hibernate-configuration instead.  Support for obsolete DTD/XSD namespaces may be removed at any time.
Dec 09, 2022 4:50:48 PM org.hibernate.annotations.common.reflection.java.JavaReflectionManager <clinit>
INFO: HCANN000001: Hibernate Commons Annotations {5.1.2.Final}
Dec 09, 2022 4:50:48 PM org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl configure
WARN: HHH10001002: Using Hibernate built-in connection pool (not for production use!)
Dec 09, 2022 4:50:48 PM org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl buildCreator
INFO: HHH10001005: using driver [oracle.jdbc.driver.OracleDriver] at URL [jdbc:oracle:thin:@localhost:1521:xe]
Dec 09, 2022 4:50:48 PM org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl buildCreator
INFO: HHH10001001: Connection properties: {password=****, user=system}
Dec 09, 2022 4:50:48 PM org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl buildCreator
INFO: HHH10001003: Autocommit mode: false
Dec 09, 2022 4:50:48 PM org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl$PooledConnections <init>
INFO: HHH000115: Hibernate connection pool size: 20 (min=1)
Dec 09, 2022 4:50:49 PM org.hibernate.dialect.Dialect <init>
INFO: HHH000400: Using dialect: org.hibernate.dialect.Oracle12cDialect
Hibernate: drop table Answer cascade constraints
Dec 09, 2022 4:50:49 PM org.hibernate.resource.transaction.backend.jdbc.internal.DdlTransactionIsolatorNonJtaImpl getIsolatedConnection
INFO: HHH10001501: Connection obtained from JdbcConnectionAccess [org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator$ConnectionProviderJdbcConnectionAccess@74b86971] for (non-JTA) DDL execution was not in auto-commit mode; the Connection 'local transaction' will be committed and the Connection will be set into auto-commit mode.
Hibernate: drop table Question cascade constraints
Hibernate: drop table Student cascade constraints
Hibernate: drop table student_address cascade constraints
Hibernate: create table Answer (answer_id number(10,0) not null, answer varchar2(255 char), primary key (answer_id))
Dec 09, 2022 4:50:49 PM org.hibernate.resource.transaction.backend.jdbc.internal.DdlTransactionIsolatorNonJtaImpl getIsolatedConnection
INFO: HHH10001501: Connection obtained from JdbcConnectionAccess [org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator$ConnectionProviderJdbcConnectionAccess@7a1b8a46] for (non-JTA) DDL execution was not in auto-commit mode; the Connection 'local transaction' will be committed and the Connection will be set into auto-commit mode.
Hibernate: create table Question (question_id number(10,0) not null, question varchar2(255 char), answer_answer_id number(10,0), primary key (question_id))
Hibernate: create table Student (id number(10,0) not null, course varchar2(255 char), duration varchar2(255 char), city varchar2(255 char), name varchar2(255 char), primary key (id))
Hibernate: create table student_address (address_id number(10,0) generated as identity, addedDate date, CITY varchar2(100 char), image blob, IS_OPEN number(1,0), STREET varchar2(50 char), primary key (address_id))
Hibernate: alter table Question add constraint FKs6ghcwuovtcp489oo5dy7rvk5 foreign key (answer_answer_id) references Answer
Dec 09, 2022 4:50:49 PM org.hibernate.engine.transaction.jta.platform.internal.JtaPlatformInitiator initiateService
INFO: HHH000490: Using JtaPlatform implementation: [org.hibernate.engine.transaction.jta.platform.internal.NoJtaPlatform]
Hibernate: select answer_.answer_id, answer_.answer as answer2_0_ from Answer answer_ where answer_.answer_id=?
Hibernate: insert into Question (answer_answer_id, question, question_id) values (?, ?, ?)
Hibernate: update Question set answer_answer_id=?, question=? where question_id=?
Dec 09, 2022 4:50:49 PM org.hibernate.engine.jdbc.spi.SqlExceptionHelper logExceptions
WARN: SQL Error: 2291, SQLState: 23000
Dec 09, 2022 4:50:49 PM org.hibernate.engine.jdbc.spi.SqlExceptionHelper logExceptions
ERROR: ORA-02291: integrity constraint (SYSTEM.FKS6GHCWUOVTCP489OO5DY7RVK5) violated - parent key not found

Dec 09, 2022 4:50:49 PM org.hibernate.engine.jdbc.batch.internal.AbstractBatchImpl release
INFO: HHH000010: On release of batch it still contained JDBC statements
Exception in thread "main" javax.persistence.PersistenceException: org.hibernate.exception.ConstraintViolationException: could not execute statement
    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.doFlush(SessionImpl.java:1411)
    at org.hibernate.internal.SessionImpl.managedFlush(SessionImpl.java:489)
    at org.hibernate.internal.SessionImpl.flushBeforeTransactionCompletion(SessionImpl.java:3290)
    at org.hibernate.internal.SessionImpl.beforeTransactionCompletion(SessionImpl.java:2425)
    at org.hibernate.engine.jdbc.internal.JdbcCoordinatorImpl.beforeTransactionCompletion(JdbcCoordinatorImpl.java:449)
    at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl.beforeCompletionCallback(JdbcResourceLocalTransactionCoordinatorImpl.java:183)
    at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl.access$300(JdbcResourceLocalTransactionCoordinatorImpl.java:40)
    at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl$TransactionDriverControlImpl.commit(JdbcResourceLocalTransactionCoordinatorImpl.java:281)
    at org.hibernate.engine.transaction.internal.TransactionImpl.commit(TransactionImpl.java:101)
    at com.map.MapDemo.main(MapDemo.java:25)
Caused by: org.hibernate.exception.ConstraintViolationException: could not execute statement
    at org.hibernate.exception.internal.SQLExceptionTypeDelegate.convert(SQLExceptionTypeDelegate.java:59)
    at org.hibernate.exception.internal.StandardSQLExceptionConverter.convert(StandardSQLExceptionConverter.java:37)
    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.executeUpdate(ResultSetReturnImpl.java:200)
    at org.hibernate.engine.jdbc.batch.internal.NonBatchingBatch.addToBatch(NonBatchingBatch.java:46)
    at org.hibernate.persister.entity.AbstractEntityPersister.update(AbstractEntityPersister.java:3571)
    at org.hibernate.persister.entity.AbstractEntityPersister.updateOrInsert(AbstractEntityPersister.java:3438)
    at org.hibernate.persister.entity.AbstractEntityPersister.update(AbstractEntityPersister.java:3852)
    at org.hibernate.action.internal.EntityUpdateAction.execute(EntityUpdateAction.java:202)
    at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:604)
    at org.hibernate.engine.spi.ActionQueue.lambda$executeActions$1(ActionQueue.java:478)
    at java.base/java.util.LinkedHashMap.forEach(LinkedHashMap.java:723)
    at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:475)
    at org.hibernate.event.internal.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:344)
    at org.hibernate.event.internal.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:40)
    at org.hibernate.event.service.internal.EventListenerGroupImpl.fireEventOnEachListener(EventListenerGroupImpl.java:107)
    at org.hibernate.internal.SessionImpl.doFlush(SessionImpl.java:1407)
    ... 9 more
Caused by: java.sql.SQLIntegrityConstraintViolationException: ORA-02291: integrity constraint (SYSTEM.FKS6GHCWUOVTCP489OO5DY7RVK5) violated - parent key not found

    at oracle.jdbc.driver.T4CTTIoer11.processError(T4CTTIoer11.java:629)
    at oracle.jdbc.driver.T4CTTIoer11.processError(T4CTTIoer11.java:563)
    at oracle.jdbc.driver.T4C8Oall.processError(T4C8Oall.java:1150)
    at oracle.jdbc.driver.T4CTTIfun.receive(T4CTTIfun.java:770)
    at oracle.jdbc.driver.T4CTTIfun.doRPC(T4CTTIfun.java:298)
    at oracle.jdbc.driver.T4C8Oall.doOALL(T4C8Oall.java:497)
    at oracle.jdbc.driver.T4CPreparedStatement.doOall8(T4CPreparedStatement.java:151)
    at oracle.jdbc.driver.T4CPreparedStatement.executeForRows(T4CPreparedStatement.java:1051)
    at oracle.jdbc.driver.OracleStatement.executeSQLStatement(OracleStatement.java:1530)
    at oracle.jdbc.driver.OracleStatement.doExecuteWithTimeout(OracleStatement.java:1310)
    at oracle.jdbc.driver.OraclePreparedStatement.executeInternal(OraclePreparedStatement.java:3745)
    at oracle.jdbc.driver.OraclePreparedStatement.executeLargeUpdate(OraclePreparedStatement.java:3917)
    at oracle.jdbc.driver.OraclePreparedStatement.executeUpdate(OraclePreparedStatement.java:3896)
    at oracle.jdbc.driver.OraclePreparedStatementWrapper.executeUpdate(OraclePreparedStatementWrapper.java:991)
    at org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.executeUpdate(ResultSetReturnImpl.java:197)
    ... 22 more
Caused by: Error : 2291, Position : 0, Sql = update Question set answer_answer_id=:1 , question=:2  where question_id=:3 , OriginalSql = update Question set answer_answer_id=?, question=? where question_id=?, Error Msg = ORA-02291: integrity constraint (SYSTEM.FKS6GHCWUOVTCP489OO5DY7RVK5) violated - parent key not found

    at oracle.jdbc.driver.T4CTTIoer11.processError(T4CTTIoer11.java:636)
    ... 36 more

【问题讨论】:

  • 尝试先保存答案或将级联添加到关系中,例如@OneToOne(cascade = CascadeType.ALL)
  • 它有效,但你能解释一下为什么需要 Cascade 吗?另外,为什么我会遇到这种情况,而不是视频中的讲师。

标签: java spring oracle hibernate jpa


【解决方案1】:

您创建和配置实体的方式,Question 具有指向Answer 的外键。这很好。抛出的异常是因为您要求 JPA 保存一个问题,其中包含对尚未保存的答案的 FK。我必须承认错误消息和日志有点混乱,但这应该是原因。

一种解决方案是手动保存问题之前的答案。另一种解决方案是对 JPS 一对一关系使用 cascade 指令,这样JPA会为你保存问题前的答案.这些中的任何一个都应该工作:

@OneToOne(cascade = CascadeType.ALL) // cascade all operations
// -OR-
@OneToOne(cascade = CascadeType.PERSIST) // cascade the persist operation only
// -OR you can even specify many types
@OneToOne(cascade = {CascadeType.PERSIST,CascadeType.DELETE})

我没有看过视频,但我敢肯定,如果您检查细节,就会有细微的差别。

【讨论】:

    猜你喜欢
    • 2012-07-18
    • 1970-01-01
    • 1970-01-01
    • 2011-10-22
    • 2013-02-14
    • 1970-01-01
    • 2019-07-27
    • 2017-07-11
    • 1970-01-01
    相关资源
    最近更新 更多