简体   繁体   English

Hibernate - OneToMany 单向映射 - SQLGrammarException

[英]Hibernate - OneToMany UniDirectional Mapping - SQLGrammarException

I'm new to Hibernate learning so studying relations being used in it.我是 Hibernate 学习的新手,因此正在研究其中使用的关系。 What I have understood is - For OneToMany uni-directional relation mapping with foreign key, the Join Column would be in target entity (In my case - Review class).我所理解的是 - 对于具有外键的 OneToMany 单向关系映射,连接列将位于目标实体中(在我的情况下 - 审查类)。 And I need not to make it bi-directional to make it work.而且我不需要让它双向工作。

But While implementing it, I'm getting below error:但是在实现它时,我遇到了以下错误:

Hibernate: insert into course (title, id) values (?, ?)
Hibernate: insert into review (comment, id) values (?, ?)
2020-05-07 19:44:24 WARN  SqlExceptionHelper:137 - SQL Error: 928, SQLState: 42000
2020-05-07 19:44:24 ERROR SqlExceptionHelper:142 - ORA-00928: missing SELECT keyword

Exception in thread "main" javax.persistence.PersistenceException: org.hibernate.exception.SQLGrammarException: 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:1356)
    at org.hibernate.internal.SessionImpl.managedFlush(SessionImpl.java:443)
    at org.hibernate.internal.SessionImpl.flushBeforeTransactionCompletion(SessionImpl.java:3202)
    at org.hibernate.internal.SessionImpl.beforeTransactionCompletion(SessionImpl.java:2370)
    at org.hibernate.engine.jdbc.internal.JdbcCoordinatorImpl.beforeTransactionCompletion(JdbcCoordinatorImpl.java:447)
    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.practice.hibernate008.onetomany.unidirectional.HibernateApp_1_CreateCourseAndReviewsDemo.main(HibernateApp_1_CreateCourseAndReviewsDemo.java:40)

Course Entity Class:课程实体 Class:

@Entity
@Table(name="course")
public class Course {

    @Id
    @SequenceGenerator(allocationSize=1,name="id_generator", sequenceName="ID_GENERATOR_SEQ",initialValue=30)
    @GeneratedValue(strategy=GenerationType.SEQUENCE, generator="id_generator")   //Auto Increment feature - Strategy to handle multiple objects
    @Column(name="id")
    private int id;

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

    @OneToMany(cascade=CascadeType.ALL)
    @JoinColumn(name="course_id")
    private List<Review> reviews;

    public Course() {}

    public Course(String title) {
        super();
        this.title = title;
    }

    //add convenience method
    public void addReview(Review review){
        if(reviews == null){
            reviews = new ArrayList<Review>();
        }
        reviews.add(review);
    }

    public int getId() {
        return id;
    }

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

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public List<Review> getReviews() {
        return reviews;
    }

    public void setReviews(List<Review> reviews) {
        this.reviews = reviews;
    }

    @Override
    public String toString() {
        return "Course [id=" + id + ", title=" + title + ", reviews=" + reviews + "]";
    }
}

Review Entity Class:查看实体 Class:

@Entity
@Table(name="review")
public class Review {

    @Id
    @SequenceGenerator(allocationSize=1,name="id_generator", sequenceName="ID_GENERATOR_SEQ",initialValue=30)
    @GeneratedValue(strategy=GenerationType.SEQUENCE, generator="id_generator")
    @Column(name="id")
    private int id;

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

    public Review() {}

    public Review(String comment) {
        super();
        this.comment = comment;
    }

    public int getId() {
        return id;
    }

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

    public String getComment() {
        return comment;
    }

    public void setComment(String comment) {
        this.comment = comment;
    }

    @Override
    public String toString() {
        return "Review [id=" + id + ", comment=" + comment + "]";
    }

}

Main Method:主要方法:

public static void main(String[] args) {

    SessionFactory sessionFactory = new Configuration().configure("hibernate-configuration.xml")
                                                       .addAnnotatedClass(Course.class)
                                                       .addAnnotatedClass(Review.class)
                                                       .buildSessionFactory();

    Session session = sessionFactory.getCurrentSession();

    try{

        Course course = new Course("Hibernate - Beginner Course");
        course.addReview(new Review("Great Course ... loved it."));
        course.addReview(new Review("Cool Course ... well done!!"));
        course.addReview(new Review("Dump Course .. You are an idiot."));

        session.beginTransaction();
        System.out.println("Saving the course :: " + course);
        session.save(course);

        session.getTransaction().commit();
    } finally{
        sessionFactory.close();
    }
}

SQLs for table created:创建表的 SQL:

CREATE TABLE "COURSE" 
(   
    "ID" NUMBER NOT NULL ENABLE, 
    "TITLE" VARCHAR2(50 BYTE) DEFAULT null, 
     PRIMARY KEY ("ID"),
 );

CREATE TABLE "REVIEW" 
(   
    "ID" NUMBER NOT NULL ENABLE, 
    "COMMENT" VARCHAR2(256 BYTE) DEFAULT null, 
    "COURSE_ID" NUMBER  DEFAULT NULL, 
     PRIMARY KEY ("ID"),
     FOREIGN KEY("COURSE_ID") REFERENCES "COURSE"("ID")
);

Reference link:参考链接:

OneToMany-UniDirectional-Example3 OneToMany-UniDirectional-Example3

Example 3: Unidirectional One-to-Many association using a foreign key mapping

    // In Customer class:

    @OneToMany(orphanRemoval=true)
    @JoinColumn(name="CUST_ID") // join column is in table for Order
    public Set<Order> getOrders() {return orders;}

Hibernate Configuration: Hibernate 配置:

<hibernate-configuration>
    <session-factory>
        <!-- JDBC Database connection settings -->
        <property name="connection.driver_class">oracle.jdbc.driver.OracleDriver</property>
        <property name="connection.url">jdbc:oracle:thin:@localhost:1521:oracledb</property>
        <property name="connection.username">hibernate</property>
        <property name="connection.password">hibernate</property>

        <!-- JDBC connection pool settings ... using built-in test pool -->
        <property name="connection.pool_size">1</property>

        <!-- Select our SQL dialect -->
        <property name="dialect">org.hibernate.dialect.OracleDialect</property>

        <!-- Echo the SQL to stdout -->
        <property name="show_sql">true</property>

        <!-- Set the current session context -->
        <property name="current_session_context_class">thread</property>
    </session-factory>
</hibernate-configuration>

Tried below options but did not work:尝试了以下选项,但没有奏效:

 1. escaping character backtick ("`") 
 2. escaping character (""\") 
 3. hibernate property : <property name="hibernate.globally_quoted_identifiers">true</property>

Please help out for this !!!请帮忙解决这个问题!!!

Actually, your mapping is okay.实际上,您的映射没问题。 You should only add backticks for the reserved oracle keyword comment .您应该只为 保留的 oracle 关键字comment添加反引号

@Entity
@Table(name="review")
public class Review {

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

   // ...
}

Finally, I managed to solve it by renaming the column name in DB to course_comment最后,我设法通过将 DB 中的列名重命名为course_comment来解决它

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM