无法保留附加现有对象的新对象

时间:2014-09-12 20:21:25

标签: java hibernate jpa orm hibernate-mapping

我是一个新的Hibernate用户,被我认为应该是一个非常简单的操作所困扰。我试图从数据库加载用户,将其附加到新对象,然后持久保存该新对象。我看到了一个空约束违规。

我的理解是,如果在数据库中找不到load()对象,AdmUser方法会抛出异常。只是为了确定,我检查过,它绝对不是空的。我知道它可能是一个代理,但我在同一个会话中,所以这应该不是问题,对吧?我在这里做错了什么?

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>

源代码:

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();

日志文件:

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

我认为这就是一切。如果还有其他有用的东西,请不要羞于询问。

2 个答案:

答案 0 :(得分:1)

一对一元素用于双向一对一关联的“反向”。

一对一元素不会映射到数据库外键。您需要使用唯一的多对一:

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

多对一元素能够控制FK,因此它将持久映射。

答案 1 :(得分:0)

您的错误日志非常明确 - &#34;演员&#34;您尝试持久化的AuditLogEntry实体中的属性为null,DB中的列定义不允许这样做。

如果您完全确定不是这种情况(并且基本上必须如此),我们将需要更多细节(表ddl,hibernate映射,相关实体填充部分)