I've researched a lot, but none of the solutions I tried to implement worked... I have the class below, which has many #JoinColumn #ManyToOne relations:
public class Consultas implements Serializable {
#Basic(optional = false)
#Column(name = "status")
private boolean status;
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Basic(optional = false)
#Column(name = "idconsultas")
private Integer idconsultas;
#Basic(optional = false)
#Column(name = "data_consulta")
#Temporal(TemporalType.DATE)
private Date dataConsulta;
#Basic(optional = false)
#Column(name = "hora_consulta")
#Temporal(TemporalType.TIME)
private Date horaConsulta;
#JoinColumn(name = "idforma_pagamento", referencedColumnName = "idforma_pagamento")
#ManyToOne(optional = false)
private FormaPagamento idformaPagamento;
#JoinColumn(name = "idfuncionario", referencedColumnName = "idfuncionario")
#ManyToOne(optional = false)
private Funcionario idfuncionario;
#JoinColumn(name = "idpaciente", referencedColumnName = "idpaciente")
#ManyToOne(optional = false)
private Paciente idpaciente;
#JoinColumn(name = "idplano", referencedColumnName = "idplano")
#ManyToOne(optional = false)
private Plano idplano;
When I try to map an instance of this class with the code below, coming from an interface:
JSON.generateJSON(this.consultas, Consultas.class);
The generateJSON method:
public static String generateJSON(Object o, Class valueType)
{
if (valueType == Consultas.class) {
Consultas k = (Consultas) o;
mapper.writeValue(json, k);
}
The output file also brings EVERY attribute from the #JoinColumn#ManyToOne relations (i.e every attribute from the class "Plano","Paciente","FormaPagamento" and "Funcionario"). Why is it mapping all the attributes instead of only the "id" contained inside the Consultas class?
My problem is that I want to write as JSON simply the attributes from the Consultas class, without any additional attributes from its relations.
Maybe it already has an answer, but I couldn't find a proper solution at all. Thanks in advance
Related
I have an entity like Process, which will be created by , updated by one user. When I try to apply the filter. I have created the foreign key relationship in the database. Now, when I use the JPA Specification to apply dynamic filter, I am getting exception as
No property CREATED found for type Process!
#Table(name = "process")
#Entity
public class Process {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "PROCESS_ID")
#JsonProperty("id")
private Long id = null;
#NotNull
#Column(name = "NAME")
#JsonProperty("name")
private String name = null;
#Column(name = "CREATED_BY", updatable = false)
#JsonProperty("createdBy")
private Long createdBy = null;
#Column(name = "updatedBy", nullable = true)
#JsonProperty("updatedBy")
private Long updatedBy = null;
}
Hence, I Added the entity relationship mapping in the process entity as given below,
Now, I am getting below error. I am new to JPA and hibernate, the relation mapping is very confusing, kindly help.
#Table(name = "process")
#Entity
public class Process {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "PROCESS_ID")
#JsonProperty("id")
private Long id = null;
#NotNull
#Column(name = "NAME")
#JsonProperty("name")
private String name = null;
#Column(name = "CREATED_BY", updatable = false)
#JsonProperty("createdBy")
private Long createdBy = null;
#Column(name = "updatedBy", nullable = true)
#JsonProperty("updatedBy")
private Long updatedBy = null;
//newly added below properties so that there will be no error when fetching data
#OneToOne(targetEntity = UserDetails.class, fetch = FetchType.LAZY, mappedBy = "id")
private UserDetails CREATED;
#OneToOne(targetEntity = UserDetails.class, fetch = FetchType.LAZY, mappedBy = "id")
private UserDetails UPDATED;
}
Now, I am getting the below error
Referenced property not a (One|Many)ToOne: com.app.users.details.domain.UserDetails.id in mappedBy of com.app.scenarios.domain.Process.CREATED
Kindly let me know what i am doing wrong. I have a process which can be created by a user and can be updated by a user. In DB, I am having a foreign key relationship for process and userdetails entity.
EDIT
Code to get the filtered data from DB using JPA Specification
Page<process> result = this.processDao.findAll(getprocessGridData(processSearchCondition.getprocessName()), pageRequest);
private static Specification<process> getprocessGridData(String processName) {
return (Specification<process>) (root, query, criteriaBuilder) -> (
criteriaBuilder.like(root.get("name"), processName)
);
}
I guess what you actually want is this:
#Table(name = "process")
#Entity
public class Process {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "PROCESS_ID")
#JsonProperty("id")
private Long id;
#NotNull
#Column(name = "NAME")
#JsonProperty("name")
private String name;
#OneToOne(fetch = FetchType.LAZY)
#jOINColumn(name = "CREATED_BY", updatable = false)
private UserDetails createdBy;
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "UPDATED_BY", nullable = true)
private UserDetails updatedBy;
}
I'm trying to add a new Object to the h2-memory data base with POST Rest API.
I got this error : nested exception is org.hibernate.exception.ConstraintViolationException
In my Expense Entity I had put #ManyToOne(cascade=CascadeType.ALL) so it's not supposed to create the category object before creating the expense object , isn't?
Thanks in advance.
Here is my entites:
public class Expense {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id", updatable = false, nullable = false)
private Long id;
private String description;
#Column(name = "expense_date")
private Instant expenseDate;
#Column(name = "location")
private String location;
#ManyToOne(cascade={CascadeType.ALL})
#Nullable
#JoinColumn(name = "category_id", referencedColumnName = "id", nullable = false)
private Category category;
#ManyToOne(cascade=CascadeType.ALL)
#JoinColumn(name = "user_id", referencedColumnName = "id", nullable = false)
#Nullable
#JsonIgnore
private User user;}
Category Class
public class Category {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id", updatable = false, nullable = false)
private Long id;
#NonNull
private String name;}
User Class:
public class User {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id", updatable = false, nullable = false)
private Long id;
private String name;
private String email;}
You have an error in your definition of Expense class.
The annotation #Nullable - allows NULL values, and nullable = false - don`t allow.
Problem solved when I removed nullable=false from #JoinColumn. because in Post method , I did not provide the id because it's generated so it's theorically nullable
We have a Java ee application running on JBoss 6.4 GA using JPA and Hibernate with the following entities:
#Entity
#SequenceGenerator(name = "sequence", sequenceName="SEQ_CAMPAIGNS_ID",allocationSize = 1)
#Table(name = "CAMPAIGN")
public class CampaignEntity implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "sequence")
#Column(name = "ID")
private Long id;
#Column(name = "NAME")
private String name;
#Column(name = "IS_ACTIVE", nullable = false)
private boolean active;
#Column(name = "START_DATE", nullable = false)
private Date startDate;
#Column(name = "END_DATE", nullable = false)
private Date endDate;
#Column(name = "LEGAL_ENTITY_ID", nullable = false)
private Integer legalEntityId;
#Column(name = "DEPARTMENT", nullable = false)
#Enumerated(value = EnumType.STRING)
private Department department;
#Column(name = "CATEGORY", nullable = false)
#Enumerated(value = EnumType.STRING)
private Category category;
#Embedded
CampaignConditionsEntity campaignConditions;
#OneToMany(cascade = CascadeType.ALL, mappedBy = "campaign", orphanRemoval = true)
#OrderBy
private List<CodeEntity> campaignCodes;
public CampaignEntity() {
}
And the following CampaignConditionsEntity:
#Embeddable
public class CampaignConditionsEntity implements Serializable {
private static final String CAMPAIGN_ID = "CAMPAIGN_ID";
#ElementCollection(fetch = FetchType.EAGER)
#CollectionTable(name = "CAMPAIGN_COND_TRIP_TYPE", joinColumns = #JoinColumn(name = CAMPAIGN_ID))
private Set<TripTypeConditionEntity> tripTypeConditions;
And the following CodeEntity:
#Entity
#Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
#SequenceGenerator(name = "sequence", sequenceName = "SEQ_CODES_ID", allocationSize = 1)
public abstract class CodeEntity implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "sequence")
#Column(name = "ID", nullable = false)
private Long id;
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "CAMPAIGN_ID")
private CampaignEntity campaign;
#OneToOne(mappedBy = "code", cascade = CascadeType.ALL, fetch = FetchType.LAZY, optional = false, orphanRemoval = true)
private DiscountEntity discount;
#Column(name = "MAX_USAGES", nullable = false)
private Integer maxUsages;
#Column(name = "UNLIMITED_USAGES", nullable = false)
private boolean unlimitedUsages;
#Column(name = "NEGATIVE_SH", nullable = false)
private boolean negativeSH;
#Column(name = "UNIQUE_BUYER", nullable = false)
private boolean uniqueBuyer;
#Column(name = "START_DATE")
private Date startDate;
#Column(name = "END_DATE")
private Date endDate;
#Embedded
private CodeConditionsEntity codeConditions;
public CodeEntity() {
}
This is the CodeConditionsEntity:
#Embeddable
public class CodeConditionsEntity implements Serializable {
private static final String CODE_ID = "CODE_ID";
#ElementCollection(fetch = FetchType.EAGER)
#CollectionTable(name = "CODE_COND_TRIP_TYPE", joinColumns = #JoinColumn(name = CODE_ID))
private Set<TripTypeConditionEntity> tripTypeConditions;
#ElementCollection(fetch = FetchType.EAGER)
#CollectionTable(name = "CODE_COND_CARRIERS", joinColumns = #JoinColumn(name = CODE_ID))
private Set<CarrierConditionEntity> carrierConditions;
This is the CarrierConditionEntity:
#Embeddable
public class CarrierConditionEntity implements Serializable {
#Column(name = "CARRIER", nullable = false, length = 3)
private String carrierCode;
#Column(name = "IS_INCLUDED", nullable = false)
private boolean included;
The problem is that in the logs we are finding unexpected deletes when the only operation that we are doing are finds of particular campaign entities.
In the production logs we find the following deletes
Hibernate: delete from CODE_COND_CARRIERS where CODE_ID=? and CARRIER=? and IS_INCLUDED=?
do you have any suggestion?
thanks
I have some suggestions :)
Be aware of what is a Persistence Context (EntityManager instance in JPA terminology / Session in Hibernate one), the entity lifecycle and transaction scope (unit of work)
Do not mutate entity state if you don't expect the changes to be reflected in database, or at least detach the entity before mutating it.
Mark your transaction as "readOnly" if you only fetch data in the related unit of work. (beware that if you have many "Transactional" methods joining the same physical transaction, the flag is set by the surrounding one and cannot be overridden by inner logical transactions). That way the EntityManager won't be flushed at the end of the transaction and pending changes won't be persisted to the database.
You can track the method triggering the unexpected deletion using an EntityListener on the related entity and printing the current strackTrace (new Throwable().printStackTrace()/ log(new Throwable()) in the PreRemove method
I found where was the problem:
The problem was that the Entities didn't have the equals() and the hashcode() implemented. Also there were entities that have a #PostLoad that modified the entity after loading it from database. Then in this situation Hibernate though that there was a change in those entities that didn't have the equals and the hashcode, and then it delete all of them and inserted again in the database (to have the same entities before the query)
Adding the equals and hashcode methods and deleting postload removed the unexpected deletes and inserts from the logs.
regards
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
I have a web-service with Java class files that have been generated with NetBeans based on the database schema I have.
I get strange exceptions sometimes and one of them is this one:
javax.xml.ws.WebServiceException: javax.xml.bind.MarshalException
- with linked exception:
[com.sun.istack.internal.SAXException2: A cycle is detected in the object graph. This will cause infinitely deep XML: org.mylib.Person[ personId=1 ] ->org.mylib.TeamPerson[ teamPersonPK=org.mylib.teamPersonPK[ teamId=1, personId=1 ] ] -> org.mylib.Person[ personId=1 ]]
I have googled this exception and found some simillar cases but I still cannot understand the problem. I have just generated those classes (Person.java, Team.java, TeamPerson.java) with NetBeans so how can the problem occur?
This happens when I try to get all Persons:
Iterator iter = team.getTeamPersonCollection().iterator();
while(iter.hasNext()) {
Person person = ((TeamPerson)iter.next()).getPerson();
...
}
EDIT
If I remove the Team reference from TeamPerson I get the following error:
Internal Exception: Exception [EclipseLink-7154] (Eclipse Persistence Services - 2.2.0.v20110202-r8913): org.eclipse.persistence.exceptions.ValidationException
Exception Description: The attribute [teamPersonCollection] in entity class [class org.mylib.Team] has a mappedBy value of [team] which does not exist in its owning entity class [org.mylib.TeamPerson]. If the owning entity class is a #MappedSuperclass, this is invalid, and your attribute should reference the correct subclass.
at org.eclipse.persistence.exceptions.PersistenceUnitLoadingException.exceptionSearchingForPersistenceResources(PersistenceUnitLoadingException.java:126)
EDIT 2
Parts of the generated classes looks like this:
Team.java
public class Team implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#Basic(optional = false)
#Column(name = "team_id")
private Integer teamId;
#Column(name = "type")
private String type;
#OneToMany(cascade = CascadeType.ALL, mappedBy = "team")
private Collection<TeamPerson> teamPersonCollection;
Person.java
public class Person implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#Basic(optional = false)
#Column(name = "person_id")
private Integer personId;
#Column(name = "name")
private String name;
#OneToMany(cascade = CascadeType.ALL, mappedBy = "person")
private Collection<TeamPerson> teamPersonCollection;
TeamPerson.java
public class TeamPerson implements Serializable {
private static final long serialVersionUID = 1L;
#EmbeddedId
protected TeamPersonPK teamPersonPK;
#Basic(optional = false)
#Column(name = "timestamp")
#Temporal(TemporalType.TIMESTAMP)
private Date timestamp;
#JoinColumn(name = "team_id", referencedColumnName = "team_id", insertable = false, updatable = false)
#ManyToOne(optional = false)
private Team team;
#JoinColumn(name = "person_id", referencedColumnName = "person_id", insertable = false, updatable = false)
#ManyToOne(optional = false)
private Person person;
TeamPersonPK.java
#Embeddable
public class TeamPersonPK implements Serializable {
#Basic(optional = false)
#Column(name = "team_id")
private int teamId;
#Basic(optional = false)
#Column(name = "person_id")
private int personId;
The solution is simply to add the annotation : "#XmlTransient" (javax.xml.bind.annotation.XmlTransient) at the getter of the property that causes the cycle.
Well maybe thats is because your Person class contains the field of type TeamPerson and the TeamPerson contains the field of type Person. And the marshaller is confused un parsing such loop init?
UPD. Maybe you need to change this
#OneToMany(cascade = CascadeType.ALL, mappedBy = "team")
private Collection<TeamPerson> teamPersonCollection;
to:
#OneToMany(cascade = CascadeType.ALL, mappedBy = "teamId")
private Collection<TeamPerson> teamPersonCollection;
because field team does not exist in class TeamPerson?