get max value of composite column using jpa criteria query - jpa

want to get the maximum value of composite column relationId from table ElementRelationType I have written code which is only working for non composite key. my compositKey contains relationId and language
CriteriaBuilder cb1 = entityManager.getCriteriaBuilder();
CriteriaQuery<Integer> cq1 = cb1.createQuery(Integer.class);
Root<ElementRelationTypes> root = cq1.from(ElementRelationTypes.class);
cq1.select(cb1.max(root.<Integer>get("relationId")));
TypedQuery<Integer> qr = entityManager.createQuery(cq1);
Integer i=qr.getResultList().get(0);
my classes are
public class ElementRelationTypes {
private RelationId relationLangPK=new RelationId();
private Country country;
private Status status;
#EmbeddedId
public RelationId getRelationLangPK() {
return relationLangPK;
}
public void setRelationLangPK(RelationId relationLangPK) {
this.relationLangPK = relationLangPK;
}
#Transient
public Integer getRelationId() {
return getRelationLangPK().getRelationId();
}
public void setRelationId(Integer relationId) {
getRelationLangPK().setRelationId(relationId);
}
#Transient
public Language getLanguage() {
return getRelationLangPK().getLanguage();
}
public void setLanguageCode(Language language) {
getRelationLangPK().setLanguage(language);
}
compositClass
public class RelationId implements Serializable {
private Integer relationId;
private Language language;
#JoinColumn(name=PersistenseConstants.ELEMENT_RELATION_TYPE_COL_RELATION_ID)
public Integer getRelationId() {
return relationId;
}
public void setRelationId(Integer relationId) {
this.relationId = relationId;
}
#OneToOne
#JoinColumn(name=PersistenseConstants.LANGUAGE_ENTITY_COL_LANG_CODE)
public Language getLanguage() {
return language;
}
public void setLanguage(Language language) {
this.language = language;
}
exception
java.lang.IllegalArgumentException: Unable to resolve attribute [relationLangPK.relationId] against path
16:14:16,757 ERROR [stderr] (http-/0.0.0.0:8080-1) at org.hibernate.ejb.criteria.path.AbstractPathImpl.unknownAttribute(AbstractPathImpl.java:118)
16:14:16,757 ERROR [stderr] (http-/0.0.0.0:8080-1) at org.hibernate.ejb.criteria.path.AbstractPathImpl.locateAttribute(AbstractPathImpl.java:223)
16:14:16,757 ERROR [stderr] (http-/0.0.0.0:8080-1) at org.hibernate.ejb.criteria.path.AbstractPathImpl.get(AbstractPathImpl.java:194)

It seems to me that the problem is caused by composite expression. Try to access this property in the following way:
cq1.select(
cb1.max(
root.<ElementRelationTypes>get("relationLangPK").<Integer>get("relationId")
)
);

Related

Error column specified more than once when inserting an entity with EmbeddedId using Micronaut Data

I'm using Micronaut Data JDBC and I'm facing an error. I have this entity:
#MappedEntity(value = "document_metadata")
#AllArgsConstructor
#EqualsAndHashCode
public class DocumentMetadataJDBCEntity implements DocumentMetadata {
#Embeddable
#AllArgsConstructor
public static class MetadataPk {
#MappedProperty(value = "document_uid")
#NotNull
private UUID documentUid;
#MappedProperty(value = "metadata_key")
#NotNull
private String metadataKey;
public UUID getDocumentUid() {
return documentUid;
}
public String getMetadataKey() {
return metadataKey;
}
}
#EmbeddedId
private MetadataPk metadataPk;
#NotNull
private String metadataValue;
public MetadataPk getMetadataPk() {
return metadataPk;
}
#Override
public String getMetadataKey() {
return getMetadataPk().getMetadataKey();
}
#Override
public String getMetadataValue() {
return metadataValue;
}
public UUID getDocumentUid() {
return getMetadataPk().getDocumentUid();
}
}
And when inserting I get this error:
io.micronaut.data.exceptions.DataAccessException: SQL error executing INSERT: Batch entry 0 INSERT INTO "document_metadata" ("metadata_key","metadata_value","document_uid","document_uid","metadata_key") VALUES ('id','1234','c960d8de-99a4-40a6-91bf-b0d4a73910d6'::uuid,'c960d8de-99a4-40a6-91bf-b0d4a73910d6'::uuid,'id') was aborted: ERROR: column "document_uid" specified more than once
The code for saving is the next one:
Set<DocumentMetadataJDBCEntity> metadataSet = metadata.entrySet().stream()
.map(e -> new DocumentMetadataJDBCEntity(new DocumentMetadataJDBCEntity.MetadataPk(
savedDocument.getUid(), e.getKey()), e.getValue())).collect(toSet());
Iterable<DocumentMetadataJDBCEntity> persistedMetadata = documentMetadataJDBCRepository.saveAll(metadataSet);
Any idea?
Add #Transient to your convenience accessor (getter) methods:
#Override
#Transient
public String getMetadataKey() {
return getMetadataPk().getMetadataKey();
}
#Transient
public UUID getDocumentUid() {
return getMetadataPk().getDocumentUid();
}
It "tells" Micronaut not to save the return value into the DB.

JPA, How to find an object that has composite id?

Based on second approach answered here I designed my JPA class.
#Entity(name = "SearchKeywordJPA")
#IdClass(SearchKeywordJPA.SearchKeyId.class)
public class SearchKeywordJPA implements Comparable<SearchKeywordJPA> {
#Id
private String keyword;
#Id
private long date;
private String userUUID;
#Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
SearchKeywordJPA that = (SearchKeywordJPA) o;
if (date != that.date) return false;
if (!keyword.equals(that.keyword)) return false;
if (!userUUID.equals(that.userUUID)) return false;
return true;
}
#Override
public int hashCode() {
int result = keyword.hashCode();
result = 31 * result + (int) (date ^ (date >>> 32));
result = 31 * result + userUUID.hashCode();
return result;
}
#Override
public String toString() {
return "SearchKeywordJPA{" +
"keyword='" + keyword + '\'' +
", date=" + date +
", userUUID='" + userUUID + '\'' +
'}';
}
public String getKeyword() {
return keyword;
}
public void setKeyword(String keyword) {
this.keyword = keyword;
}
public long getDate() {
return date;
}
public void setDate(long date) {
this.date = date;
}
public String getUserUUID() {
return userUUID;
}
public void setUserUUID(String userUUID) {
this.userUUID = userUUID;
}
#Override
public int compareTo(SearchKeywordJPA searchRecord) {
long comparedDate = searchRecord.date;
if (this.date > comparedDate) {
return 1;
} else if (this.date == comparedDate) {
return 0;
} else {
return -1;
}
}
/**********************
* Key class
**********************/
public class SearchKeyId {
private int id;
private int version;
}
}
In my servlet I want to check datastore and store my object if is not exist.
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
...
for(SearchKeywordJPA item: applicationList) {
if(!isRecorded(item))
storeRecord(item);
}
}
private boolean isRecorded(SearchKeywordJPA record) {
EntityManager em = EMF.get().createEntityManager();
SearchKeywordJPA item = em.find(SearchKeywordJPA.class, record);
return item != null;
}
private void storeRecord(SearchKeywordJPA record) {
EntityManager em = EMF.get().createEntityManager();
em.persist(record);
}
However when I run, application crashes and log says
javax.persistence.PersistenceException: org.datanucleus.store.appengine.FatalNucleusUserException: Received a request to find an object of type com.twitterjaya.model.SearchKeywordJPA identified by SearchKeywordJPA{keyword='airasia', date=1335680686149, userUUID='FFFF0000'}. This is not a valid representation of a primary key for an instance of com.twitterjaya.model.SearchKeywordJPA.
What is the reason? any suggestion would be appreciated. Thanks
You pass an instance of the IdClass into em.find ... i.e SearchKeyId. Obviously if you really have an IdClass that has no equals/hashCode/toString/constructor then you will likely get many problems. Those problems will only be increased by using an ancient plugin for GAE/Datastore.
If your Key is
#Entity(name = "SearchKeywordJPA")
#IdClass(SearchKeywordJPA.SearchKeyId.class)
public class SearchKeywordJPA implements Comparable<SearchKeywordJPA> {
you are doing it wrong.
IdClass does not need any annotation of #IdClass just the #Id
annotation.
Key can not be an entity.
Need to implements Serializable , comparable is not needed
Need to override equals and hascode and have no arg constructor
Class key need to be as follows.
public class SearchKeyId implements Serializable {
private String keyword;
private long date;
And your entity I assume something like this.
#Entity(name = "SearchKeywordJPA")
#IdClass(SearchKeyId.class)
public class SearchKeywordJPA {
#Id
private String keyword;
#Id
private long date;
private String userUUID;
Just consider that find method will use the SearchKey.class to find
the entities.
Fields that are in the IdClass need to have #Id annotation in the entity.
Key can not be an entity on its own.
Comparable is not really needed as all the comparison are placed in the IdClass

BLOB as parameter in procedure call in mybatis

This is the call in the ProductServices.xml
<update id="resetPassword" parameterType="batchReport">
{ call user_account_mng.enc_reset_password(
#{user_Id,jdbcType=VARCHAR,mode=IN},
#{encrypted_password,jdbcType=VARCHAR,mode=IN},
#{usr_id, dbcType=VARCHAR,mode=IN},
#{salt,jdbcType=VARCHAR,mode=IN},
#{ret_code,jdbcType=CHAR,mode=OUT},
#{pgp_encrypted_password,jdbcType=BLOB,mode=IN}
)}
Now BatchReport is a POJO:
(i have declared an alias for it as batchReport)
public class BatchReport
{
private String user_Id;
private String encrypted_password;
private String usr_id;
private String salt;
private String ret_code;
private byte[] pgp_encrypted_password;
public String getUser_Id() {
return user_Id;
}
public void setUser_Id(String user_Id) {
this.user_Id = user_Id;
}
public String getEncrypted_password() {
return encrypted_password;
}
public void setEncrypted_password(String encrypted_password) {
this.encrypted_password = encrypted_password;
}
public String getUsr_id() {
return usr_id;
}
public void setUsr_id(String usr_id) {
this.usr_id = usr_id;
}
public String getSalt() {
return salt;
}
public void setSalt(String salt) {
this.salt = salt;
}
public String getRet_code() {
return ret_code;
}
public void setRet_code(String ret_code) {
this.ret_code = ret_code;
}
public byte[] getPgp_encrypted_password() {
return pgp_encrypted_password;
}
public void setPgp_encrypted_password(byte[] pgp_encrypted_password) {
this.pgp_encrypted_password = pgp_encrypted_password;
}
}
My main class is like this :
<BatchReport batchReport = new BatchReport();
byte[] byteArray =new byte[]{1,2,3};
batchReport.setUser_Id("CHI");
batchReport.setEncrypted_password("97D6B45");
batchReport.setSalt("71L");
batchReport.setPgp_encrypted_password(byteArray);
String returnCode = productServiceObj.resetPassword(batchReport);
i am getting following error:
Error setting null parameter. Most JDBC drivers require that the JdbcType must be specified for all nullable parameters. Cause: java.sql.SQLException: Invalid column type
The error may involve com.example.services.ProductServices.resetPassword-Inline
ProductServices is a class in which the method resetPassword is declared.
Please help me with this BLOB issue.
What should be the jdbcType in the called procedure.
what value should be passed in this pgp_encrypted_password.
Okay I found the solution to the problem now the jdbcType in the query in .xml file remains the same i.e BLOB.
Next the type which gets set for passing in the values is byte[].
So everything remains same as i have covered up .
Error actually existed as the in .xml file returns an integer indicating the number of rows changed in query and I have given the function return type as String so here goes the solution for the problem it should be of type Object.

EntityManager persist() method does not insert record to database => SEVERE: javax.persistence.TransactionRequiredException

I have problem with using EntityManager persist() method.
I am using JSF2.0, glassfish 3, JPA and hibernate, i am not using spring.
I try to add events in an events table with the method persist, but EntityManager persist() method does not insert record to database and i have this error message =>
SEVERE: javax.persistence.TransactionRequiredException
at com.sun.enterprise.container.common.impl.EntityManagerWrapper.doTxRequiredCheck(EntityManagerWrapper.java:163)
at com.sun.enterprise.container.common.impl.EntityManagerWrapper.flush(EntityManagerWrapper.java:411)
at dao.EvenementDao.addEvenement(EvenementDao.java:128).
#ManagedBean
#Stateless
public class EvenementDao implements Serializable{
/**
*
*/
private static final long serialVersionUID = -3343483942392617877L;
/**
*
*/
private List<TEvenement> listeEvenement;
private List<SelectItem> listeSelectItemEvnt;
private TEvenement tevenement ;
public EvenementDao() {
}
#PersistenceUnit(unitName="GA2010-ejbPU-dev")
private EntityManagerFactory emf;
#PostConstruct
private void init() {
tevenement = new TEvenement();
}
public List<TEvenement> getListeEvenement() {
EntityManager em = emf.createEntityManager();
TypedQuery<TEvenement> requete = m.createNamedQuery("TEvenement.findPrivateOther",
TEvenement.class);
listeEvenement = requete.getResultList();
return listeEvenement;
}
public TEvenement getEvenement() {
return tevenement;
}
public void setEvenement(TEvenement evenement) {
this.tevenement = evenement;
}
public void addEvenement(){
EntityManager em = emf.createEntityManager();
HttpSession session = (HttpSession) FacesContext.getCurrentInstance().
getExternalContext().getSession(false);
Integer codeUser = (Integer) session.getAttribute("codeUser");
tevenement.setUtilCreation(codeUser);
System.out.println("je rentre dans addevenemnt");
try{
System.out.println("i persist "+ em);
em.persist(tevenement);
em.flush();
System.out.println(tevenement.getDetailsEvenement());
FacesMessage message = new FacesMessage("Evenement ajouté avec succès.");
FacesContext.getCurrentInstance().addMessage(null, message);
}catch(Exception e){
e.printStackTrace();
}
}
}
So, this is not working, but the progam enter in the fonction addEvenement , FacesMessage message = new FacesMessage("Evenement ajouté avec succès."); returns me the message as if it was working.
i thouht it was due to my entityMAnager but in fact an ohter function works fine with the same Entity manager so i dont understand.
**public List<TEvenement> getListeEvenement()** {
EntityManager em = emf.createEntityManager();
TypedQuery<TEvenement> requete = em.createNamedQuery("TEvenement.findPrivateOther", TEvenement.class);
listeEvenement = requete.getResultList();
return listeEvenement;
}
this one works fine, the only difference is that in this case the query is a select and in the other case it's a persist so a query that impact the database.
the code of the entity :
#Entity
#Table(name="t_evenements")
#NamedQueries({#NamedQuery(name="TEvenement.findAll", query="SELECT evnt FROM TEvenement evnt"),
#NamedQuery(name="TEvenement.findPrivateOther", query="SELECT evnt FROM TEvenement evnt WHERE evnt.typeEvenement = 6 OR evnt.typeEvenement = 7")})
public class TEvenement implements Serializable {
private static final long serialVersionUID = -1908959833491896991L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name="REF_EVENEMENT", unique=true, nullable=false)
private Integer refEvenement;
#Temporal(TemporalType.DATE)
#Column(name="DATE_DEBUT_EVENEMENT")
private Date dateDebutEvenement;
#Temporal(TemporalType.DATE)
#Column(name="DATE_FIN_EVENEMENT")
private Date dateFinEvenement;
#Column(name="DETAILS_EVENEMENT")
private String detailsEvenement;
#Column(name="IS_EVERYDAY")
private byte isEveryday;
#Column(name="RAPPEL_EVENEMENT")
private int rappelEvenement;
public Integer getUtilEvenement() {
return utilEvenement;
}
public void setUtilEvenement(Integer utilEvenement) {
this.utilEvenement = utilEvenement;
}
#Column(name="TITRE_EVENEMENT")
private String titreEvenement;
#Column(name="TYPE_EVENEMENT")
private String typeEvenement;
#Column(name="UTIL_COPIE_EVENEMENT")
private Integer utilCopieEvenement;
#Column(name="UTIL_EVENEMENT")
private Integer utilEvenement;
#Column(name="HEURE_EVENEMENT")
private String heureEvenement;
#Column(name="UTIL_CREATION")
private Integer utilCreation;
public String getHeureEvenement() {
return heureEvenement;
}
public void setHeureEvenement(String heureEvenement) {
this.heureEvenement = heureEvenement;
}
public TEvenement() {
}
public Integer getRefEvenement() {
return this.refEvenement;
}
public void setRefEvenement(int refEvenement) {
this.refEvenement = refEvenement;
}
public Date getDateDebutEvenement() {
return this.dateDebutEvenement;
}
public Integer getUtilCreation() {
return utilCreation;
}
public void setUtilCreation(Integer utilCreation) {
this.utilCreation = utilCreation;
}
public void setUtilCopieEvenement(Integer utilCopieEvenement) {
this.utilCopieEvenement = utilCopieEvenement;
}
public void setDateDebutEvenement(Date dateDebutEvenement) {
this.dateDebutEvenement = dateDebutEvenement;
}
public Date getDateFinEvenement() {
return this.dateFinEvenement;
}
public void setDateFinEvenement(Date dateFinEvenement) {
this.dateFinEvenement = dateFinEvenement;
}
public String getDetailsEvenement() {
return this.detailsEvenement;
}
public void setDetailsEvenement(String detailsEvenement) {
this.detailsEvenement = detailsEvenement;
}
public byte getIsEveryday() {
return this.isEveryday;
}
public void setIsEveryday(byte isEveryday) {
this.isEveryday = isEveryday;
}
public int getRappelEvenement() {
return this.rappelEvenement;
}
public void setRappelEvenement(int rappelEvenement) {
this.rappelEvenement = rappelEvenement;
}
public String getTitreEvenement() {
return this.titreEvenement;
}
public void setTitreEvenement(String titreEvenement) {
this.titreEvenement = titreEvenement;
}
public String getTypeEvenement() {
return this.typeEvenement;
}
public void setTypeEvenement(String typeEvenement) {
this.typeEvenement = typeEvenement;
}
public Integer getUtilCopieEvenement() {
return this.utilCopieEvenement;
}
public void setUtilCopieEvenement(int utilCopieEvenement) {
this.utilCopieEvenement = utilCopieEvenement;
}
}
Do anyone have a idea what am i missing?
The difference isn't that you call persist, the difference is that you call em.flush() which as the error states, requires the EntityManager be joined to a transaction. Makes sure your getListeEvenement() method is wrapped in a transaction, or start one depending on your setup.

JAXB works with JPA, throw IllegalAnnotationsException

I have been stacked in this place for few days. any help will be appreciated.
Here is my story:
I have a JPA entity class (ExtOffer), and Now I annotate it with JAXB annotation in order to do marshall/unmarshall by JAXB. And I also create a wrapper class(ExtOffers), which basically is a collection of ExtOffer.
And when I call JAXBContext.newInstance(ExtOffers.class), I got an IllegalAnnotationsException:JAXB annotation is placed on a method that is not a JAXB property.
I search google and some post says that it's due to annotate #XmlElement on wrong place.
But my class has #XmlAccessorType(XmlAccessType.NONE) annotation and only the getter method has been annotated with #Xmlelement.
below is my ExtOffer class and ExtOffers class:
//ExtOffer:
#Entity
#Table (name = "extoffer")
#XmlType(name = "ExtOfferType")
#XmlAccessorType(XmlAccessType.NONE)
public class ExtOffer {
public ExtOffer() {
}
#Id
#Column(name = "OfferID", nullable = false, unique = true, length = 32)
protected String offerId;
#Column(name = "HasMoreScreenShot", nullable = false, unique = false, length = 1)
private String hasMoreScreenShot;
public void setOfferId(String offerId) {
this.offerId = offerId;
}
#XmlElement(name="OfferID", required = true)
public String getOfferId() {
return offerId;
}
public void setHasMoreScreenShot(String hasMoreScreenShot) {
this.hasMoreScreenShot= hasMoreScreenShot;
}
#XmlElement(name = "HasMoreScreenShot")
public String GetHasMoreScreenShot() {
return hasMoreScreenShot;
}
}
//ExtOffers wrapper
#XmlRootElement(name="extoffers")
#XmlAccessorType(XmlAccessType.NONE)
public class ExtOfferWrapper {
private List<ExtOffer> extoffers;
public ExtOfferWrapper() {
}
#XmlElement(name="extoffer")
public List<ExtOffer> getExtoffers() {
return extoffers;
}
public void setExtoffers(List<ExtOffer> extoffers) {
this.extoffers = extoffers;
}
}
JAXB annotation is placed on a method that is not a JAXB property
this problem is related to the following location:
at #javax.xml.bind.annotation.XmlElement(nillable=false, name=HasMoreScreenShot, required=false, defaultValue=, type=class javax.xml.bind.annotation.XmlElement$DEFAULT, namespace=##default)
at com.symbio.fuhu.appstore.jpa.entity.ExtOffer
at public java.util.List com.symbio.fuhu.appstore.jaxb.mapping.wrapper.ExtOfferWrapper.getExtoffers()
at com.symbio.fuhu.appstore.jaxb.mapping.wrapper.ExtOfferWrapper
You have an upper case 'G'
#XmlElement(name = "HasMoreScreenShot")
public String GetHasMoreScreenShot() {
return hasMoreScreenShot;
}