保存时休眠一对一的空外键

时间:2016-01-07 12:30:42

标签: java spring hibernate

我遇到一对一关系的问题 - 保存外键后,即使我有关联对象,外键总是被设置为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)

我尽一切努力让它发挥作用但没有成功。

1 个答案:

答案 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作为主键。