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

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

Related

Why List(#OneToMany) with JPA in Entity seen PersistentBag

I have two entities as follows Personel.java and PersonelEgitimDurum.java
List personelEgitimDurumList is PersistentBag in Personel as seen follows;
[enter image description here][1]
[1]: https://i.stack.imgur.com/Q3IC2.png
Personel.java as follows;
#Entity
#Table(name="personel")
public class Personel extends BaseEntity {
#OneToOne(cascade = CascadeType.ALL)
#JoinColumn(name="kisi_id")
private Kisi kisi;
#Column(name="personel_tipi",length = 2,nullable = false)
private int personelTipi;
#Column(name="sicil_no",length = 100,nullable = false)
private String sicilNo;
#OneToMany(fetch = FetchType.EAGER, mappedBy = "personel", cascade =CascadeType.ALL,orphanRemoval = true)
private List<PersonelEgitimDurum> personelEgitimDurumList= new ArrayList<PersonelEgitimDurum>();
#Column(name="khk_onay",length = 1)
private int khkOnay;
}
PersonelEgitimDurum.java as follows;
#Entity
#Table(name = "personel_egitim_durum", indexes = {#Index(name = "index_personel_egitim_durum", columnList = "id")})
public class PersonelEgitimDurum extends BaseEntity {
#ManyToOne(cascade=CascadeType.PERSIST,fetch=FetchType.EAGER)
#JoinColumn(name="personel_id",nullable = false, updatable = true)
private Personel personel;
#Column(name = "ogrenim_durumu")
private String ogrenimDurumu;
#Column(name = "okul_id", length = 3)
private Long okulId;
#Column(name = "universite_bolum_id", length = 4)
private Long universiteBolumId;
#Column(name = "mezuniyet_tarihi")
private Date mezuniyetTarihi;
#Column(name = "aciklama", length = 500)
private String aciklama;
}
PersonelServiceImpl.java as follows;
#Service
#Transactional
public class PersonelServiceImpl implements PersonelService {
#Override
public PersonelDTO findPersonelByKimlikNo(String kimlikNo) {
Kisi kisi=kisiDAO.findKisiByKimlikNo(kimlikNo);
Personel personel=personelDao.findPersonelByKisi(kisi);
PersonelDTO personelDTO=mapper.toDto(personel);
return personelDTO;
}
}
Problem is that personel from findPersonelByKimlikNo in PersonelServiceImpl include that personelEgitimDurumList is PersistentBag as image. So mapStruct does not convert entity to dto.
Error log follows;
java.lang.StackOverflowError: null
at org.hibernate.collection.internal.PersistentBag.size(PersistentBag.java:261) ~[hibernate-core-5.2.17.Final.jar:5.2.17.Final]
at org.kktcmeb.personel.kktcmebpersonel.mapper.PersonelMapperImpl.personelEgitimDurumListToPersonelEgitimDurumDTOList(PersonelMapperImpl.java:159) ~[classes/:na]
at org.kktcmeb.personel.kktcmebpersonel.mapper.PersonelMapperImpl.toDto(PersonelMapperImpl.java:53) ~[classes/:na]
at org.kktcmeb.personel.kktcmebpersonel.mapper.PersonelMapperImpl.personelEgitimDurumToPersonelEgitimDurumDTO(PersonelMapperImpl.java:144) ~[classes/:na]
at org.kktcmeb.personel.kktcmebpersonel.mapper.PersonelMapperImpl.personelEgitimDurumListToPersonelEgitimDurumDTOList(PersonelMapperImpl.java:161) ~[classes/:na]
at org.kktcmeb.personel.kktcmebpersonel.mapper.PersonelMapperImpl.toDto(PersonelMapperImpl.java:53) ~[classes/:na]
Anyone have idea about this situation? Please help
#Entity
#Table(name="personel")
**#JsonIdentityInfo(generator=ObjectIdGenerators.PropertyGenerator.class, property="id")**
public class Personel extends BaseEntity {
#OneToOne(cascade = CascadeType.ALL)
#JoinColumn(name="kisi_id")
private Kisi kisi;
#Column(name="personel_tipi",length = 2,nullable = false)
private int personelTipi;
#Column(name="sicil_no",length = 100,nullable = false)
private String sicilNo;
#OneToMany(fetch = FetchType.EAGER, mappedBy = "personel", cascade =CascadeType.ALL,orphanRemoval = true)
private List<PersonelEgitimDurum> personelEgitimDurumList= new ArrayList<PersonelEgitimDurum>();
#Column(name="khk_onay",length = 1)
private int khkOnay;
}
ADD to head of entities->#JsonIdentityInfo(generator=ObjectIdGenerators.PropertyGenerator.class, property="id")
#Entity
#Table(name = "personel_egitim_durum", indexes = {#Index(name = "index_personel_egitim_durum", columnList = "id")})
#JsonIdentityInfo(generator=ObjectIdGenerators.PropertyGenerator.class, property="id")
public class PersonelEgitimDurum extends BaseEntity {
#ManyToOne(cascade=CascadeType.PERSIST,fetch=FetchType.EAGER)
#JoinColumn(name="personel_id",nullable = false, updatable = true)
private Personel personel;
#Column(name = "ogrenim_durumu")
private String ogrenimDurumu;
#Column(name = "okul_id", length = 3)
private Long okulId;
#Column(name = "universite_bolum_id", length = 4)
private Long universiteBolumId;
#Column(name = "mezuniyet_tarihi")
private Date mezuniyetTarihi;
#Column(name = "aciklama", length = 500)
private String aciklama;
}

Bean validation succeeded but failed on jpa merge method

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!

javax.persistence.NoResultException: No entity found for query JPQL Query

#Entity
#Table(name = "ways", schema = "public", uniqueConstraints = #UniqueConstraint(columnNames = "gid"))
public class Ways implements java.io.Serializable {
private WaysId id;
public Ways() {
}
public Ways(WaysId id) {
this.id = id;
}
#EmbeddedId
#AttributeOverrides({
#AttributeOverride(name = "gid", column = #Column(name = "gid", unique = true)),
#AttributeOverride(name = "classId", column = #Column(name = "class_id", nullable = false)),
#AttributeOverride(name = "length", column = #Column(name = "length", precision = 17, scale = 17)),
#AttributeOverride(name = "name", column = #Column(name = "name")),
#AttributeOverride(name = "x1", column = #Column(name = "x1", precision = 17, scale = 17)),
#AttributeOverride(name = "y1", column = #Column(name = "y1", precision = 17, scale = 17)),
#AttributeOverride(name = "x2", column = #Column(name = "x2", precision = 17, scale = 17)),
#AttributeOverride(name = "y2", column = #Column(name = "y2", precision = 17, scale = 17)),
#AttributeOverride(name = "reverseCost", column = #Column(name = "reverse_cost", precision = 17, scale = 17)),
#AttributeOverride(name = "rule", column = #Column(name = "rule")),
#AttributeOverride(name = "toCost", column = #Column(name = "to_cost", precision = 17, scale = 17)),
#AttributeOverride(name = "maxspeedForward", column = #Column(name = "maxspeed_forward")),
#AttributeOverride(name = "maxspeedBackward", column = #Column(name = "maxspeed_backward")),
#AttributeOverride(name = "osmId", column = #Column(name = "osm_id")),
#AttributeOverride(name = "priority", column = #Column(name = "priority", precision = 17, scale = 17)),
#AttributeOverride(name = "theGeom", column = #Column(name = "the_geom")),
#AttributeOverride(name = "source", column = #Column(name = "source")),
#AttributeOverride(name = "target", column = #Column(name = "target"))})
//#AttributeOverride(name = "vitesse", column = #Column(name = "vitesse", precision = 17, scale = 17))})
public WaysId getId() {
return this.id;
}
public void setId(WaysId id) {
this.id = id;
}
}
#Embeddable
public class WaysId implements java.io.Serializable {
private Integer gid;
private int classId;
private Double length;
private String name;
private Double x1;
private Double y1;
private Double x2;
private Double y2;
private Double reverseCost;
private String rule;
private Double toCost;
private Integer maxspeedForward;
private Integer maxspeedBackward;
private Long osmId;
private Double priority;
private Serializable theGeom;
private Integer source;
private Integer target;
}
public double convertidTolat1(Integer id) {
Double lat = null;
Query query = entityManager
.createQuery("select n.id.x1 from Ways n where n.id.gid=:id");
query.setParameter("id", id);
lat = (Double) query.getSingleResult();
return lat;
}
#GET
#Path("lat/{id}")
#Produces(MediaType.APPLICATION_JSON)
public BigDecimal getlat(#PathParam(value = "id") long id) {
BigDecimal d = iservices.getLat(id);
return d;
}
Hi every body, here is my code, i want to know what's wrong with my query?
There is nothing wrong with your query. Path expressions for Embeddables are perfectly valid in JPA. You just don't get no result for it.
Javadoc for NoResultException is pretty descriptive.
Thrown by the persistence provider when Query.getSingleResult() or TypedQuery.getSingleResult() is executed on a query and there is no result to return. This exception will not cause the current transaction, if one is active, to be marked for rollback.
I would suggest wrapping getSingleResult() in a try-catch block to handle no-result case
Object result = null;
try {
result = query.getSingleResult();
} catch (NoResultException e) {
log.debug("No result forund for... ");
}
or to always use getResultList(), i.e.
List results = query.getResultList();
if (results.isEmpty()) {
return null; // handle no-results case
} else {
return results.get(0);
}
You can even sometimes go further and check DB integrity if you are expecting only one result.
if (results.size() > 1) {
log.warn("Found duplicated result for...");
}
I prefer to do this
public class BwJpaResultHelper {
public static Object getSingleResultOrNull(Query query){
List results = query.getResultList();
if (results.isEmpty()) return null;
else if (results.size() == 1) return results.get(0);
throw new NonUniqueResultException(results.size());
}
}
I think this one will be okay. it worked for me
public Optional<UserDO> findByUserId(String userId) {
List<UserDO> userDOList = list(namedQuery("User.findByUserId").setParameter("theUserId", userId));
return (userDOList.isEmpty()) ? Optional.empty() : Optional.of(userDOList.get(0));
}

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

JPA an Java - #JoinColumns error

I am currently trying to display information requested via JPA 2.0 (eclipselink). I am using glassfish 3.0.1 and netbeans 6.9.1 as IDE. My persistence entities are created under netbeans option "create entity classes from database". My shcema is designed with workbench mysql, and my server is of course mysql. I really cant figure out what creates this #JoinColumns error.
javax.servlet.ServletException: Exception [EclipseLink-30005] (Eclipse Persistence Services - 2.0.1.v20100213-r6600): org.eclipse.persistence.exceptions.PersistenceUnitLoadingException
Exception Description: An exception was thrown while searching for persistence archives with ClassLoader: WebappClassLoader (delegate=true; repositories=WEB-INF/classes/)
Internal Exception: javax.persistence.PersistenceException: Exception [EclipseLink-28018] (Eclipse Persistence Services - 2.0.1.v20100213-r6600): org.eclipse.persistence.exceptions.EntityManagerSetupException
Exception Description: Predeployment of PersistenceUnit [myprojectPU] failed.
Internal Exception: Exception [EclipseLink-7220] (Eclipse Persistence Services - 2.0.1.v20100213-r6600): org.eclipse.persistence.exceptions.ValidationException
Exception Description: The #JoinColumns on the annotated element [field userInfo] from the entity class [class com.myproject.jpa.UserId] is incomplete. When the source entity class uses a composite primary key, a #JoinColumn must be specified for each join column using the #JoinColumns. Both the name and the referencedColumnName elements must be specified in each such #JoinColumn.
This part randomly swaps from [field userInfo] from the entity class [class com.myproject.jpa.UserId] to [field userIdList] from the entity class [class com.myproject.jpa.Cell]. So both classes probably have the same issue.
Here are my classes:
#Entity
#XmlRootElement
#Table(name = "user_id", catalog = "workitout", schema = "")
public class UserId implements Serializable {
private static final long serialVersionUID = 1L;
#EmbeddedId
protected UserIdPK userIdPK;
#Basic(optional = false)
#Column(name = "email", nullable = false, length = 45)
private String email;
#Basic(optional = false)
#Column(name = "password", nullable = false, length = 45)
private String password;
#ManyToMany(mappedBy = "userIdList")
private List<Cell> cellList;
#JoinColumn(name = "USER_INFO_id_info", referencedColumnName = "id_info", nullable = false, insertable = false, updatable = false)
#ManyToOne(optional = false)
private UserInfo userInfo;
...
}
#Entity
#XmlRootElement
#Table(name = "user_info", catalog = "workitout", schema = "")
public class UserInfo implements Serializable {
private static final long serialVersionUID = 1L;
#EmbeddedId
protected UserInfoPK userInfoPK;
#Basic(optional = false)
#Column(name = "fullName", nullable = false, length = 45)
private String fullName;
#Basic(optional = false)
#Column(name = "city", nullable = false, length = 45)
private String city;
#Basic(optional = false)
#Column(name = "gender", nullable = false, length = 10)
private String gender;
#Basic(optional = false)
#Column(name = "isCoach", nullable = false)
private boolean isCoach;
#Column(name = "age")
private Integer age;
#Column(name = "description", length = 200)
private String description;
#Column(name = "linkImage", length = 45)
private String linkImage;
#Column(name = "friendList", length = 500)
private String friendList;
#Column(name = "coachList", length = 500)
private String coachList;
#JoinColumn(name = "USER_SPORT_id_sport", referencedColumnName = "id_sport", nullable = false, insertable = false, updatable = false)
#ManyToOne(optional = false)
private UserSport userSport;
#OneToMany(cascade = CascadeType.ALL, mappedBy = "userInfo")
private List<UserId> userIdList;
...
}
*The first error was solved, but the [field userIdList] from the entity class [class com.myproject.jpa.Cell]. remains. Ive added the code of my cell table:
import java.io.Serializable;
import java.util.List;
import javax.persistence.Basic;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlTransient;
#Entity
#XmlRootElement
#Table(name = "cell", catalog = "workitout", schema = "")
#NamedQueries({
#NamedQuery(name = "Cell.findAll", query = "SELECT c FROM Cell c"),
#NamedQuery(name = "Cell.findByIdCell", query = "SELECT c FROM Cell c WHERE c.idCell = :idCell"),
#NamedQuery(name = "Cell.findByName", query = "SELECT c FROM Cell c WHERE c.name = :name")})
public class Cell implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#Basic(optional = false)
#Column(name = "id_cell", nullable = false)
private Integer idCell;
#Basic(optional = false)
#Column(name = "name", nullable = false, length = 45)
private String name;
#ManyToMany
#JoinTable(name = "user_id_has_cell", joinColumns = {
#JoinColumn(name = "cell_id_cell", referencedColumnName = "id_cell", nullable = false)}, inverseJoinColumns = {
#JoinColumn(name = "USER_ID_id", referencedColumnName = "id", nullable = false),
#JoinColumn(name = "USER_INFO_id_info", referencedColumnName = "id_info", nullable = false, insertable = false, updatable = false),
#JoinColumn(name = "USER_SPORT_id_sport", referencedColumnName = "id_sport", nullable = false, insertable = false, updatable = false)
})
private List<UserId> userIdList;
#OneToMany(cascade = CascadeType.ALL, mappedBy = "cell")
private List<WorkoutSession> workoutSessionList;
public Cell() {
}
public Cell(Integer idCell) {
this.idCell = idCell;
}
public Cell(Integer idCell, String name) {
this.idCell = idCell;
this.name = name;
}
public Integer getIdCell() {
return idCell;
}
public void setIdCell(Integer idCell) {
this.idCell = idCell;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public List<UserId> getUserIdList() {
return userIdList;
}
public void setUserIdList(List<UserId> userIdList) {
this.userIdList = userIdList;
}
public List<WorkoutSession> getWorkoutSessionList() {
return workoutSessionList;
}
public void setWorkoutSessionList(List<WorkoutSession> workoutSessionList) {
this.workoutSessionList = workoutSessionList;
}
#Override
public int hashCode() {
int hash = 0;
hash += (idCell != null ? idCell.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 Cell)) {
return false;
}
Cell other = (Cell) object;
if ((this.idCell == null && other.idCell != null) || (this.idCell != null && !this.idCell.equals(other.idCell))) {
return false;
}
return true;
}
Error message describes the problem pretty clearly - UserInfo has a composite key, therefore you need to specify several #JoinColumns, one column for each field of the composite key:
#JoinColumns({
#JoinColumn(...),
#JoinColumn(...)
})
#ManyToOne(optional = false)
private UserInfo userInfo;
From the error message I would try to add the following to your class UserId:
#JoinColumn(name = "USER_INFO_uSERSPORTidsport", referencedColumnName = "uSERSPORTidsport", nullable = false, insertable = false, updatable = false)
#ManyToOne(optional = false)
private UserSport usersport;