Hibernate - OneToMany 单向映射 - SQLGrammarException
Posted
技术标签:
【中文标题】Hibernate - OneToMany 单向映射 - SQLGrammarException【英文标题】:Hibernate - OneToMany UniDirectional Mapping - SQLGrammarException 【发布时间】:2020-05-07 14:42:28 【问题描述】:我是 Hibernate 学习的新手,因此正在研究其中使用的关系。我所理解的是 - 对于具有外键的 OneToMany 单向关系映射,连接列将位于目标实体中(在我的情况下 - 审查类)。而且我不需要让它双向工作。
但是在实现它时,我遇到了以下错误:
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)
课程实体类:
@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 + "]";
审查实体类:
@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 + "]";
主要方法:
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();
创建表的 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")
);
参考链接:
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>
<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>
尝试了以下选项,但没有成功:
1. escaping character backtick ("`")
2. escaping character (""\")
3. hibernate property : <property name="hibernate.globally_quoted_identifiers">true</property>
请帮忙!!!
【问题讨论】:
【参考方案1】:其实,你的映射没问题。您应该只为reserved oracle keyword comment
添加backticks。
@Entity
@Table(name="review")
public class Review
@Column(name = "`comment`")
private String comment;
// ...
【讨论】:
我知道双向关系,它对我来说很好用。问题是单向映射。更新了问题。如果我已经在使用外键,为什么还要附加链接? 您必须更正数据库架构以使用单向 @OneToMany。正如我所提到的,为此,您需要两个连接实体之间的附加链接表。 你能解释一下 - 架构有什么问题吗?对于 OneToMany 单向映射,外键应该在目标实体中,这在我的情况下是正确的。 我已经更正了我的答案。问题的根本原因完全在其他地方。 ;) 它没有帮助......它现在给出了这个错误 -Caused by: java.sql.SQLSyntaxErrorException: ORA-00904: "comment": invalid identifier
:|【参考方案2】:
最后,我设法通过将DB中的列名重命名为course_comment
来解决它
@Column(name="course_comment")
private String courseComment;
【讨论】:
以上是关于Hibernate - OneToMany 单向映射 - SQLGrammarException的主要内容,如果未能解决你的问题,请参考以下文章
删除元素时使用 JoinTable 和 OrderColumn 的 Hibernate 单向 OneToMany 映射中的约束冲突
Hibernate如何正确删除@OneToMany中的孩子?