我不能让cascade在一个实体上工作,Hibernate

时间:2013-09-04 17:59:27

标签: 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对象也会抛出异常。

这是操纵会话的类(它仅用于测试):

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有多对一关系的实体。

1 个答案:

答案 0 :(得分:0)

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

此外,除非您还定义了包含上述@Id字段的@IdClass,否则不应使用多个@Id注释来定义复合标识。或者你也可以@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;
...
}