java - 我无法让级联在实体 Hibernate 上工作

标签 java hibernate jpa

我有一个具有两个多对一关系的实体,其中一个在保存时级联,另一个返回:

Exception in thread "main" org.hibernate.TransientObjectException: object references an 
unsaved transient instance - save the transient instance before flushing : dto.publicSchema.Pessoas

这是有效实体的代码:

@Entity
@Table(name="`Doc_tipo`", schema="public")
public class Doc_tipo implements Serializable {

private static final long serialVersionUID = 1859372890916956036L;

@Id
@Column(nullable=false)
private int tp_doc;
@Column(nullable=false,columnDefinition="CHAR(255)")
private String descricao;
@Column(nullable=false,columnDefinition="CHAR(255)")
private String tp_emissor;

//getters and setters
}

下面是不允许级联的实体代码:

@Entity
@Table(name="`Pessoas`", schema="public")
public class Pessoas implements Serializable {

private static final long serialVersionUID = 8292302132119274975L;

@Id @GeneratedValue
@Column(nullable=false,columnDefinition="serial NOT NULL")
private int seq_pessoa;


static Date padrao_dt_criacao = new Date();
@Column(nullable=false, columnDefinition="date NOT NULL")
private Date dt_criacao = padrao_dt_criacao;

@Column(columnDefinition="CHAR(255)")
private String nome;

@Column(columnDefinition="CHAR(1) NULL")
private char tp_pessoa;

@Column(columnDefinition="CHAR(255)")
private String fantasia;

@Column(columnDefinition="VARCHAR(25)")
private String idioma;

@Column(columnDefinition="VARCHAR(25)")
private String login;

@Column(columnDefinition="VARCHAR(25)")
private String senha;   


static Date padrao_dt_i = new Date();
@Column(nullable=false, columnDefinition="date NOT NULL")
private Date dt_i = padrao_dt_i;

//Pessoa está ativa para o sitema se este campo estiver em branco
@Column(columnDefinition="date")
private Date dt_f; 

@Column(columnDefinition="oid")
private int foto;   

//getters and setters   
}   

这是与上面两个有多对一关系的类 但级联只适用于第一个:

@Entity
@Table(name="`Documentos`", schema="public")
public class Documentos implements Serializable {

private static final long serialVersionUID = -4874330647877687810L;

@Id
@ManyToOne(cascade=CascadeType.ALL)
@JoinColumn(name="seq_pessoa",columnDefinition="integer",referencedColumnName="seq_pessoa",nullable=false)
private Pessoas seq_pessoa;

@Id @GeneratedValue
@Column(nullable=false,columnDefinition="serial NOT NULL")
private int cd_doc;

@ManyToOne(cascade=CascadeType.ALL)
@JoinColumn(name="tp_doc",referencedColumnName="tp_doc",nullable=false)
private Doc_tipo tp_doc;

@Column(nullable=false)
private int tp_emissor;

@Column(nullable=false,columnDefinition="CHAR(2) NOT NULL DEFAULT 'DF'::bpchar")
private String tp_emissor_uf="DF";

@Column(columnDefinition="CHAR(5)")
private String alfa_doc;

@Column(nullable=false,columnDefinition="CHAR(20)")
private String nr_doc;

//Data de validade do documento
@Column(columnDefinition="date")
private Date dt_f_valid;

@Transient
transient static Date padrao_dt_i = new Date();
@Column(columnDefinition="date DEFAULT now()")
private Date dt_i = padrao_dt_i;

@Column(columnDefinition="date")
private Date dt_f;
    //getters and setters
}

当我去保存一个 Documentos 对象时,hibernate 将 Doc_tipo 插入到它的表中 正如它应该的那样,而不是插入 Pessoa 对象也会抛出该异常。

这是操作 session 的类(仅用于测试):

public class Hibernate {



public static SessionFactory getSessionFactory() {

    SessionFactory sessionFactory = null;
    try {
        Configuration configuration = new Configuration();

        configuration.configure();

        ServiceRegistry  serviceRegistry = new  ServiceRegistryBuilder().applySettings(

        configuration.getProperties()).buildServiceRegistry();

        sessionFactory = configuration.buildSessionFactory(serviceRegistry);
    } catch (HibernateException hbe) {

        hbe.printStackTrace();

    }

    return sessionFactory;
}

public static void main(String[] args) {


    SessionFactory sessionFactory = getSessionFactory();
    Session session = sessionFactory.openSession();
    session.beginTransaction();


    Pessoas a = new Pessoas();
    a.setDt_criacao(new Date());
    a.setDt_f(new Date());
    a.setDt_i(new Date());
    a.setFantasia("teste");
    a.setFoto(12);
    a.setIdioma("aa");
    a.setLogin("aa");
    a.setNome("aa");
    a.setSenha("a");
    a.setTp_pessoa('H');



    Doc_tipo b = new Doc_tipo();
    b.setDescricao("aa");
    b.setTp_doc(5);
    b.setTp_emissor("aaa");


    Documentos c = new Documentos();

    c.setAlfa_doc("aaa");
    c.setDt_f(new Date());
    c.setDt_f_valid(new Date());
    c.setDt_i(new Date());
    c.setNr_doc("aa");
    c.setSeq_pessoa(a);
    c.setTp_doc(b);
    c.setTp_emissor(1);
    c.setTp_emissor_uf("aa");

    //session.save(a);
    session.save(c);





    session.getTransaction().commit();
    session.close();



}

}

如果我删除对 save() Pessoas 对象的注释,一切正常,但我不应该这样做,当我尝试在另一个中级联保存时会发生同样的异常 也与 Pessoas 具有多对一关系的实体。

最佳答案

Documentos 使用主键 (Pessoas.seq_pessoa) 引用 Pessoas,因为 Pessoas 使用序列,它仅在保存/刷新到数据库后创建。所以在保存/持久化实际发生之前没有什么可引用的。

此外,您不应使用多个@Id 注释来定义复合身份,除非您还定义了包含上述@Id 字段的@IdClass。或者你也可以 @EmbeddedId 注释。 JPA 支持两种不同的复合 PK 方法。在每种情况下,都必须有一个包含字段的 PK 类。

A) 实体上的多个@Id 字段/属性。实体中字段的名称和类型必须与 PK 类中的名称和类型匹配。类上还必须有一个@IdClass 注释。例如:

public class EmpPK {
int id;
String name;
...
}

@Entity
@IdClass(EmpPK.class)
public class Employee {
@Id int id;
@Id String name;

...
}

B) 在实体中嵌入 PK 类的属性。在这种情况下,属性用@EmbeddedId 标记,PK 类必须用@Embeddable 注释。例如:

@Embeddable
public class EmpPK {
int id;
String name;
...
}

@Entity
public class Employee {
@EmbeddedId EmpPK empId;
...
}

关于java - 我无法让级联在实体 Hibernate 上工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18620754/

相关文章:

java - 有关如何在 GWT 项目中连接到 MS SQL Server 的任何示例或教程

java - Maven2有哪些隐藏特性?

java - 如何使用android媒体记录器输出基本流?

Spring 和 hibernate : Function of annotatedClasses and packagesToScan

java - 动态继承 - Java

java - 如何检测ThreadPool中是否有空闲线程?

java - 无法在 Struts 中加载配置

java - 无法解决 DataAccessException。它是从所需的 .class 文件中间接引用的

java - 将外部属性放入命名查询中

java - 如何处理一个表的外键映射到多个表的主键?