Hibernate One-to-One, When inserting, Why FK is null - java

When I run this code, it is running with out error. But When I check the values, as you can see, In the "Tbl_InstructorDetail" table the parentId is null
can anyone help.
thank you.
This is my Entities and my main class with table relation
enter image description here
this is my tables from my database
create table Tbl_Instructor
(
uuid int identity
constraint Pk_Tbl_Instructor_uuid
primary key,
Title nvarchar(50)
)
create table Tbl_InstructorDetail
(
uuid int identity
constraint Pk_Tbl_InstructorDetail_uuid
primary key,
Created_By nvarchar(50),
parentId int
constraint Fk_Tbl_InstructorDetail_Tbl_Instructor
references Tbl_Instructor
)
#Entity
#Table(name = "Tbl_InstructorDetail", schema = "dbo", catalog = "OJT_2021_KST")
public class TblInstructorDetailEntity {
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Id
#Column(name = "uuid", nullable = false)
private int uuid;
#Basic
#Column(name = "Created_By", nullable = true, length = 50)
private String createdBy;
#Basic
#Column(name = "parentId", nullable = true,insertable = false,updatable = false)
private Integer parentId;
#OneToOne
#JoinColumn(name = "parentId",referencedColumnName="uuid")
private TblInstructorEntity instructorEntity;
#Entity
#Table(name = "Tbl_Instructor", schema = "dbo", catalog = "OJT_2021_KST")
public class TblInstructorEntity {
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Id
#Column(name = "uuid", nullable = false)
private int uuid;
#Basic
#Column(name = "Title", nullable = true, length = 50)
private String title;
#OneToOne(mappedBy="instructorEntity",cascade = CascadeType.ALL)
private TblInstructorDetailEntity detailEntity;
Main class
TblInstructorEntity instructor = new TblInstructorEntity();
instructor.setTitle("This is a Test");
TblInstructorDetailEntity detail = new TblInstructorDetailEntity();
detail.setCreatedBy("Kyle");
instructor.setDetailEntity(detail);
session.getTransaction().begin();
session.save(instructor);
session.getTransaction().commit();

You don't need to add parentId in TblInstructorDetailEntity because it's referenced from TblInstructorEntity. In main class foreign key pass null because you can take a reference to the parent table before save parent table.
Here down is modified code:
Entity
#Entity
#Table(name = "Tbl_InstructorDetail", schema = "dbo", catalog = "OJT_2021_KST")
public class TblInstructorDetailEntity {
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Id
#Column(name = "uuid", nullable = false)
private int uuid;
#Basic
#Column(name = "Created_By", nullable = true, length = 50)
private String createdBy;
// remove parentId column because it is foreign key
#OneToOne
#JoinColumn(name = "parentId",referencedColumnName="uuid")
private TblInstructorEntity instructorEntity;
// getter setter
}
#Entity
#Table(name = "Tbl_Instructor", schema = "dbo", catalog = "OJT_2021_KST")
public class TblInstructorEntity {
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Id
#Column(name = "uuid", nullable = false)
private int uuid;
#Basic
#Column(name = "Title", nullable = true, length = 50)
private String title;
#OneToOne(mappedBy="instructorEntity",cascade = CascadeType.ALL)
private TblInstructorDetailEntity detailEntity;
// getter setter
}
Main
Session session = HibernateUtil.getSessionFactory().openSession();
session.beginTransaction();
TblInstructorEntity instructor = new TblInstructorEntity();
instructor.setTitle("This is a Test");
TblInstructorDetailEntity detail = new TblInstructorDetailEntity();
detail.setCreatedBy("Kyle");
session.save(instructor); // Save parent entity
detail.setInstructorEntity(instructor); // Reference from parent entity
session.save(detail); // Save child entity
session.getTransaction().commit();
HibernateUtil.shutdown();

Related

Create record with already prepared key

I have a simple model:
#Entity
#Table(name = "doctor_data")
public class DoctorData {
#Id
#GeneratedValue(strategy = GenerationType.SEQUENCE)
#Column(name = "doctor_id")
private int id;
#Column(name = "first_name", nullable = false)
private String docName;
#ManyToOne
#JoinColumn(name = "user_id")
#JsonBackReference
private User user;
}
How can I pass the prepared value in "user_id" foreign key due DTO, or simple post request?

Error relationship persistence using Spring Data JPA in a many to one

I have the following code for many to many or many to one relationship persistence using Spring JPA.
This is my repository test https://github.com/Truebu/testJpa.git
This class has three one-to-many relationships, but none work well
#Entity(name = "routine_assignament")
#Table(name = "routine_assignament")
public class RoutineAssignament {
#Id
#GeneratedValue(strategy = IDENTITY)
#Column(name = "id", updatable = false)
private Long id;
#Column(name = "date_start",nullable = true,columnDefinition = "DATE")
private Date date_start = new Date();
#Column(name = "date_end",nullable = true,columnDefinition = "DATE")
private Date date_end;
#ManyToOne
#JoinColumn(name = "id_user")
private User user;
#ManyToOne
#JoinColumn(name = "id_routine")
private Routine routine;
#OneToMany(mappedBy = "routine_assignament")
private Set<Score> scores = new HashSet<>();
#OneToMany(mappedBy = "routine_assignament")
private Set<Statistic> statistics = new HashSet<>();
#OneToMany(mappedBy = "routine_assignament")
private Set<KeepRoutine> keepRoutines = new HashSet<>();
The other classes
#Entity(name = "score")
#Table(name = "score")
public class Score {
#Id
#GeneratedValue(strategy = IDENTITY)
#Column(name = "id", updatable = false)
private Long id;
#Column(name = "commentary",nullable = false,columnDefinition = "TEXT", unique = true)
private String commentary;
#Column(name = "assessment",nullable = false,columnDefinition = "INT", unique = true)
private String assessment;
#ManyToOne
#JoinColumn(name = "id_routine_assignament")
private RoutineAssignament routineAssignament;
}
#Entity(name = "statistic")
#Table(name = "statistic")
public class Statistic {
#Id
#GeneratedValue(strategy = IDENTITY)
#Column(name = "id", updatable = false)
private Long id;
#Column(name = "time",nullable = false,columnDefinition = "TEXT", unique = true)
private String time;
#ManyToOne
#JoinColumn(name = "id_routine_assignament")
private RoutineAssignament routineAssignament;
}
and
#Entity(name = "keep_routine")
#Table(name = "keep_routine")
public class KeepRoutine {
#Id
#GeneratedValue(strategy = IDENTITY)
#Column(name = "id", updatable = false)
private Long id;
#ManyToOne
#JoinColumn(name = "id_routine_assignament")
private RoutineAssignament routineAssignament;
}
The entity relationship diagram is this:
My mistake is that it doesn't detect these relationships correctly.
When I run it it generates this:
Failed to initialize JPA EntityManagerFactory: mappedBy reference an unknown target entity property: com.example.demo.model.entities.KeepRoutine.routine_assignament in com.example.demo.model.entities.RoutineAssignament.keepRoutines
This error is reproduced with all three classes (KeepRoutine, Statistic and Score), I don't know why
Your OneToMany mapping is not appropriate. You need to use routineAssignament the property name instead of the table name routine_assignament as shown below. This property name is defined in the ManyToOne relationship.
#OneToMany(mappedBy = "routineAssignament")
private Set<Score> scores = new HashSet<>();
#OneToMany(mappedBy = "routineAssignament")
private Set<Statistic> statistics = new HashSet<>();
#OneToMany(mappedBy = "routineAssignament")
private Set<KeepRoutine> keepRoutines = new HashSet<>();

JPA - wrong number of column. should be 2

A Foreign key refering br.com.copagaz.inova.mobile.persistencia.entidade.viagem.nf.NFeProtocolo from br.com.copagaz.inova.mobile.persistencia.entidade.viagem.nf.NfCabeca has the wrong number of column. should be 2
My problem is in one column reference, if i remove #ManyToOne and #JoinColumn(name = "protocolo"), the system works but the selects does not.
i tried to use hibernate.hbm2ddl.auto to auto create the FKs but with no success.
I think the nfe_operacao use a composed PK, and nf_cabeca reference's ii, but did not work.
Any one could help?
#Entity
#Table(name = "nf_cabeca", schema = "mobile", uniqueConstraints =
{#UniqueConstraint(columnNames =
{"NUMERO_FILIAL","serie_nota","numero_nota"})})
public class NfCabeca implements java.io.Serializable {
private static final long serialVersionUID = -921687831233770627L;
#Id
#SequenceGenerator(name = "nf_cabeca_sequencial_seq", sequenceName = "nf_cabeca_sequencial_seq", schema = "mobile", allocationSize = 1, initialValue = 1)
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "nf_cabeca_sequencial_seq")
#Column(name = "sequencial", insertable = false, updatable = false)
private long sequencial;
#Temporal(TemporalType.TIMESTAMP)
#Column(name = "data_hora", nullable = false, length = 29)
private Date dataHora;
#Column(name = "valor_total", nullable = false, precision = 17, scale = 17)
private Double valorTotal;
#Column(name = "cancelada")
private Integer cancelada;
#Temporal(TemporalType.DATE)
#Column(name = "data_vencimento", length = 13)
private Date dataVencimento;
#Column(name = "boleto", length = 17)
private String boleto;
#ManyToOne
#JoinColumn(name = "protocolo")
private NFeProtocolo protocolo;
#Column(name = "chave")
private String chave;
#Column(name = "status_nf")
private Integer statusNf;
#Column(name = "status_danfe")
private Integer statusDanfe;
#Column(name = "modelo", length = 3)
private String modelo;
#Column(name = "reconciliada")
private boolean reconciliada = false;
#OneToMany(mappedBy = "nfCabeca", cascade = CascadeType.MERGE)
private List<NfObservacao> nfObservacao;
#OneToMany(mappedBy = "nfCabeca", cascade = CascadeType.ALL)
private List<NfItens> nfItens;
#OneToMany(cascade = CascadeType.ALL, orphanRemoval = true)
#JoinColumn(name = "nf_cabeca")
private List<NFeProtocolo> protocolos = new ArrayList<NFeProtocolo>();
}
This references this table:
#Entity
#IdClass(NFeProtocoloId.class)
#Table(name = "nfe_protocolo", schema = "mobile")
public class NFeProtocolo implements Serializable {
private static final long serialVersionUID = 2092981840170296102L;
#Id
#Column(name = "nf_cabeca", length = 100, insertable = false, updatable = false)
private long nf_cabeca_id;
#Id
#Column(name = "protocolo", length = 100)
private String protocolo;
#Column(name = "operacao", length = 15, nullable = false)
#Enumerated(EnumType.STRING)
private NFeProtocoloOperacao operacao;
#Temporal(TemporalType.TIMESTAMP)
#Column(name = "data_hora", length = 29, nullable = false)
private Date dataHora;
#Column(name = "status", length = 10)
private String status;
}
I think the problem is that your #ManyToOne mapping is not correctly declared. As the the entity NFeProtocolo has a composite primary key, you should use #JoinColumns annotation that consists of an array of #JoinColumn annotations:
#ManyToOne
#JoinColumns({#JoinColumn(name = "nf_cabeca_id", referncedColumnName="nf_cabeca_id"),
#JoinColumn(name= "protocolo", referencedColumnName="protocolo")})
private NFeProtocolo protocolo;
You can choose an appropriate name as a foreign key column name.
A Foreign key refering br.com.copagaz.inova.mobile.persistencia.entidade.viagem.nf.NFeProtocolo from br.com.copagaz.inova.mobile.persistencia.entidade.viagem.nf.NfCabeca has the wrong number of column. should be 2
Your problem is simple: Your Entity NFeProtocolo has a composite Id with two columns:
public class NFeProtocolo implements Serializable {
#Id
#Column(name = "nf_cabeca", length = 100, insertable = false, updatable = false)
private long nf_cabeca_id;
#Id
#Column(name = "protocolo", length = 100)
private String protocolo;
But your class NfCabeca is referencing it through only one column:
public class NfCabeca implements java.io.Serializable {
#ManyToOne
#JoinColumn(name = "protocolo")
private NFeProtocolo protocolo;
The solution:
A composite primary key is usually made up of two or more primitive or JDK object types.
As you have a composite key, you should use an Embeddable key, there are many examples about it like this, this and this.

Hibernate creating Composite Key instead of using Identifier

I have an Entity FooBar which serves as the #ManyToMany join table for Foo and Bar entities including some additional information.
#Entity
#Table(name = "foo_bar")
public class FooBar
{
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "id", unique = true, nullable = false)
protected Long id;
#Column(name = "someInfo", nullable = true)
private String someInfo;
#ManyToOne(optional = false)
private Foo foo;
#ManyToOne(optional = false)
private Bar bar;
//getters, setters, and toString()
}
#Entity
#Table(name = "foo")
public class Foo
{
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "id", unique = true, nullable = false)
protected Long id;
#OneToMany(mappedBy = "foo", cascade = CascadeType.ALL, fetch = FetchType.EAGER)
private Set<FooBar> fooBars;
//Foo has a number of other fields
#Column(name = "orderIndex", nullable = false)
private int orderIndex;
#Column(name = "upgradeDirection", nullable = false)
#Enumerated(EnumType.STRING)
private Order direction;
#ManyToOne(optional = false)
private SomeEntity e;
//getters, setters, and toString()
}
#Entity
#Table(name = "bar")
public class Bar
{
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "id", unique = true, nullable = false)
protected Long id;
#OneToMany(mappedBy = "bar") //TODO specify a cascade and fetch attribute
private Set<FooBar> fooBars;
//Bar contains a number of other fields
#Column(name = "value", nullable = false)
private String value;
//getters, setters, and toString()
}
When Hibernate creates the table is has columns 'id', 'someInfo', 'foo_id', and 'bar_id'. 'foo_id' and 'bar_id' are used in as a composite key instead of using the 'id' field, any idea why?

Hibernate List Mapping Annotation

Well i have this problem
These are my tables
this is my code for "Compra"
#Entity
#Table(name = "compra")
public class Compra implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "codigo", unique = true, nullable = false)
private int codigo;
#ManyToOne
#JoinColumn(name = "codProveedor", nullable = false)
private Proveedor proveedor;
#Column(name = "tipoComprobante", nullable = false)
private String tipoComprobante;
#Temporal(TemporalType.DATE)
#Column(name = "fechaFactura", nullable = false)
private Date fechaFactura;
#Temporal(TemporalType.DATE)
#Column(name = "fechaLlegada", nullable = false)
private Date fechaLlegada;
#Column(name = "serie", nullable = false)
private String serie;
#Column(name = "numero", nullable = false)
private int numero;
#Column(name = "importe", nullable = false)
private double importe;
#Column(name = "vigencia", nullable = false)
private boolean vigencia = true;
#ElementCollection
private List<DetalleCompra> lstDetalle = new ArrayList<DetalleCompra>();
// getters and setters ...
And this is my code for "DetalleCompra"
#Entity
#Table(name = "detalleCompra")
public class DetalleCompra implements Serializable {
#Id
#GeneratedValue(generator = "gen")
#GenericGenerator(name = "gen", strategy = "foreign", parameters = #Parameter(name = "property", value = "compra"))
#Column(name = "codCompra", nullable = false)
private int codCompra;
#ManyToOne
#JoinColumn(name = "codPresentacion", nullable = false)
private Presentacion presentacion;
#Column(name = "imei", nullable = false)
private String imei;
#Column(name = "simcard", nullable = false)
private String simcard;
getters and setters ...
Well everything looks fine, but when i want to save i have this problem
org.hibernate.TransientObjectException: object references an unsaved transient instance – save the transient instance before flushing: DetalleCompra
well it is clear because when i want to save Compra and DetalleCompra, the second table expect the fk value
public void registrar(Compra compra) {
try {
session = HibernateUtil.getSessionFactory().openSession();
trans = session.beginTransaction();
session.save(compra);
trans.commit();
} catch (Exception e) {
trans.rollback();
throw e;
} finally {
session.close();
}
}
Well the pk of table "compra" is generated well but for the other table does not recognized this value autogenerated, why?, how can i solve that?
#ElementCollection
Defines a collection of instances of a basic type or embeddable class.
Must be specified if the collection is to be mapped by means of a
collection table.
You use wrong annotation to represent relation. There is one to many relation between Compra and DetalleCompra.
You should change #ElementCollection annotation to #OneToMany. Do not forget to specify join columns #JoinColumn(name="codCompra"). I assume that Presentacion is properly mapped.
See also
Unidirectional Mapping vs. Bidirectional Mapping
mappedBy attribute
#OneToMany annotation
#ElementCollection annotation

Categories