我遇到一对一关系的问题 - 保存外键后,即使我有关联对象,外键总是被设置为null。我在Spring 4.0.0.RELEASE和MySql 5.6数据库中使用Hibernate 4.3.7.Final。
在我保存LawFirmProfile对象列后的情况下,lawFirm_id参考LawFirm始终为空。
实体:
@Data
@Entity
@Table(name="usr_lawfirm")
@PrimaryKeyJoinColumn(name="userId")
public class LawFirm extends User implements Serializable{
...
@OneToOne(mappedBy = "lawFirm")
private LawFirmProfile lawFirmProfile = new LawFirmProfile();
@Override
public boolean equals(Object obj){
return super.equals(obj);
}
@Override
public int hashCode() {
return super.hashCode();
}
}
@Data
@Entity
@Table(name="lf_profile")
@EqualsAndHashCode(of = {"id"})
public class LawFirmProfile implements Serializable{
@Id
@GeneratedValue(strategy = IDENTITY)
private Integer id;
...
@OneToOne
@JoinColumn(name = "lawFirm_id")
private LawFirm lawFirm;
}
@Data
@Entity
@Table(name = "usr_user")
@Inheritance(strategy = InheritanceType.JOINED)
@EqualsAndHashCode(of = {"email"})
public class User implements Serializable {
@Id
@GeneratedValue(strategy = IDENTITY)
@Column(unique = true, nullable = false)
private Integer userId;
@Column(unique = true)
private String email;
...
}
以下是负责保存此记录的代码:
@Override
@Transactional
public void saveProfile(LawFirm lawFirm){
LawFirmProfile profile = lawFirm.getLawFirmProfile();
userDao.update(lawFirm);
profile.setLawFirm(lawFirm);
lawFirmProfileDao.saveOrUpdate(profile);
}
Hibernate和Spring配置:
<tx:annotation-driven transaction-manager="transactionManager"/>
<bean
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location">
<value>system.properties</value>
</property>
</bean>
<bean id="dataSource"
class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="${jdbc.driverClassName}" />
<property name="jdbcUrl" value="${jdbc.url}" />
<property name="user" value="${jdbc.username}" />
<property name="password" value="${jdbc.password}" />
<property name="minPoolSize" value="${c3p0.minPoolSize}" />
<property name="maxPoolSize" value="${c3p0.maxPoolSize}" />
<property name="maxIdleTime" value="${c3p0.maxIdleTime}" />
<property name="maxStatements" value ="${c3p0.maxStatements}" />
</bean>
<!-- Hibernate session factory -->
<bean id="sessionFactory"
class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource">
<ref bean="dataSource"/>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
<prop key="hibernate.show_sql">true</prop>
<prop key="hibernate.hbm2ddl.auto">update</prop>
<prop key="hibernate.validator.apply_to_ddl">false</prop>
<prop key="hibernate.validator.autoregister_listeners">false</prop>
<prop key="javax.persistence.validation.mode">none</prop>
</props>
</property>
<property name="packagesToScan" value="com.test." />
</bean>
<bean id="transactionManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
Dao也是一个带有注释为@Transactional的方法的春豆。
在保存期间,我从C3p0得到以下错误。然而,LawFirmProfile记录保存在数据库中,但对LawFirm的引用无效。
2016-01-07 13:25:26,084 Participating in existing transaction
2016-01-07 13:25:26,095 Adding transactional method 'saveOrUpdate' with attribute: PROPAGATION_REQUIRED,ISOLATION_DEFAULT; ''
2016-01-07 13:25:26,096 Returning cached instance of singleton bean 'transactionManager'
2016-01-07 13:25:26,096 Found thread-bound Session [SessionImpl(PersistenceContext[entityKeys=[EntityKey[com.efsf.gateone.user.model.LawFirm#55]],collectionKeys=[CollectionKey[com.efsf.gateone.user.model.User.sendMessages#55], CollectionKey[com.efsf.gateone.user.model.User.payments#55], CollectionKey[com.efsf.gateone.user.model.LawFirm.invitations#55], CollectionKey[com.efsf.gateone.user.model.User.receivedMessages#55], CollectionKey[com.efsf.gateone.user.model.User.attachments#55], CollectionKey[com.efsf.gateone.user.model.LawFirm.legalCases#55]]];ActionQueue[insertions=org.hibernate.engine.spi.ExecutableList@6350cb30 updates=org.hibernate.engine.spi.ExecutableList@4d4bef40 deletions=org.hibernate.engine.spi.ExecutableList@34487a65 orphanRemovals=org.hibernate.engine.spi.ExecutableList@25b97b4 collectionCreations=org.hibernate.engine.spi.ExecutableList@4b44aba1 collectionRemovals=org.hibernate.engine.spi.ExecutableList@95ffda2 collectionUpdates=org.hibernate.engine.spi.ExecutableList@7d049b7c collectionQueuedOps=org.hibernate.engine.spi.ExecutableList@397c2a03 unresolvedInsertDependencies=UnresolvedEntityInsertActions[]])] for Hibernate transaction
2016-01-07 13:25:26,096 Participating in existing transaction
Hibernate: insert into lf_profile (city, postCode, street, krsNumber, name, nip, regon, email, phone, website, description, latitude, longitude, lawFirm_id, lawFirmType, lawyerNumber, pricePerHour, solicitorNumber, specialization) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
2016-01-07 13:25:26,126 com.mchange.v2.async.ThreadPoolAsynchronousRunner@6db73230: Adding task to queue -- com.mchange.v2.c3p0.stmt.GooGooStatementCache$1StmtAcquireTask@7e308448
2016-01-07 13:25:26,127 cxnStmtMgr.statementSet( com.mysql.jdbc.JDBC4Connection@40a126ad ).size(): 7
2016-01-07 13:25:26,127 checkoutStatement: com.mchange.v2.c3p0.stmt.GlobalMaxOnlyStatementCache stats -- total size: 7; checked out: 1; num connections: 1; num keys: 7
2016-01-07 13:25:26,142 checkinStatement(): com.mchange.v2.c3p0.stmt.GlobalMaxOnlyStatementCache stats -- total size: 7; checked out: 0; num connections: 1; num keys: 7
2016-01-07 13:25:26,142 Initiating transaction commit
2016-01-07 13:25:26,143 Committing Hibernate transaction on Session [SessionImpl(PersistenceContext[entityKeys=[EntityKey[com.efsf.gateone.user.model.LawFirm#55], EntityKey[com.efsf.gateone.lawfirm.model.LawFirmProfile#68]],collectionKeys=[CollectionKey[com.efsf.gateone.user.model.User.sendMessages#55], CollectionKey[com.efsf.gateone.user.model.User.payments#55], CollectionKey[com.efsf.gateone.user.model.LawFirm.invitations#55], CollectionKey[com.efsf.gateone.user.model.User.receivedMessages#55], CollectionKey[com.efsf.gateone.user.model.User.attachments#55], CollectionKey[com.efsf.gateone.user.model.LawFirm.legalCases#55]]];ActionQueue[insertions=org.hibernate.engine.spi.ExecutableList@6350cb30 updates=org.hibernate.engine.spi.ExecutableList@4d4bef40 deletions=org.hibernate.engine.spi.ExecutableList@34487a65 orphanRemovals=org.hibernate.engine.spi.ExecutableList@25b97b4 collectionCreations=org.hibernate.engine.spi.ExecutableList@4b44aba1 collectionRemovals=org.hibernate.engine.spi.ExecutableList@95ffda2 collectionUpdates=org.hibernate.engine.spi.ExecutableList@7d049b7c collectionQueuedOps=org.hibernate.engine.spi.ExecutableList@397c2a03 unresolvedInsertDependencies=UnresolvedEntityInsertActions[]])]
Hibernate: update usr_user set email=?, lastLogin=?, login=?, name=?, password=?, phone=?, premiumUntil=?, status=?, surname=? where userId=?
2016-01-07 13:25:26,145 com.mchange.v2.c3p0.stmt.GlobalMaxOnlyStatementCache ----> CACHE HIT
2016-01-07 13:25:26,145 checkoutStatement: com.mchange.v2.c3p0.stmt.GlobalMaxOnlyStatementCache stats -- total size: 7; checked out: 1; num connections: 1; num keys: 7
2016-01-07 13:25:26,147 checkinStatement(): com.mchange.v2.c3p0.stmt.GlobalMaxOnlyStatementCache stats -- total size: 7; checked out: 0; num connections: 1; num keys: 7
2016-01-07 13:25:26,147 Converting Throwable to SQLException...
java.lang.NullPointerException
at com.mchange.v2.c3p0.impl.NewProxyPreparedStatement.maybeDirtyTransaction(NewProxyPreparedStatement.java:2520)
at com.mchange.v2.c3p0.impl.NewProxyPreparedStatement.getMaxRows(NewProxyPreparedStatement.java:1403)
at org.hibernate.engine.jdbc.internal.JdbcCoordinatorImpl.close(JdbcCoordinatorImpl.java:530)
at org.hibernate.engine.jdbc.internal.JdbcCoordinatorImpl.release(JdbcCoordinatorImpl.java:407)
at org.hibernate.engine.jdbc.batch.internal.AbstractBatchImpl.releaseStatements(AbstractBatchImpl.java:173)
at org.hibernate.engine.jdbc.batch.internal.NonBatchingBatch.addToBatch(NonBatchingBatch.java:76)
at org.hibernate.persister.entity.AbstractEntityPersister.update(AbstractEntityPersister.java:3281)
at org.hibernate.persister.entity.AbstractEntityPersister.updateOrInsert(AbstractEntityPersister.java:3183)
at org.hibernate.persister.entity.AbstractEntityPersister.update(AbstractEntityPersister.java:3525)
at org.hibernate.action.internal.EntityUpdateAction.execute(EntityUpdateAction.java:158)
at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:453)
我尽一切努力让它发挥作用但没有成功。
答案 0 :(得分:0)
您对LawFirm
的{{1}}课程引用应如下所示
LawFirmProfile
此外,当您的LawFirm类ID更新时,请务必同时更新LawFirmProfile类。看起来应该是这样的:
@OneToOne(cascade = {CascadeType.ALL}) // The cascade part is probably optional
@PrimaryKeyJoinColumn
private LawFirmProfile lawFirmProfile;
现在为您的LawFirmProfile课程。确保该参数有public void setUserId(int userId) {
if(LawFirmProfile != null) {
LawFirmProfile.setLawFirmId(userId);
}
this.userId = userId;
}
lawFirmId
还要确保LawFirmProfile类具有对LawFirm的引用
@Column(name="lawFirm_id")
@Id
private int lawFirmId;
... lawFirmId getter and setter....
使用getter和setter,使用这样的setter:
@MapsId
@OneToOne
@JoinColumn(name="lawFirmId")
private LawFirm lawFirm;
然后正如评论中所讨论的那样,从lf_profile中删除public void setLawFirm(LawFirm lawFirm) {
this.lawFirm = lawFirm;
if(lawFirm != null) {
lawFirmId = lawFirm.getUserId();
}
}
列,并将lawFirm_id作为主键。