【问题标题】:Hibernate & Spring Roo: org.hibernate.PersistentObjectException: detached entity passed to persistHibernate & Spring Roo:org.hibernate.PersistentObjectException:分离的实体传递给持久化
【发布时间】:2014-04-02 05:48:26
【问题描述】:

我正在使用 Spring Roo 生成基于表的实体(在 MS SQL Server 上创建)。以下是我的sql脚本:

CREATE TABLE [dbo].[JMSMessage](
     [MessageID] [nvarchar](100) NOT NULL,
     [Destination] [varchar](50) NOT 
     [Status] [varchar](15) NULL,
CONSTRAINT [PK_JMSMessage] PRIMARY KEY CLUSTERED 
(
    [MessageID] ASC
) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF,ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]

Spring Roo生成的Java实体是

@Entity
@Table(schema = "dbo",name = "JMSMessage")
@Configurable
public class Jmsmessage {

    @Column(name = "Destination", length = 50)
    @NotNull
    private String destination;

    @Column(name = "Status", length = 15)
    private String status;

    public String getDestination() {
        return destination;
    }

    public void setDestination(String destination) {
        this.destination = destination;
    }

    public String getStatus() {
        return status;
    }

    public void setStatus(String status) {
        this.status = status;
    }

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name = "MessageID", length = 100)
    private String messageId;

    public String getMessageId() {
        return this.messageId;
    }

    public void setMessageId(String id) {
        this.messageId = id;
    }

    @PersistenceContext
    transient EntityManager entityManager;

    public static final EntityManager entityManager() {
        EntityManager em = new Jmsmessage().entityManager;
        if (em == null) throw new IllegalStateException("Entity manager has not been injected (is the Spring Aspects JAR configured as an AJC/AJDT aspects library?)");
        return em;
    }

    public static Jmsmessage findJmsmessage(String messageId) {
        if (messageId == null || messageId.length() == 0) return null;
        return entityManager().find(Jmsmessage.class, messageId);
    }

    @Transactional
    public void persist() {
        if (this.entityManager == null) this.entityManager = entityManager();
        this.entityManager.persist(this);
    }

    @Transactional
    public void remove() {
        if (this.entityManager == null) this.entityManager = entityManager();
        if (this.entityManager.contains(this)) {
            this.entityManager.remove(this);
        } else {
            Jmsmessage attached = Jmsmessage.findJmsmessage(this.messageId);
            this.entityManager.remove(attached);
        }
    }

    @Transactional
    public void flush() {
        if (this.entityManager == null) this.entityManager = entityManager();
        this.entityManager.flush();
    }

    @Transactional
    public void clear() {
        if (this.entityManager == null) this.entityManager = entityManager();
        this.entityManager.clear();
    }

    @Transactional
    public Jmsmessage merge() {
        if (this.entityManager == null) this.entityManager = entityManager();
        Jmsmessage merged = this.entityManager.merge(this);
        this.entityManager.flush();
        return merged;
    }

    public String toString() {
        return ReflectionToStringBuilder.toString(this, ToStringStyle.SHORT_PREFIX_STYLE);
    }
}

然后,当我运行以下代码来创建实体实例并尝试持久化它时,程序会抛出 PersistentObjectException 说“分离的实体传递给持久化”。

Jmsmessage message = new Jmsmessage();
message.setMessageId("m1");
message.setDestination("queue1");
message.setStatus("status1");
message.persist(); // If i use message.merge(), it will throws another Sql exception saying "Cannot insert the value NULL into column 'MessageID'"

我怎样才能使持久工作,有什么建议吗?提前致谢!

【问题讨论】:

  • ID 的生成类型为 AUTO.. 将其更改为已分配。按照这个:stackoverflow.com/questions/10041938/…
  • 试图将其更改为已分配,但仍然抛出相同的异常
  • @Id @GenericGenerator(name = "idGenerator", strategy = "assigned") @GeneratedValue(generator = "idGenerator") @Column(name = "MessageID", length = 100) private String Jmsmessage .messageId;

标签: java spring hibernate jpa spring-roo


【解决方案1】:

你不应该为messageId设置一个值,因为你有@GeneratedValue(strategy = GenerationType.AUTO)的策略

另一方面,我注意到您使用了 roo 提供的活动记录模式。我建议您将其更改为 DAO 模式,因为这样的代码在 Java/Spring/Hibernate 世界中非常罕见:)

【讨论】:

  • 但 MessageID 列不允许为空
  • 是的,我知道,但是您的 JPA 供应商会提供正确的值,因为您有自动策略
  • @dereck 太好了!
【解决方案2】:

您有 ID 生成策略 auto,但您在实体中分配了一些 id 值。这意味着 ORM 引擎会将您的新实体视为分离实体,因为它获得了 id,并且它会抛出异常,例如尝试保存分离的实体。如果您尝试合并实体以解决问题,ORM 引擎将检查您提供给实体,它将无法与您的实体匹配任何行,因为没有具有该主键的此类行..
错误的底线是,您将 ORM 引擎与 Id 生成混淆了

希望这有帮助!

【讨论】:

    猜你喜欢
    • 2020-11-02
    • 2017-10-21
    • 1970-01-01
    • 2018-01-05
    • 2018-06-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-06-26
    相关资源
    最近更新 更多