简体   繁体   中英

Unable to persist new object w/ attached existing object

I'm a new Hibernate user being stymied by what I think should be a really straightforward operation. I am trying to load a user from the database, attach it to a new object, and then persist that new object. I am seeing a null constraint violation.

My understanding was that the load() method throws an exception if the AdmUser object can't be found in the database. Just to be sure, I checked, and it is definitely not null. I know it might be a proxy, but I'm in the same session, so that shouldn't be an issue, right? What am I doing wrong here?

AuditLog POJO:

public class AdmAuditLog implements java.io.Serializable {

    private AdmUser actionBy;
    // ...

    public AdmAuditLog() {
    }

    public AdmUser getActionBy() {
        return this.actionBy;
    }

    public void setActionBy(final AdmUser actionBy) {
        this.actionBy = actionBy;
    }

    // ...
}

AdmAuditLog.hbm.xml:

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
    <class name="com.locustec.lotus.db.admin.AdmAuditLog" table="ADM_AUDIT_LOG">
        <id ... />
        <property ... />
        <one-to-one name="actionBy" class="com.locustec.lotus.db.admin.AdmUser" fetch="join" lazy="false" />
    </class>
</hibernate-mapping>

Source code:

final Session session = ...;
final Transaction transaction = session.beginTransaction();

final AdmUser user =
        (AdmUser) asess.load(AdmUser.class, userId);
LOGGER.error("User {} = {}", user.getFullName(), user);

final AdmAuditLog adm = new AdmAuditLog();
adm.setXXX(xxx);
// more setters
adm.setActionBy(user);

session.save(adm);
transaction.commit();

Log file:

20:04:47,900 ERROR User Eric Stein = com.mycompany.myproduct.db.admin.AdmUser@7b2792a0
20:04:49,578 WARN  SQL Error: 515, SQLState: 23000
20:04:49,579 ERROR Cannot insert the value NULL into column 'ACTION_BY', table 'MyDatabase.dbo.ADM_AUDIT_LOG'; column does not allow nulls. INSERT fails.

AuditLog DDL:

USE [MyDatabase]
GO

/****** Object:  Table [dbo].[ADM_AUDIT_LOG]    Script Date: 09/12/2014 20:09:55 ******/
SET ANSI_NULLS ON
GO

SET QUOTED_IDENTIFIER ON
GO

CREATE TABLE [dbo].[ADM_AUDIT_LOG](
    [ALID] [int] NOT NULL,
    [SCOPE_ID] [bigint] NOT NULL,
    [SCOPE] [nvarchar](100) NOT NULL,
    [ACTIVITY_ID] [bigint] NOT NULL,
    [ACTIVITY] [nvarchar](100) NOT NULL,
    [ELEMENT_ID] [bigint] NULL,
    [ELEMENT] [nvarchar](200) NULL,
    [DETAIL] [nvarchar](2000) NULL,
    [ACTION_BY] [bigint] NOT NULL,
    [ACTION_DATE] [datetime] NOT NULL,
    [ACTION_FROM] [nvarchar](50) NULL,
 CONSTRAINT [PK_ADM_AUDIT_LOG] PRIMARY KEY CLUSTERED 
(
    [ALID] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY]

GO

I think that's everything. If there's something else that would be helpful, please don't be shy about asking.

The one-to-one element is used for the "inverse" side on bidirectional one-to-one associations.

The one-to-one element doesn't map to a database Foreign Key. You need to use a unique many-to-one instead:

<many-to-one 
    name="actionBy" 
    class="com.locustec.lotus.db.admin.AdmUser" 
    fetch="join" 
    lazy="false" 
    unique="true"
    not-null="true"/>

The many-to-one element is able to control the FK so it will persist the mapping.

Your error log is pretty explicit - "actor" property in AuditLogEntry entity you're trying to persist is null and column definition in DB does not allow that.

If you are absolutely certain that is not the case (and it basically has to be) we're going to need a lot more details (table ddl, hibernate mapping, relevant entity filling parts)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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