我是一个新的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
我认为这就是一切。如果还有其他有用的东西,请不要羞于询问。
答案 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映射,相关实体填充部分)