Hibernate一对一映射报错:字段列表中不存在'laptop_lid'列
Hibernate一对一关联映射报错:Unknown column 'laptop_lid' in 'field list'
问题场景
学习Hibernate一对一(One To One)关联映射时,尝试将Java代码中的数据插入对应两张数据库表,运行时出现报错,核心错误为:Caused by: java.sql.SQLSyntaxErrorException: Unknown column 'laptop_lid' in 'field list'。
相关配置与代码
Hibernate.cfg.xml
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE hibernate-configuration SYSTEM "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd"> <hibernate-configuration> <session-factory> <property name = "hibernate.dialect"> org.hibernate.dialect.MySQLDialect </property> <property name = "hibernate.connection.driver_class">com.mysql.jdbc.Driver </property> <!-- Assume test is the database name --> <property name = "hibernate.connection.url">jdbc:mysql://localhost:3306/aliens </property> <property name = "hibernate.connection.username">root</property> <property name = "hibernate.connection.password">root</property> <property name = "hbm2ddl">update</property> <property name = "show_sql">true</property> <!-- List of XML mapping files --> <mapping class= "com.jee.projetHibernate.Student"/> <mapping class= "com.jee.projetHibernate.Laptop"/> </session-factory> </hibernate-configuration>
Student实体类
package com.jee.projetHibernate; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.OneToOne; import javax.persistence.Table; @Entity @Table(name = "student") public class Student { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name="userid") private int id; @Column(name="username") private String name; @OneToOne private Laptop laptop; public Laptop getLaptop() { return laptop; } public void setLaptop(Laptop laptop) { this.laptop = laptop; } public Student() { super(); } public Student(int id, String name) { super(); this.id = id; this.name = name; } public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } @Override public String toString() { return "Student [id=" + id + ", name=" + name + "]"; } }
Laptop实体类
package com.jee.projetHibernate; import javax.persistence.Entity; import javax.persistence.Id; import javax.persistence.Table; @Entity @Table(name = "laptop") public class Laptop { @Id private int lid; private String lname; public int getLid() { return lid; } public void setLid(int lid) { this.lid = lid; } public String getLname() { return lname; } public void setLname(String lname) { this.lname = lname; } }
App主类
package com.jee.projetHibernate; import javax.imageio.spi.ServiceRegistry; import org.hibernate.*; import org.hibernate.boot.registry.StandardServiceRegistry; import org.hibernate.boot.registry.StandardServiceRegistryBuilder; import org.hibernate.cfg.Configuration; import com.mysql.cj.Session; import com.mysql.cj.xdevapi.SessionFactory; public class App { public static void main( String[] args ) { Laptop lap2=new Laptop(); lap2.setLid(3); lap2.setLname("macbook"); Student alien=new Student(); alien.setName("marah"); alien.setLaptop(lap2); Configuration conf =new Configuration().configure("hibernate.cfg.xml").addAnnotatedClass(Student.class).addAnnotatedClass(Laptop.class); StandardServiceRegistry serviceRegistry= new StandardServiceRegistryBuilder().applySettings(conf.getProperties()).build(); org.hibernate.SessionFactory sf=conf.buildSessionFactory(); org.hibernate.Session session=sf.openSession(); Transaction tx=session.beginTransaction(); //to save data in database session.save(lap2); session.save(alien); tx.commit(); //to fetch or get data from database /* * alien2=(Student)session.get(Student.class, 17); System.out.println(alien2); */ } }
完整报错信息
INFO: HHH000490: Using JtaPlatform implementation: [org.hibernate.engine.transaction.jta.platform.internal.NoJtaPlatform] Hibernate: insert into laptop (lname, lid) values (?, ?) Hibernate: insert into student (laptop_lid, username) values (?, ?) oct. 28, 2022 3:30:57 PM org.hibernate.engine.jdbc.spi.SqlExceptionHelper logExceptions WARN: SQL Error: 1054, SQLState: 42S22 oct. 28, 2022 3:30:57 PM org.hibernate.engine.jdbc.spi.SqlExceptionHelper logExceptions ERROR: Unknown column 'laptop_lid' in 'field list' Exception in thread "main" org.hibernate.exception.SQLGrammarException: could not execute statement at org.hibernate.exception.internal.SQLExceptionTypeDelegate.convert(SQLExceptionTypeDelegate.java:63) 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.dialect.identity.GetGeneratedKeysDelegate.executeAndExtract(GetGeneratedKeysDelegate.java:58) at org.hibernate.id.insert.AbstractReturningDelegate.performInsert(AbstractReturningDelegate.java:43) at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:3279) at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:3885) at org.hibernate.action.internal.EntityIdentityInsertAction.execute(EntityIdentityInsertAction.java:84) at org.hibernate.engine.spi.ActionQueue.execute(ActionQueue.java:645) at org.hibernate.engine.spi.ActionQueue.addResolvedEntityInsertAction(ActionQueue.java:282) at org.hibernate.engine.spi.ActionQueue.addInsertAction(ActionQueue.java:263) at org.hibernate.engine.spi.ActionQueue.addAction(ActionQueue.java:317) at org.hibernate.event.internal.AbstractSaveEventListener.addInsertAction(AbstractSaveEventListener.java:330) at org.hibernate.event.internal.AbstractSaveEventListener.performSaveOrReplicate(AbstractSaveEventListener.java:287) at org.hibernate.event.internal.AbstractSaveEventListener.performSave(AbstractSaveEventListener.java:193) at org.hibernate.event.internal.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:123) at org.hibernate.event.internal.DefaultSaveOrUpdateEventListener.saveWithGeneratedOrRequestedId(DefaultSaveOrUpdateEventListener.java:194) at org.hibernate.event.internal.DefaultSaveEventListener.saveWithGeneratedOrRequestedId(DefaultSaveEventListener.java:38) at org.hibernate.event.internal.DefaultSaveOrUpdateEventListener.entityIsTransient(DefaultSaveOrUpdateEventListener.java:179) at org.hibernate.event.internal.DefaultSaveEventListener.performSaveOrUpdate(DefaultSaveEventListener.java:32) at org.hibernate.event.internal.DefaultSaveOrUpdateEventListener.onSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:75) at org.hibernate.event.service.internal.EventListenerGroupImpl.fireEventOnEachListener(EventListenerGroupImpl.java:107) at org.hibernate.internal.SessionImpl.fireSave(SessionImpl.java:672) at org.hibernate.internal.SessionImpl.save(SessionImpl.java:665) at org.hibernate.internal.SessionImpl.save(SessionImpl.java:660) at com.jee.projetHibernate.App.main(App.java:44) Caused by: java.sql.SQLSyntaxErrorException: Unknown column 'laptop_lid' in 'field list' at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:120) at com.mysql.cj.jdbc.exceptions.SQLExceptionsMapping.translateException(SQLExceptionsMapping.java:122) at com.mysql.cj.jdbc.ClientPreparedStatement.executeInternal(ClientPreparedStatement.java:953) at com.mysql.cj.jdbc.ClientPreparedStatement.executeUpdateInternal(ClientPreparedStatement.java:1098) at com.mysql.cj.jdbc.ClientPreparedStatement.executeUpdateInternal(ClientPreparedStatement.java:1046) at com.mysql.cj.jdbc.ClientPreparedStatement.executeLargeUpdate(ClientPreparedStatement.java:1371) at com.mysql.cj.jdbc.ClientPreparedStatement.executeUpdate(ClientPreparedStatement.java:1031) at org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.executeUpdate(ResultSetReturnImpl.java:197) ... 23 more
问题原因及解决方案
问题原因
使用@OneToOne注解时,Hibernate默认会在关联的student表中生成名为laptop_lid的外键字段,但当前数据库的student表中不存在该字段。尽管配置了hbm2ddl.auto=update,但如果student表已存在且包含数据,Hibernate可能无法自动添加该外键字段。
解决方案
方案一:让Hibernate自动重建表结构
将hibernate.cfg.xml中的hbm2ddl属性值改为create(注意:此操作会清空原有表数据并重建表),运行程序后Hibernate会自动创建包含外键字段的student表。测试完成后可改回update。
方案二:手动指定外键并更新数据库
- 修改Student类的
@OneToOne注解,添加@JoinColumn明确指定外键字段名:
@OneToOne @JoinColumn(name = "laptop_id") // 指定外键字段名为laptop_id private Laptop laptop;
- 手动在数据库的student表中添加
laptop_id字段(类型为int,与laptop表的lid字段类型一致)。
方案三:配置双向关联(可选)
若需要双向关联,可在Laptop类中添加Student字段,并通过mappedBy指定由Student维护关联关系:
- Student类修改:
@OneToOne @JoinColumn(name = "laptop_id") private Laptop laptop;
- Laptop类添加:
@OneToOne(mappedBy = "laptop") private Student student;
此配置仅会在student表中生成外键字段,避免双向关联导致的字段重复问题。
内容的提问来源于stack exchange,提问作者HAFIDA FAOUZI
相关产品推荐
相关产品推荐

