【问题标题】:Detached entity passed to persist with primary key that is also foreign key传递的分离实体与主键保持一致,主键也是外键
【发布时间】:2017-02-17 12:38:19
【问题描述】:

我在 postgres 中有以下表格:

create table USER(
    USER_ID SERIAL primary key,
    USER_NAME varchar(50) not null,
    PASSWORD varchar(120) not null,
)

create table ACCESS_TOKEN(
    USER_CODE INTEGER,
    TOKEN_CREATED DATE,
    TOKEN_VALUE VARCHAR(100),

    primary key (USER_CODE, TOKEN_CREATED),
    foreign key (USER_CODE) references USER(USER_ID),
)

我已经创建了以下实体

@Entity
@Table(name="USER")
public class User implements Serializable{

    @Id
    @SequenceGenerator(name = "USER_USER_ID_SEQ_GEN", sequenceName = "USER_USER_ID_SEQ", initialValue=1, allocationSize = 1)
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "USER_USER_ID_SEQ_GEN")
    @Column(name="USER_ID")
    private int id;

    @Column(name="USER_NAME")
    private String name;

    @Column(name="PASSWORD")
    private String password;
}

@Entity
@Table(name = "ACCESS_TOKEN")
@IdClass(AccessToken.AccessTokenPK.class)
public class AccessToken implements Serializable{

    @Id
    @JoinColumn(name="USER_CODE", referencedColumnName = "USER_ID")
    @ManyToOne
    private User user;

    @Id
    @Column(name="TOKEN_CREATED")
    @Temporal(TemporalType.TIMESTAMP)
    private Date created;


    @Column(name = "TOKEN_VALUE")
    private String token;


    public static class AccessTokenPK implements Serializable{
        protected int user;
        protected Date created;

        //constructor, hashbode, and equals
    }

}

但是,当我尝试按以下方式保留访问令牌时:

AccessToken accessToken = new AccessToken();
accessToken.setUser(userEntity);
accessToken.setCreated(new Date());
accessToken.setToken("some string");
// persist token
dao.persist(accessToken);

我收到以下错误

detached entity passed to persist: User

【问题讨论】:

  • User 是一个新实体吗?如果是这样,您是否尝试过这里的建议:stackoverflow.com/questions/17592247/…?基本上,最简单的解决方案似乎是先坚持User,然后再坚持AccessToken。如果没有,请发布您用于从持久存储中获取 User 实体的代码。
  • 用户是现有实体,我可以通过传递原生插入查询来解决这个问题,但是通过 JPA,它给了我这个错误
  • 您需要确保当您调用dao.persist(accessToken) 时,accessToken.user 字段代表一个托管实体。实现这一目标的最简单方法是在调用dao.persist 之前调用accessToken.setUser(entityManager.getReference(User.class, userEntity.getId()))。不过,您绝对需要在事务范围内进行所有这些调用。

标签: postgresql hibernate jpa


【解决方案1】:

Hibernate 通过其主键识别实体。 尝试将 GenerationType.AUTO 设置为用户的主键,

@Entity
@Table(name="USER")
public class User implements Serializable{

    @Id
    @SequenceGenerator(name = "USER_USER_ID_SEQ_GEN", sequenceName = "USER_USER_ID_SEQ", initialValue=1, allocationSize = 1)
    @GeneratedValue(strategy = GenerationType.AUTO, generator = "USER_USER_ID_SEQ_GEN")
    @Column(name="USER_ID")
    private int id;

    @Column(name="USER_NAME")
    private String name;

    @Column(name="PASSWORD")
    private String password;
}




@Entity
@Table(name = "ACCESS_TOKEN")
@IdClass(AccessToken.AccessTokenPK.class)
public class AccessToken implements Serializable{

    @Id
    @ManyToOne(cascade = {CascadeType.ALL},fetch= FetchType.EAGER)
    @JoinColumn(name="USER_CODE", referencedColumnName = "USER_ID")
    @ManyToOne
    private User user;

    @Id
    @Column(name="TOKEN_CREATED")
    @Temporal(TemporalType.TIMESTAMP)
    private Date created;


    @Column(name = "TOKEN_VALUE")
    private String token;


    public static class AccessTokenPK implements Serializable{
        protected int user;
        protected Date created;

        //constructor, hashbode, and equals
    }

}

【讨论】:

  • 你是如何创建 userEntity 的?在这里,accessToken.setUser(userEntity);尝试对主键进行硬编码并传递它,如果它有效,那就是问题所在。
  • 这样,UserEntity userEntity = new UserEntity(); userEntity.setId(1234);
猜你喜欢
  • 2010-10-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-11-21
  • 2015-02-03
  • 2015-03-08
  • 1970-01-01
相关资源
最近更新 更多