Bean validation succeeded but failed on jpa merge method - jpa

I want to persist an entity(MyEntity) with merge method. This entity have some beans validation.
public class MyEntity extends AbstractEntity {
#Basic(optional = false)
#Column(name = "city", length = 255, nullable = false)
#NotNull
#NotEmpty(message = "{myentity.validation.size.name}")
private String city;
private String number;
#Basic(optional = false)
#Column(name = "zipcode", length = 255, nullable = false)
#NotNull
private String zipcode;
private String phoneNumber;
#Email(message = "{myentity.validation.conform.email}")
#Size(min = 2, max = 100, message = "{myentity.validation.size.email}")
private String email;
private String website;
private String gpsLocation;
#ElementCollection()
#CollectionTable(name = "translation_poi", joinColumns = #JoinColumn(name = "point_id"))
#MapKeyJoinColumn(name = "locale")
#NotEmpty
private Map<Locale, MyEntityI18n> translations = new HashMap<>();
}
#Embeddable
public class MyEntityI18n implements java.io.Serializable {
#Basic(optional = false)
#Column(name = "name", length = 255, nullable = false)
#NotNull
#NotEmpty(message = "{myentity.validation.size.name}")
private String name;
#Column(name = "comment", length = 1200)
private String comment;
#Column(name = "short_description", length = 1200)
private String shortDescription;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
The merge succeeded on an existing entity value but with a new entity the merge failed despite the fact that the following validation succeeded.
private boolean validate(MyEntity poi) {
boolean result = true;
Set<ConstraintViolation<MyEntity>> constraintViolations = validator.validate(poi);
if (constraintViolations.size() > 0) {
result = false;
for (ConstraintViolation<MyEntity> constraints : constraintViolations) {
FacesContext context = FacesContext.getCurrentInstance();
String message = constraints.getPropertyPath() + " " + constraints.getMessage();
context.addMessage(null, new FacesMessage(FacesMessage.SEVERITY_WARN, constraints.getMessage(), message));
}
}
return result;
}

Try to add a #Valid to MyEntity.translations property. I think that your validation method hasn't take account the MyEntityI18n.name validation.
About merge fails, Do you have a not-null DB constraint on the MyEntityI18n.name field?
Good luck!

Related

Why is there a loop in #OneToMany mapping?

I am trying to create a #OneToMany database using JPA. There is a object Flight and a object Passenger.
the code:
#Entity
#Table(name = "passengers")
public class Passenger {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
#Column(name = "name")
private String name;
#Column(name = "surname")
private String surname;
private String email;
private String phoneNumber;
private String birthDate;
#ManyToOne(optional = false)
#JoinColumn(name = "flight_id")
private Flight flight;
public Passenger() {
}
public Passenger(String name, String surname, String email, String phoneNumber, String birthDate, Flight flight) {
super();
this.name = name;
this.surname = surname;
this.email = email;
this.phoneNumber = phoneNumber;
this.birthDate = birthDate;
this.flight = flight;
}
#Entity
#Table(name = "flights")
public class Flight {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "flight_id")
private long id;
private String departure;
private String destination;
private String date;
private int capacity;
private float price;
#OneToMany(fetch = FetchType.EAGER, mappedBy = "flight", cascade = CascadeType.ALL)
private Set<Passenger> passengers;
public Flight() {
}
public Flight(String departure, String destination, String date, int capacity, float price) {
super();
this.departure = departure;
this.destination = destination;
this.date = date;
this.capacity = capacity;
this.price = price;
}
this is how I add a new Passenger:
#PostMapping("/flights")
public ResponseEntity<Object> updateFlight(#RequestBody Flight flight) {
long id = flight.getId();
Optional<Flight> flightOptional = flightRepository.findById(id);
if (!flightOptional.isPresent())
return ResponseEntity.notFound().build();
int currentCapacity = flight.getCapacity();
flight.setCapacity(currentCapacity - 1);
for(Passenger passenger : flight.getPassengers()) {
System.out.println(passenger.getName());
}
this.flightRepository.save(flight);
return ResponseEntity.noContent().build();
}
Unfortunately, when I map the flights and passengers, I appear to have a never ending loop. Passengers have the details of the flight and passengers and again flight and then passengers, and so on.
Is there any way I can resolve it? Am I missing anything?
To avoid the cyclic problem Use #JsonManagedReference, #JsonBackReference as below.
Add #JsonManagedReference on Parent class
#JsonManagedReference
#OneToMany(fetch = FetchType.EAGER, mappedBy = "flight", c
ascadee = CascadeType.ALL)
private Set<Passenger> passengers;
Add #JsonBackReference on child class as below
#JsonBackReference
#ManyToOne(optional = false)
#JoinColumn(name = "flight_id")
private Flight flight;

How to filter by faculty name?

I want to implement lazy record loading on a Primefaces DataTable (version 7). I have two entities, one is called Faculties and the other is Careers, which are related. The datatable correctly shows the list of all the races (includes pagination and filtering), the problem I have is that I do not know how to filter the races by the name of a certain faculty, since I do not know how to include the join in the query that I leave then.
Could you guide me on how to solve it please?
Entity Faculties
public class Facultades implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Basic(optional = false)
#Column(name = "idfacultad")
private Integer idfacultad;
#Basic(optional = false)
#NotNull
#Size(min = 1, max = 100)
#Column(name = "nombre")
private String nombre;
#Size(max = 20)
#Column(name = "abreviatura")
private String abreviatura;
#OneToMany(cascade = CascadeType.ALL, mappedBy = "idfacultad")
private List<Carreras> carrerasList;}
Entity Carreras
public class Carreras implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Basic(optional = false)
#Column(name = "idcarrera")
private Integer idcarrera;
#Basic(optional = false)
#NotNull
#Size(min = 1, max = 150)
#Column(name = "nombre")
private String nombre;
#Basic(optional = false)
#NotNull
#Column(name = "tipo")
private int tipo;
#JoinColumn(name = "idfacultad", referencedColumnName = "idfacultad")
#ManyToOne(optional = false)
private Facultades idfacultad;}
Query findByParams
public List<Carreras> findByParams(int start, int size, String sortField, SortOrder sortOrder, Map<String, Object> filters) {
CriteriaBuilder criteriaBuilder = em.getCriteriaBuilder();
CriteriaQuery<Carreras> criteriaQuery = criteriaBuilder.createQuery(Carreras.class);
Root<Carreras> root = criteriaQuery.from(Carreras.class);
CriteriaQuery<Carreras> select = criteriaQuery.select(root);
Join<Carreras, Facultades> facultad = root.join("idfacultad");
if (sortField != null) {
criteriaQuery.orderBy(sortOrder == SortOrder.DESCENDING ? criteriaBuilder.asc(root.get(sortField)) : criteriaBuilder.desc(root.get(sortField)));
}
if (filters != null && filters.size() > 0) {
List<Predicate> predicados = new ArrayList<>();
filters.entrySet().forEach((entry) -> {
String key = entry.getKey();
Object val = entry.getValue();
if (!(val == null)) {
// Construimos la expresion con los predicados que si existan
Expression<String> expresion = root.get(key).as(String.class);
Predicate predicado = criteriaBuilder.like(criteriaBuilder.lower(expresion), "%" + val.toString().toLowerCase() + "%");
predicados.add(predicado);
}
});
if (predicados.size() > 0) {
criteriaQuery.where(criteriaBuilder.and(predicados.toArray(new Predicate[predicados.size()])));
}
}
// Creamos la consulta
TypedQuery<Carreras> consulta = em.createQuery(select);
consulta.setFirstResult(start);
consulta.setMaxResults(size);
return consulta.getResultList();
}
You need to manually check if the filter key equals the Facultades object, and in that case create a predicate on the joined expression that you have already created:
if (key.equals("Facultad")) {
expresion = facultad.get("nombre").as(String.class);
} else {
expresion = root.get(key).as(String.class);
}

hibernate envers throw entity not found exception, when audit table doesn't have record with ID

Account Entity
#Getter
#Accessors(chain = true, fluent = true)
#NoArgsConstructor
#AllArgsConstructor(staticName = "of")
#ToString(of = {"customerName"}, callSuper = true)
#Entity
#Table(name = "ACCOUNTS",
uniqueConstraints = #UniqueConstraint(name = UNQ_CUSTOMER_NAME, columnNames = { "CUSTOMER_NAME" }),
indexes = {
#Index(name = IDX_CUSTOMER_ENTITY, columnList = "CUSTOMER_ENTITY")
}
)
public class Account extends BaseAutoAssignableVersionableEntity<String, Long> implements Diffable<Account> {
public static final String CUSTOMER_ENTITY = "Customer Entity";
public static final String CUSTOMER_REPORTING_MANAGER = "Customer Reporting Manager";
public static final String CUSTOMER_NAME = "Customer Name";
public static final String ACCOUNT_MANAGER = "Account Manager";
public static final String CITY = "City";
public static final String CUSTOMER_TIME_TRACKING = "Customer Time Tracking";
#NotNull
#Column(name = "CUSTOMER_NAME", nullable = false, length = 150)
#Audited(withModifiedFlag = true)
private String customerName; // Unique
#NotNull
#Size(min = 1, max = 4)
#Column(name = "CUSTOMER_GROUP", nullable = false, length = 4)
#Audited(withModifiedFlag = true)
private String customerGroup;
// #NotNull
#Column(name = "CUSTOMER_ENTITY", nullable = true, length = 150)
#Audited(withModifiedFlag = true)
private String customerEntity; // customer entity is optional and can be same for multiple accounts
#NotNull
#Column(name = "CUSTOMER_REPORTING_MANAGER", nullable = false, length = 150)
#Audited(withModifiedFlag = true)
private String customerReportingManager;
#Column(name = "CUSTOMER_TIME_TRACKING", length = 1)
#Audited(withModifiedFlag = true)
private boolean customerTimeTracking = false;
#NotNull
#OneToOne(fetch = FetchType.EAGER, optional = false)
#JoinColumn(name = "ACCOUNT_MANAGER_CODE", unique = false, nullable = false, foreignKey = #ForeignKey(name = FK_ACCOUNTS_MGR_RESOURCE_CODE))
#Audited(withModifiedFlag = true, targetAuditMode = RelationTargetAuditMode.NOT_AUDITED, modifiedColumnName = "ACCOUNT_MANAGER_CODE_MOD")
private Resource accountManager;
Resource Entity
#Getter
#Accessors(chain = true, fluent = true)
#NoArgsConstructor
#ToString(of = { "name" }, callSuper = true)
#Entity
// #formatter:off
#Table(name = "RESOURCES",
uniqueConstraints = {
#UniqueConstraint(name = UNQ_RESOURCES_LOGIN_ID, columnNames = {"LOGIN_ID"}),
#UniqueConstraint(name = UNQ_RESOURCES_EMAIL_ID, columnNames = {"EMAIL_ID"}),
#UniqueConstraint(name = UNQ_RESOURCES_PAYROLL_ID, columnNames = {"PAYROLL_ID"})
},
indexes = {
#Index(name = IDX_RESOURCES_NAME, columnList = "NAME")
}
)
// #formatter:on
public class Resource extends BaseAutoAssignableVersionableEntity<String, Long> implements Diffable<Resource> {
public static final String EMAIL_ID = "Email ID";
public static final String GRAYT_HR_ID = "Grayt HR ID";
public static final String NAME = "Name";
public static final String GENEDER = "Gender";
public static final String DESIGNATION = "Designation";
public static final String TYPE_OF_RESOURCE = "Resource Type";
public static final String STATUS_OF_RESOURCE = "Resource Status";
public static final String BASE_LOCATION = "Base Location";
public static final String DEPUTED_LOCATION = "Deputed Location";
public static final String PRIMARY_SKILLS = "Primary Skills";
public static final String SECONDARY_SKILLS = "Secondary Skills";
public static final String EXPECTED_JOINING_DATE = "Expected Joining Date";
public static final String ACTUAL_JOINING_DATE = "Actual Joining Date";
public static final String EXIST_DATE = "Exist Date";
// #Pattern(regexp = REGEX_LOGIN_ID, message = MESSAGE_LOGIN_ID_INVALID)
// #NotNull(message = MESSAGE_LOGIN_ID_MANDATORY)
#Column(name = "LOGIN_ID", nullable = false, length = 100)
private String loginId;
#Email(message = MESSAGE_EMAIL_INVALID)
#Column(name = "EMAIL_ID", nullable = true, length = 255)
#Audited(withModifiedFlag = true)
private String emailId;
#Pattern(regexp = REGEX_PAYROLL_ID, message = MESSAGE_PAYROLL_ID_INVALID)
#Column(name = "PAYROLL_ID", nullable = true, length = 100)
#Audited(withModifiedFlag = true, modifiedColumnName = "PAYROLL_ID_MOD")
private String payrollId;
#NotNull
#Column(name = "NAME", nullable = false, length = 255)
#Audited(withModifiedFlag = true)
private String name;
#NotNull
#Enumerated(EnumType.STRING)
#Column(name = "GENDER", nullable = false, length = 10)
#Audited(withModifiedFlag = true)
private Gender gender;
#NotNull
#OneToOne(fetch = FetchType.EAGER, optional = false)
#JoinColumn(name = "DESIGNATION_ID", unique = false, nullable = false, foreignKey = #ForeignKey(name = FK_RESOURCES_DESIGNATION_ID))
#Audited(withModifiedFlag = true, targetAuditMode = RelationTargetAuditMode.NOT_AUDITED, modifiedColumnName = "DESIGNATION_ID_MOD")
private Designation designation;
#NotNull
#OneToOne(fetch = FetchType.EAGER, optional = false)
#JoinColumn(name = "EMP_TYPE_CODE", unique = false, nullable = false, foreignKey = #ForeignKey(name = FK_RESOURCES_EMP_TYPE_CODE))
#Audited(withModifiedFlag = true, targetAuditMode = RelationTargetAuditMode.NOT_AUDITED, modifiedColumnName = "EMP_TYPE_CODE_MOD")
private EmploymentType employmentType;
public boolean isFTE() {
return (this.employmentType.equals(EmploymentType.fullTimeEmployee()));
}
#Audited(withModifiedFlag = true, modifiedColumnName = "EMP_STATUS_ID_MOD")
#OneToOne(optional = false, cascade = CascadeType.PERSIST, orphanRemoval = true)
#JoinColumn(name = "emp_status_id", unique = false, foreignKey = #ForeignKey(name = FK_RESOURCES_EMP_STATUS_ID))
private EmploymentStatus employmentStatus;
When i'm creating the account, used the existing resource as account manager and created successfully. Then fetch the history successfully. But unfortunately deleted the resource record in resource_aud table, then fetch the history. It's throwing below error
javax.persistence.EntityNotFoundException: Unable to find com.gspann.itrack.domain.model.staff.Resource with id IN10000
at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl$JpaEntityNotFoundDelegate.handleEntityNotFound(EntityManagerFactoryBuilderImpl.java:159)
at org.hibernate.proxy.AbstractLazyInitializer.checkTargetState(AbstractLazyInitializer.java:244)
at org.hibernate.proxy.AbstractLazyInitializer.initialize(AbstractLazyInitializer.java:166)
at org.hibernate.proxy.AbstractLazyInitializer.getImplementation(AbstractLazyInitializer.java:268)
at org.hibernate.proxy.pojo.javassist.JavassistLazyInitializer.invoke(JavassistLazyInitializer.java:73)
at com.gspann.itrack.domain.model.staff.Resource_$$_jvst4e_12.name(Resource_$$_jvst4e_12.java)
at com.gspann.itrack.domain.model.business.Account.diff(Account.java:328)
at com.gspann.itrack.domain.model.business.Account.diff(Account.java:1)
at com.gspann.itrack.domain.model.common.audit.util.AuditQueryUtils.getAllRevisionById(AuditQueryUtils.java:66)
at com.gspann.itrack.domain.service.impl.AccountManagementServiceImpl.getAllRevisionByAccountCode(AccountManagementServiceImpl.java:268)
below is the query generated by hibernate envers
/* select
e__,
r
from
com.gspann.itrack.domain.model.business.Account_AUD e__,
com.gspann.itrack.audit.domain.CustomRevisionEntity r
where
e__.REVTYPE <> :_p0
and e__.originalId.code = :_p1
and e__.originalId.REV.id = r.id
order by
e__.originalId.REV.id asc */ select
account_au0_.code as code1_1_0_,
account_au0_.rev as rev2_1_0_,
customrevi1_.id as id1_49_1_,
account_au0_.revtype as revtype3_1_0_,
account_au0_.customer_entity as customer4_1_0_,
account_au0_.customer_entity_mod as customer5_1_0_,
account_au0_.customer_group as customer6_1_0_,
account_au0_.customer_group_mod as customer7_1_0_,
account_au0_.customer_name as customer8_1_0_,
account_au0_.customer_name_mod as customer9_1_0_,
account_au0_.customer_reporting_manager as custome10_1_0_,
account_au0_.customer_reporting_manager_mod as custome11_1_0_,
account_au0_.customer_time_tracking as custome12_1_0_,
account_au0_.customer_time_tracking_mod as custome13_1_0_,
account_au0_.account_manager_code as account14_1_0_,
account_au0_.account_manager_code_mod as account15_1_0_,
account_au0_.country_code as country16_1_0_,
account_au0_.country_code_mod as country17_1_0_,
customrevi1_.last_modified_on as last_mod2_49_1_,
customrevi1_.modified_by as modified3_49_1_,
customrevi1_.timestamp as timestam4_49_1_
from
accounts_aud account_au0_ cross
join
revinfo customrevi1_
where
account_au0_.revtype<>?
and account_au0_.code=?
and account_au0_.rev=customrevi1_.id
order by
account_au0_.rev asc
after calling getter method of resource it's generating another resource related query like below
/* select
e__
from
com.gspann.itrack.domain.model.staff.Resource_AUD e__
where
e__.originalId.REV.id = (
select
max(e2__.originalId.REV.id)
from
com.gspann.itrack.domain.model.staff.Resource_AUD e2__
where
e2__.originalId.REV.id <= :revision
and e__.originalId.code = e2__.originalId.code
)
and e__.REVTYPE <> :_p0
and e__.originalId.code = :_p1 */ select
resource_a0_.code as code1_48_,
resource_a0_.rev as rev2_48_,
resource_a0_.revtype as revtype3_48_,
resource_a0_.actual_joining_date as actual_j4_48_,
resource_a0_.actual_joining_date_mod as actual_j5_48_,
resource_a0_.email_id as email_id6_48_,
resource_a0_.email_id_mod as email_id7_48_,
resource_a0_.exit_date as exit_dat8_48_,
resource_a0_.exit_date_mod as exit_dat9_48_,
resource_a0_.gender as gender10_48_,
resource_a0_.gender_mod as gender_11_48_,
resource_a0_.name as name12_48_,
resource_a0_.name_mod as name_mo13_48_,
resource_a0_.payroll_id as payroll14_48_,
resource_a0_.payroll_id_mod as payroll15_48_,
resource_a0_.utilization as utiliza16_48_,
resource_a0_.utilization_mod as utiliza17_48_,
resource_a0_.utilization_type as utiliza18_48_,
resource_a0_.utilization_type_mod as utiliza19_48_,
resource_a0_.base_loc_id as base_lo20_48_,
resource_a0_.base_loc_id_mod as base_lo21_48_,
resource_a0_.deputed_loc_id as deputed22_48_,
resource_a0_.deputed_loc_id_mod as deputed23_48_,
resource_a0_.designation_id as designa24_48_,
resource_a0_.designation_id_mod as designa25_48_,
resource_a0_.emp_status_id as emp_sta26_48_,
resource_a0_.emp_status_id_mod as emp_sta27_48_,
resource_a0_.emp_type_code as emp_typ28_48_,
resource_a0_.emp_type_code_mod as emp_typ29_48_,
resource_a0_.image_id as image_i30_48_,
resource_a0_.image_id_mod as image_i31_48_
from
resources_aud resource_a0_
where
resource_a0_.rev=(
select
max(resource_a1_.rev)
from
resources_aud resource_a1_
where
resource_a1_.rev<=?
and resource_a0_.code=resource_a1_.code
)
and resource_a0_.revtype<>?
and resource_a0_.code=?
below is the code to fetch the revisions
AuditReader auditReader = this.getAuditReader();
return auditReader.createQuery().forRevisionsOfEntity(clazz, selectedEntitiesOnly, selectDeletedEntities);
My question is, why it's referring to audit table instead of main table?
Thank in advance

JPA merge does insert new entity instead of update existing one

It seems like that when I update my existing entity using jpa merge, it does insert entity with same id instead of updating existing one expected. Because after insertion, database row order lost. But I still have same entities with same ids, does Jpa use insertion to update? I mean does it delete existing entity and insert again with updated value to do its update job. Main chaos is database order is lost then.
Here is my listener method: userService Is EJB class within I use JPA.
public void onEditUserOrganization(RowEditEvent event){
UserOrganization uorg =(UserOrganization) event.getObject();
try {
userService.updateUserOrganization(uorg);
} catch (UserException ex) {
ex.printStackTrace();
FacesContext.getCurrentInstance().addMessage(null, new FacesMessage("error)"));
}finally{
parentlist = getUserOrganizationParents();
branchlist = getUserOrganizationBranches();
}
}
Here is my main update method
#Override
public void updateUserOrganization(UserOrganization org) throws UserException{
if(org != null && !em.contains(org)){
try{
UserOrganization existing = em.find(UserOrganization.class, org.getUorgId());
existing.setOrgcode(org.getOrgcode());
existing.setOrgname(org.getOrgname());
existing.setParent(org.getParent());
}catch(Exception e){
throw new UserException("Couldn't update user org with id " + org.getUorgId());
}
}
}
Here is my entity class:
public class UserOrganization implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Basic(optional = false)
#NotNull
#Column(name = "uorg_id", nullable = false)
private Integer uorgId;
#Basic(optional = false)
#NotNull
#Column(name = "parent", nullable = false)
private short parent;
#Basic(optional = false)
#NotNull
#Size(min = 1, max = 10)
#Column(name = "orgcode", nullable = false, length = 10)
private String orgcode;
#Basic(optional = false)
#NotNull
#Size(min = 1, max = 150)
#Column(name = "orgname", nullable = false, length = 150)
private String orgname;
#OneToMany(cascade = CascadeType.ALL, mappedBy = "uorgId")
private List<refMain> refList;
#OneToMany(cascade = CascadeType.ALL, mappedBy = "uorgId")
private List<User1> user1List;
#OneToMany(cascade = CascadeType.ALL, mappedBy = "userOrganization")
private List<Bankrelation> relationList;
public UserOrganization() {
}
//getter setters..
#Override
public boolean equals(Object object) {
// TODO: Warning - this method won't work in the case the id fields are not set
if (!(object instanceof UserOrganization)) {
return false;
}
UserOrganization other = (UserOrganization) object;
if ((this.uorgId == null && other.uorgId != null) || (this.uorgId != null && !this.uorgId.equals(other.uorgId))) {
return false;
}
return true;
}
#Override
public String toString() {
return "mn.bs.crasmon.model.UserOrganization[ uorgId=" + uorgId + " ]";
}
What is the best way to do update In JPA

how to start from "0" an UNSIGNED AUTO_INCREMENT field?

I have the following tables :
wherein idclient is unsigned auto_increment.
code of the Client entity:
import java.io.Serializable;
import java.util.List;
import javax.persistence.*;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlTransient;
#Entity
#Table(name = "CLIENT", catalog = "TEST", schema = "PUBLIC")
#XmlRootElement
#NamedQueries({
#NamedQuery(name = "Client.findAll", query = "SELECT c FROM Client c"),
#NamedQuery(name = "Client.findByIdclient", query = "SELECT c FROM Client c WHERE c.idclient = :idclient"),
#NamedQuery(name = "Client.findByLibel", query = "SELECT c FROM Client c WHERE c.libel = :libel"),
#NamedQuery(name = "Client.findByAdresse", query = "SELECT c FROM Client c WHERE c.adresse = :adresse"),
#NamedQuery(name = "Client.findByNomResp", query = "SELECT c FROM Client c WHERE c.nomResp = :nomResp"),
#NamedQuery(name = "Client.findByTelPortable", query = "SELECT c FROM Client c WHERE c.telPortable = :telPortable"),
#NamedQuery(name = "Client.findByTelFixe", query = "SELECT c FROM Client c WHERE c.telFixe = :telFixe"),
#NamedQuery(name = "Client.findByFax", query = "SELECT c FROM Client c WHERE c.fax = :fax"),
#NamedQuery(name = "Client.findByCodeTva", query = "SELECT c FROM Client c WHERE c.codeTva = :codeTva"),
#NamedQuery(name = "Client.findByCodeExo", query = "SELECT c FROM Client c WHERE c.codeExo = :codeExo"),
#NamedQuery(name = "Client.findByBanque", query = "SELECT c FROM Client c WHERE c.banque = :banque"),
#NamedQuery(name = "Client.findByRib", query = "SELECT c FROM Client c WHERE c.rib = :rib"),
#NamedQuery(name = "Client.findByCredit", query = "SELECT c FROM Client c WHERE c.credit = :credit"),
#NamedQuery(name = "Client.findByEchance", query = "SELECT c FROM Client c WHERE c.echance = :echance"),
#NamedQuery(name = "Client.findByMail", query = "SELECT c FROM Client c WHERE c.mail = :mail"),
#NamedQuery(name = "Client.findByEtat", query = "SELECT c FROM Client c WHERE c.etat = :etat")})
public class Client implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Basic(optional = false)
#Column(name = "IDCLIENT", nullable = false)
private Integer idclient;
#Basic(optional = false)
#Column(name = "LIBEL", nullable = false, length = 100)
private String libel;
#Basic(optional = false)
#Column(name = "ADRESSE", nullable = false, length = 100)
private String adresse;
#Basic(optional = false)
#Column(name = "NOM_RESP", nullable = false, length = 60)
private String nomResp;
#Basic(optional = false)
#Column(name = "TEL_PORTABLE", nullable = false, length = 16)
private String telPortable;
#Basic(optional = false)
#Column(name = "TEL_FIXE", nullable = false, length = 16)
private String telFixe;
#Basic(optional = false)
#Column(name = "FAX", nullable = false, length = 16)
private String fax;
#Basic(optional = false)
#Column(name = "CODE_TVA", nullable = false, length = 30)
private String codeTva;
#Basic(optional = false)
#Column(name = "CODE_EXO", nullable = false, length = 30)
private String codeExo;
#Basic(optional = false)
#Column(name = "BANQUE", nullable = false, length = 60)
private String banque;
#Basic(optional = false)
#Column(name = "RIB", nullable = false, length = 22)
private String rib;
#Basic(optional = false)
#Column(name = "CREDIT", nullable = false)
private double credit;
#Basic(optional = false)
#Column(name = "ECHANCE", nullable = false)
private int echance;
#Basic(optional = false)
#Column(name = "MAIL", nullable = false, length = 70)
private String mail;
#Basic(optional = false)
#Column(name = "ETAT", nullable = false)
private char etat;
#OneToMany(cascade = CascadeType.ALL, mappedBy = "clientIdclient")
private List<Facture> factureList;
#OneToMany(cascade = CascadeType.ALL, mappedBy = "clientIdclient")
private List<FactProforma> factProformaList;
#OneToMany(cascade = CascadeType.ALL, mappedBy = "clientIdclient")
private List<Bl> blList;
public Client() {
}
public Client(Integer idclient) {
this.idclient = idclient;
}
public Client(Integer idclient, String libel, String adresse, String nomResp, String telPortable, String telFixe, String fax, String codeTva, String codeExo, String banque, String rib, double credit, int echance, String mail, char etat) {
this.idclient = idclient;
this.libel = libel;
this.adresse = adresse;
this.nomResp = nomResp;
this.telPortable = telPortable;
this.telFixe = telFixe;
this.fax = fax;
this.codeTva = codeTva;
this.codeExo = codeExo;
this.banque = banque;
this.rib = rib;
this.credit = credit;
this.echance = echance;
this.mail = mail;
this.etat = etat;
}
public Integer getIdclient() {
return idclient;
}
public void setIdclient(Integer idclient) {
this.idclient = idclient;
}
public String getLibel() {
return libel;
}
public void setLibel(String libel) {
this.libel = libel;
}
public String getAdresse() {
return adresse;
}
public void setAdresse(String adresse) {
this.adresse = adresse;
}
public String getNomResp() {
return nomResp;
}
public void setNomResp(String nomResp) {
this.nomResp = nomResp;
}
public String getTelPortable() {
return telPortable;
}
public void setTelPortable(String telPortable) {
this.telPortable = telPortable;
}
public String getTelFixe() {
return telFixe;
}
public void setTelFixe(String telFixe) {
this.telFixe = telFixe;
}
public String getFax() {
return fax;
}
public void setFax(String fax) {
this.fax = fax;
}
public String getCodeTva() {
return codeTva;
}
public void setCodeTva(String codeTva) {
this.codeTva = codeTva;
}
public String getCodeExo() {
return codeExo;
}
public void setCodeExo(String codeExo) {
this.codeExo = codeExo;
}
public String getBanque() {
return banque;
}
public void setBanque(String banque) {
this.banque = banque;
}
public String getRib() {
return rib;
}
public void setRib(String rib) {
this.rib = rib;
}
public double getCredit() {
return credit;
}
public void setCredit(double credit) {
this.credit = credit;
}
public int getEchance() {
return echance;
}
public void setEchance(int echance) {
this.echance = echance;
}
public String getMail() {
return mail;
}
public void setMail(String mail) {
this.mail = mail;
}
public char getEtat() {
return etat;
}
public void setEtat(char etat) {
this.etat = etat;
}
#XmlTransient
public List<Facture> getFactureList() {
return factureList;
}
public void setFactureList(List<Facture> factureList) {
this.factureList = factureList;
}
#XmlTransient
public List<FactProforma> getFactProformaList() {
return factProformaList;
}
public void setFactProformaList(List<FactProforma> factProformaList) {
this.factProformaList = factProformaList;
}
#XmlTransient
public List<Bl> getBlList() {
return blList;
}
public void setBlList(List<Bl> blList) {
this.blList = blList;
}
#Override
public int hashCode() {
int hash = 0;
hash += (idclient != null ? idclient.hashCode() : 0);
return hash;
}
#Override
public boolean equals(Object object) {
// TODO: Warning - this method won't work in the case the id fields are not set
if (!(object instanceof Client)) {
return false;
}
Client other = (Client) object;
if ((this.idclient == null && other.idclient != null) || (this.idclient != null && !this.idclient.equals(other.idclient))) {
return false;
}
return true;
}
#Override
public String toString() {
return "glob.entitys.Client[ idclient=" + idclient + " ]";
}
}
when I try to insert a row into the data base :
Utilisateur user=new Utilisateur(loginActuel);
Client client=new Client(0);// the error comes from here
Facture fact=new Facture(null,new Date());
fact.setClientIdclient(client);
fact.setUtilisateurLogin(user);
FactureJpaController fjc=new FactureJpaController(emf);
fjc.create(fact);
I get this ugly error(but when i set new Client(1) it works well):
Exception in thread "AWT-EventQueue-0" javax.persistence.RollbackException: Exception [EclipseLink-7197] (Eclipse Persistence Services - 2.3.0.v20110604-r9504): org.eclipse.persistence.exceptions.ValidationException
Exception Description: Null or zero primary key encountered in unit of work clone [glob.entitys.Client[ idclient=0 ]], primary key [0]. Set descriptors IdValidation or the "eclipselink.id-validation" property.
how to solve this problem ?
remark: the client idclient = 0 is already inserted in the Database(but manually)
I'd like once and for all overcome this "problem" , how to prevent JPA or H2 Database to start from 0 ?
H2 does allow to use 0 as the primary key. The error message doesn't come from H2.
However, it seems to me that some (older?) version of EclipseLink doesn't allow to use 0.
the client idclient = 0 is already inserted in the Database
It seems this is not supported by this version of EclipseLink. It looks like to work around this problem, you should not use the value 0.
There are two ways how to allow zeroes in primary keys in Eclipselink:
Parameter in persistence.xml:
<property name="eclipselink.id-validation" value="NULL"/>
PrimaryKey annotation on concerned entity class:
#PrimaryKey(validation = IdValidation.NULL)
For JPA (specification 2.0) having (or negative) value for id is fine. And also as primary key value for H2.
Older versions of EclipseLink do consider value 0 or smaller as invalid primary key. See for example following:Bug 249948. So updating EclipseLink can help.
By the way, why you do set in constructor value for idclient that is supposed to be generated?
I had this error and adding the following annotations to my jpa identity resolved it:
#Column(name = "ID_SEARCH_LOG", nullable = false, insertable = true, updatable = true, length = 10, precision = 0)
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private int idSearchLog;
The docs say
By default, EclipseLink interprets zero as null for primitive types that cannot be null (such as int and long) causing zero to be an invalid value for primary keys.
but also that that it is possible to change this behaviour in either the persistence.xml or on a particular entity.
http://wiki.eclipse.org/EclipseLink/UserGuide/JPA/Basic_JPA_Development/Entities/Ids/Id#Allowing_Zero_Value_Primary_Keys