Modeling composite primary key with sequence field - java

I have a table where we have orderId, locationId and sequenceNum columns apart from other columns. These three columns are part of primary key constraint. sequenceNum column increments for an orderId/locationId combination and is restarts from 1 for next orderId/locationId. So sequenceNum generation should be based on max(sequenceNum)+1 for orderId/locationId combination. Can this be modeled with JPA #Embeddable and #EmbeddedId? How to reset sequence back to 1 for orderId/locationId combination?

If you user hibernate, you could user this example. If not, find the sequence generator on the API you are using, and use the same logic.
Identifiable.java
package my.app.hibernate;
import java.io.Serializable;
public interface Identifiable<T extends Serializable> {
T getId();
}
CompositeKeyEntity.java
package my.app.hibernate;
import java.io.Serializable;
public interface CompositeKeyEntity<T extends Serializable> extends Identifiable<T> {
}
SingleKeyEntity.java
package my.app.hibernate;
import java.io.Serializable;
public interface SingleKeyEntity<T extends Serializable> extends Identifiable<T> {
}
AssignedIdentityGenerator.java
package my.app.hibernate;
import java.io.Serializable;
import java.lang.reflect.Field;
import java.util.Arrays;
import java.util.List;
import org.hibernate.Criteria;
import org.hibernate.criterion.Projections;
import org.hibernate.criterion.Restrictions;
import org.hibernate.engine.spi.SessionImplementor;
import org.hibernate.id.IdentityGenerator;
import org.hibernate.internal.CriteriaImpl;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.util.FieldUtils;
public class AssignedIdentityGenerator extends IdentityGenerator {
private static final String ID_FIELD_NAME = "id";
private final Logger LOG = LoggerFactory.getLogger(this.getClass());
private Field sequenceField;
private String entityClassName;
#Override
public Serializable generate(SessionImplementor session, Object obj) {
#SuppressWarnings("unchecked")
Identifiable<Serializable> identifiable = (Identifiable<Serializable>)obj;
entityClassName = obj.getClass().getName();
Criteria criteria = new CriteriaImpl(entityClassName, session);
criteria.setReadOnly(true);
Object toSet = null;
if (identifiable instanceof CompositeKeyEntity) {
Serializable id = identifiable.getId();
if (id != null) {
String embaddebleClassName = id.getClass().getName();
buildCriteriaForEmbeddedId(id, embaddebleClassName, criteria);
toSet = id;
}
} else if (obj instanceof SingleKeyEntity) {
toSet = identifiable;
sequenceField = FieldUtils.getField(identifiable.getClass(), ID_FIELD_NAME);
buildCriteriaForSingleId(criteria);
}
Number one = castToSequenceNumberType(1L);
Number value = (Number) criteria.uniqueResult();
if(value != null) {
value = castToSequenceNumberType(value.longValue() + one.longValue());
setFieldValue(sequenceField, value, toSet);
} else {
value = one;
setFieldValue(sequenceField, value, toSet);
}
return identifiable.getId();
}
private void buildCriteriaForSingleId(Criteria criteria) {
criteria.setProjection(Projections.max(ID_FIELD_NAME).as("seq"));
}
private void buildCriteriaForEmbeddedId(Serializable id, String embaddebleClassName, Criteria criteria) {
List<Field> fields = Arrays.asList(id.getClass().getDeclaredFields());
class Utils {
Field field;
boolean numberFound = false;
}
final Utils utils = new Utils();
for (Field field : fields) {
if ("serialVersionUID".equals(field.getName()) || "$jacocoData".equals(field.getName())) {
continue;
}
if (Number.class.isAssignableFrom(field.getType())) {
if (utils.numberFound) {
throw new IllegalArgumentException(
embaddebleClassName + " has more then one sequence field: " + field.getName() + ", "
+ utils.field.getName() + ",...");
}
utils.numberFound = true;
utils.field = field;
sequenceField = field;
criteria.setProjection(Projections.max(ID_FIELD_NAME + "." + sequenceField.getName()).as("seq"));
} else {
criteria.add(Restrictions.eq(ID_FIELD_NAME + "." + field.getName(), getFieldValue(field, id)));
}
}
}
private Number castToSequenceNumberType(Number n) {
return (Number) sequenceField.getType().cast(n);
}
private void setFieldValue(Field field, Object value, Object to) {
try {
field.setAccessible(true);
field.set(to, value);
} catch (IllegalArgumentException | IllegalAccessException e) {
LOG.error(e.getMessage(), e);
}
}
private Object getFieldValue(Field field, Object from) {
try {
field.setAccessible(true);
return field.get(from);
} catch (IllegalArgumentException | IllegalAccessException e) {
LOG.error(e.getMessage(), e);
}
return null;
}
}
Customer.java
package my.app.entities;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import org.hibernate.annotations.GenericGenerator;
import my.app.hibernate.SingleKeyEntity;
#Entity(name = "whatever_entity_name")
#GenericGenerator(name = "WHATEVER_NAMED_GENERATOR", strategy = "my.app.hibernate.AssignedIdentityGenerator")
public class Customer implements SingleKeyEntity<Long> {
#Id
#GeneratedValue(generator = "WHATEVER_NAMED_GENERATOR")
private Long id;
#Column(nullable = false)
private String name;
}
CustomerItemsId.java (Item.java ommited as it follows SingleKeyEntity example)
package my.app.entities;
import javax.persistence.Embeddable;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
#Embeddable
public class CustomerItemsId implements Serializable {
private static final long serialVersionUID = 1L; //generate one
#ManyToOne
#JoinColumn(name = "customer_id")
private Customer customer;
#ManyToOne
#JoinColumn(name = "item_id")
private Item item;
private Long seq; //name as you wish
}
CustomerItems.java
package my.app.entities;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import org.hibernate.annotations.GenericGenerator;
import my.app.hibernate.CompositeKeyEntity;
#Entity(name = "whatever_entity_name")
#GenericGenerator(name = "WHATEVER_NAMED_GENERATOR", strategy = "my.app.hibernate.AssignedIdentityGenerator")
public class CustomerItems implements CompositeKeyEntity<CustomerItemsId> {
#GeneratedValue(generator = "WHATEVER_NAMED_GENERATOR")
private CustomerItems id;
#Column(nullable = false)
private String randomColumn1;
#Column(nullable = false)
private String randomColumn2;
}

Related

ERROR: constraint for relation already exists with hibernate 4.3.1

I have this error when running the dll generated the hibernate
Failed to execute: alter table sezioniastratte add constraint FK_5nekcygup70my0ixo073o215d foreign key (padre_id) references sezioni
org.postgresql.util.PSQLException: ERROR: constraint "fk_5nekcygup70my0ixo073o215d" for relation "sezioniastratte" already exists
I'm mapping a complex structure, in particular, a structure with the composite pattern, this is the class diagram:
This is my code of the classes
package it.unibas.webanalytics.modello;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Inheritance;
import javax.persistence.InheritanceType;
import javax.persistence.ManyToOne;
import javax.persistence.OneToOne;
/**
*
* #author Vincenzo Palazzo
*/
#Entity(name = "sezioniastratte")
#Inheritance(strategy = InheritanceType.JOINED)
public abstract class AbstractSezione implements ISezione {
private Long id;
protected String identificativo;
private AbstractSezione root;
private AbstractSezione padre;
public AbstractSezione(String identificativo) {
this.identificativo = identificativo;
}
public AbstractSezione() {
}
#Id
#GeneratedValue(strategy = GenerationType.TABLE)
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
#Column(unique = true, nullable = false, length = 150)
public String getIdentificativo() {
return identificativo;
}
public void setIdentificativo(String identificativo) {
this.identificativo = identificativo;
}
#OneToOne
public AbstractSezione getRoot() {
return root;
}
public void setRoot(AbstractSezione root) {
this.root = root;
}
#ManyToOne(cascade = CascadeType.ALL)
public AbstractSezione getPadre() {
return padre;
}
public void setPadre(AbstractSezione padre) {
this.padre = padre;
}
}
package it.unibas.webanalytics.modello;
import it.unibas.webanalytics.modello.visite.IVisitor;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.UUID;
import javax.persistence.Entity;
import javax.persistence.OneToMany;
import javax.persistence.Transient;
/**
*
* #author Vincenzo Palazzo
*/
#Entity(name = "pagine")
public class Pagina extends AbstractSezione{
#Deprecated
private String uuid;
private List<Visualizzazione> visualizzazioni = new ArrayList<>();
public Pagina(String identificativo) {
super(identificativo);
uuid = UUID.randomUUID().toString();
}
public Pagina() {
}
#OneToMany(mappedBy = "pagina", orphanRemoval = true)
public List<Visualizzazione> getVisualizzazioni() {
return visualizzazioni;
}
public void addVisualizzazione(Visualizzazione visualizzazione){
visualizzazioni.add(visualizzazione);
}
#Override
public boolean isPage(){
return true;
}
#Override
public void accept(IVisitor visitor) {
visitor.visitaPagina(this);
}
#Transient
public String getUuid() {
return uuid;
}
public void setUuid(String uuid) {
this.uuid = uuid;
}
public void setVisualizzazioni(List<Visualizzazione> visualizzazioni) {
this.visualizzazioni = visualizzazioni;
}
public int dimensione(){
return this.visualizzazioni.size();
}
#Override
public int hashCode() {
int hash = 5;
hash = 67 * hash + Objects.hashCode(super.identificativo);
hash = 67 * hash + Objects.hashCode(this.uuid);
return hash;
}
#Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
final Pagina other = (Pagina) obj;
if (!Objects.equals(super.identificativo, other.identificativo)) {
return false;
}
if (!Objects.equals(this.uuid, other.uuid)) {
return false;
}
return true;
}
}
package it.unibas.webanalytics.modello;
import it.unibas.webanalytics.modello.visite.IVisitor;
import java.util.ArrayList;
import java.util.List;
import javax.persistence.Entity;
import javax.persistence.OneToMany;
/**
*
* #author Vincenzo Palazzo
*/
#Entity(name = "sezioni")
public class Sezione extends AbstractSezione {
private List<AbstractSezione> sezioniList = new ArrayList<>();
public Sezione() {
}
public Sezione(String identificativo) {
super(identificativo);
}
public void addSezione(AbstractSezione sezione) {
sezioniList.add(sezione);
}
#OneToMany(mappedBy = "padre")
public List<AbstractSezione> getSezioniList() {
return sezioniList;
}
public void setSezioniList(List<AbstractSezione> sezioniList) {
this.sezioniList = sezioniList;
}
#Override
public boolean isPage() {
return false;
}
#Override
public void accept(IVisitor visitor) {
visitor.visitaSezione(this);
}
}
package it.unibas.webanalytics.modello;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.OneToOne;
/**
*
* #author Vincenzo Palazzo
*/
#Entity(name = "portali")
public class PortaleWeb {
#Id
#GeneratedValue(strategy = GenerationType.TABLE)
private long id;
#Column(nullable = false, unique = true, length = 50)
private String nomeDominio;
#Column(nullable = false, unique = true, length = 50)
private String indirizzoIp;
#Column(length = 20)
private String indestatario;
#OneToOne(mappedBy = "root")
private AbstractSezione sezione;
public PortaleWeb() {
}
public PortaleWeb(String nomeDominio, String indirizzoIp, String indestatario, AbstractSezione sezione) {
this.nomeDominio = nomeDominio;
this.indirizzoIp = indirizzoIp;
this.indestatario = indestatario;
this.sezione = sezione;
}
public String getNomeDominio() {
return nomeDominio;
}
public String getIndirizzoIp() {
return indirizzoIp;
}
public String getIndestatario() {
return indestatario;
}
public ISezione getSezione() {
return sezione;
}
public void setNomeDominio(String nomeDominio) {
this.nomeDominio = nomeDominio;
}
public void setIndirizzoIp(String indirizzoIp) {
this.indirizzoIp = indirizzoIp;
}
public void setIndestatario(String indestatario) {
this.indestatario = indestatario;
}
public void setSezione(AbstractSezione sezione) {
this.sezione = sezione;
}
}
package it.unibas.webanalytics.modello;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.ManyToOne;
/**
*
* #author Vincenzo Palazzo
*/
#Entity(name = "visualizzazioni")
public class Visualizzazione {
#Id
#GeneratedValue(strategy = GenerationType.TABLE)
private long id;
#Column(nullable = true, length = 50)
private String nazioneDiProvenienza;
#Column(length = 250)
private String urlProvenienza;
#Column(length = 250)
private String urlDestinazione;
#Column(length = 50)
private String browser;
private int daQuanto;
#ManyToOne(cascade = CascadeType.ALL)
private Pagina pagina;
public Visualizzazione() {
}
public Visualizzazione(String nazioneDiProvenienza, String urlProvenienza, String urlDestinazione, String browser, int daQuanto) {
this.nazioneDiProvenienza = nazioneDiProvenienza;
this.urlProvenienza = urlProvenienza;
this.urlDestinazione = urlDestinazione;
this.browser = browser;
this.daQuanto = daQuanto;
}
public String getNazioneDiProvenienza() {
return nazioneDiProvenienza;
}
public String getUrlProvenienza() {
return urlProvenienza;
}
public String getUrlDestinazione() {
return urlDestinazione;
}
public String getBrowser() {
return browser;
}
public int getDaQuanto() {
return daQuanto;
}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public Pagina getPagina() {
return pagina;
}
public void setPagina(Pagina pagina) {
this.pagina = pagina;
}
public void setNazioneDiProvenienza(String nazioneDiProvenienza) {
this.nazioneDiProvenienza = nazioneDiProvenienza;
}
public void setUrlProvenienza(String urlProvenienza) {
this.urlProvenienza = urlProvenienza;
}
public void setUrlDestinazione(String urlDestinazione) {
this.urlDestinazione = urlDestinazione;
}
public void setBrowser(String browser) {
this.browser = browser;
}
public void setDaQuanto(int daQuanto) {
this.daQuanto = daQuanto;
}
}
This is the DLL generate by hibernate
create table pagine (
page boolean not null,
id int8 not null,
primary key (id)
);
create table portali (
id int8 not null,
indestatario varchar(20),
indirizzoIp varchar(50) not null,
nomeDominio varchar(50) not null,
primary key (id)
);
create table sezioni (
page boolean not null,
id int8 not null,
primary key (id)
);
create table sezioniastratte (
id int8 not null,
identificativo varchar(150) not null,
padre_id int8,
root_id int8,
primary key (id)
);
create table utente (
id int8 not null,
attivo boolean not null,
lastLogin timestamp,
nome varchar(255),
nomeUtente varchar(255),
password varchar(255),
ruolo varchar(255),
primary key (id)
);
create table visualizzazioni (
id int8 not null,
browser varchar(50),
daQuanto int4 not null,
nazioneDiProvenienza varchar(50),
urlDestinazione varchar(250),
urlProvenienza varchar(250),
pagina_id int8,
primary key (id)
);
alter table portali
add constraint UK_7h0fmoqq22xrlcvgnrybiafgb unique (indirizzoIp);
alter table portali
add constraint UK_jywg6ldg7jvgfjgaw9u81bfp8 unique (nomeDominio);
alter table sezioniastratte
add constraint UK_b0jnspivif39dgey09negpjjp unique (identificativo);
alter table utente
add constraint UK_7hipuu05v6vcqr7wbl8q7p4t2 unique (nomeUtente);
alter table pagine
add constraint FK_tijtvrfbi6n06ocq6fpffgdy9
foreign key (id)
references sezioniastratte;
alter table sezioni
add constraint FK_t88ok4wbwbhdtipul9l11xued
foreign key (id)
references sezioniastratte;
alter table sezioniastratte
add constraint FK_5nekcygup70my0ixo073o215d
foreign key (padre_id)
references sezioniastratte;
alter table sezioniastratte
add constraint FK_d0cntmtmcp2wvl6hqr8ddgg8w
foreign key (root_id)
references sezioniastratte;
alter table sezioniastratte
add constraint FK_5nekcygup70my0ixo073o215d
foreign key (padre_id)
references sezioni;
alter table visualizzazioni
add constraint FK_dblrq69ykw1wch2pn845p4xf7
foreign key (pagina_id)
references pagine;
create table hibernate_sequences (
sequence_name varchar(255),
sequence_next_hi_value int4
);
Solution
Sorry for the class diagram wrong but not have another example also sorry for my terrible English but I'm learning
You mixed with the realtionships on the hierarchy levels.
Either the list must be in the AbstractSezione or the padre must be in the Sezione.

Not able to insert child data along with parent inside child table using JPA one to many mapping

I am trying to insert data to database
My input json:
{
"loop_ind": "TERM",
"callRedirectRicTgrpDetailsList": [{
"ric": "RIC1",
"tgrp": "TGRP1",
"priority": 1
},{
"ric": "RICX2",
"tgrp": "TGRP2",
"priority": 2
}]
}
and in url I am sending one more value is redirect_id
like "http://127.0.0.1:8080/myredirect/redirect/1080/"
here redirect_id is 1080
So the redirect_id and loop_ind are common for the callRedirectRicTgrpDetailsList entities. That means loop_ind and redirect_id related to parent entities and the callRedirectRicTgrpDetailsList is child entity.
When I try to insert the above details, 1st list inserted successfully[1080, TERM, RIC1, TGRP1,1]. And the second list [1080,TERM,RIC2,TGRP2,2] is not inserting. because of redirect_id is null.1080 is assigned for the 1st list and the second list shows null.
Database schema:
CREATE TABLE IF NOT EXISTS `callRedirect` (
`redirect_id` varchar(20) NOT NULL,
`loop_ind` varchar(4) NOT NULL,
PRIMARY KEY (`redirect_id`)
);
CREATE TABLE IF NOT EXISTS `callRedirect_ric_tgrp_details` (
`row_id` int(4) AUTO_INCREMENT,
`redirect_id` varchar(20) NOT NULL,
`ric` varchar(20) NOT NULL,
`tgrp` varchar (20) NOT NULL,
`priority` int NOT NULL,
PRIMARY KEY (`row_id`)
);
In dao.java:
callRedirectList.setRedirect_id(redirect_id.trim()); //which is from URL
entityManager.getTransaction().begin();
entityManager.merge(callRedirectList);
entityManager.getTransaction().commit();
Callredirect.java:
import java.util.ArrayList;
import java.util.List;
import javax.persistence.CascadeType;
import javax.persistence.Cacheable;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.OneToMany;
import javax.persistence.QueryHint;
import javax.persistence.Table;
import org.codehaus.jackson.annotate.JsonIgnore;
import org.codehaus.jackson.annotate.JsonProperty;
import org.eclipse.persistence.annotations.CascadeOnDelete;
import org.eclipse.persistence.annotations.PrivateOwned;
#Entity
#Cacheable(false)
#NamedQueries({
#NamedQuery(name = "getCallRedirectById", query = "SELECT a FROM CallRedirect a WHERE a.redirect_id=:redirect_id", hints = #QueryHint(name = "eclipselink.refresh", value = "true")),
#NamedQuery(name = "getAllCallRedirect", query = "SELECT a FROM CallRedirect a order by a.redirect_id", hints = #QueryHint(name = "eclipselink.refresh", value = "true")) })
#Table(name = "CallRedirect")
public class CallRedirect implements java.io.Serializable{
private static final long serialVersionUID = 1L;
#Id
#Column(name = "redirect_id")
#JsonProperty("redirect_id")
private String redirect_id;
#Column(name = "loop_ind")
#JsonProperty("loop_ind")
private String loop_ind;
#OneToMany(mappedBy = "callRedirect", cascade = {CascadeType.PERSIST,CascadeType.REMOVE}, fetch = FetchType.LAZY)
#CascadeOnDelete
/*#JoinColumn(name = "redirect_id") */
private List<CallRedirectRicTgrpDetails> callRedirectRicTgrpDetailsList;
public CallRedirect(){
}
public CallRedirect(String redirect_id, String loop_ind,List<CallRedirectRicTgrpDetails> callRedirectRicTgrpDetailsList){
this.redirect_id = redirect_id;
this.loop_ind = loop_ind;
this.callRedirectRicTgrpDetailsList = callRedirectRicTgrpDetailsList;
}
public String getLoop_ind()
{
return loop_ind.trim();
}
public void setLoop_ind(String loop_ind)
{
this.loop_ind = loop_ind.trim();
}
public List<CallRedirectRicTgrpDetails> getCallRedirectRicTgrpDetailsList()
{
return this.callRedirectRicTgrpDetailsList;
}
public void setCallRedirectRicTgrpDetailsList(List<CallRedirectRicTgrpDetails> callRedirectRicTgrpDetails)
{
this.callRedirectRicTgrpDetailsList= callRedirectRicTgrpDetails;
}
/**
* #return the redirectId
*/
public String getRedirect_id()
{
return redirect_id.trim();
}
/**
* #param redirectId
* the redirectId to set
*/
public void setRedirect_id(String redirect_id)
{
this.redirect_id = redirect_id.trim();
}
#Override
public String toString()
{
return "CallRedirect :: redirect_id: " + redirect_id + ", loop_ind : "
+ loop_ind +", Ric_Tgrp Details : " + callRedirectRicTgrpDetailsList;
}
}
CallRedirectRicTgrpDetails.java:
import javax.persistence.Cacheable;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.QueryHint;
import javax.persistence.Table;
import org.codehaus.jackson.annotate.JsonIgnore;
import org.codehaus.jackson.annotate.JsonProperty;
#Entity
#Cacheable(false)
#NamedQueries({
#NamedQuery(name = "getCallRedirectDetailsById", query = "SELECT a FROM CallRedirectRicTgrpDetails a WHERE a.callRedirect.redirect_id=:redirect_id ORDER BY a.priority", hints = #QueryHint(name = "eclipselink.refresh", value = "true")),
#NamedQuery(name = "getAllCallRedirectDetails", query = "SELECT a FROM CallRedirectRicTgrpDetails a ORDER BY a.priority", hints = #QueryHint(name = "eclipselink.refresh", value = "true")) })
#Table(name = "CallRedirect_ric_tgrp_details")
public class CallRedirectRicTgrpDetails implements java.io.Serializable{
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "row_id")
private int id;
#ManyToOne(fetch = FetchType.LAZY, cascade = {CascadeType.ALL, CascadeType.REMOVE})
//#JoinColumn(name = "redirect_id",insertable=false, updatable=false)
#JoinColumn(name = "redirect_id")
private CallRedirect callRedirect;
#Column(name = "ric")
#JsonProperty("ric")
private String ric;
#Column(name = "tgrp")
#JsonProperty("tgrp")
private String tgrp;
#Column(name = "priority")
#JsonProperty("priority")
private int priority;
public CallRedirectRicTgrpDetails(){
}
public CallRedirectRicTgrpDetails(int priority, int id, String ric, String tgrp){
this.priority = priority;
this.id = id;
this.ric = ric;
this.tgrp = tgrp;
}
#JsonIgnore
public CallRedirect getCallRedirect()
{
return this.callRedirect;
}
#JsonProperty
public void setCallRedirect(CallRedirect callRedirect)
{
this.callRedirect = callRedirect;
if (!this.callRedirect.getCallRedirectRicTgrpDetailsList().contains(this)) {
this.callRedirect.getCallRedirectRicTgrpDetailsList().add(this);
}
}
/**
* #return the ric
*/
public String getRic()
{
return ric.trim();
}
/**
* #param ric
* the ric to set
*/
public void setRic(String ric)
{
this.ric = ric.trim();
}
/**
* #return the tgrp
*/
public String getTgrp()
{
return tgrp.trim();
}
/**
* #param tgrp
* the tgrp to set
*/
public void setTgrp(String tgrp)
{
this.tgrp = tgrp.trim();
}
public int getId()
{
return id;
}
public void setId(int id)
{
this.id = id;
}
public int getPriority()
{
return priority;
}
public void setPriority(int priority)
{
this.priority = priority;
}
/*#Override
public String toString()
{
return "CallRedirectRicTgrpDetails ::RowId : " + id + ", RedirectId : " + callRedirect.getRedirect_id() + ", Ric : " + ric + ", Tgrp : " + tgrp
+ ", Priority : " + priority;
}*/
}
Looks like you might failing to go to all the child objects and calling setCallRedirect. Cascade magic doesn't handle that for you

HIbernate SELECT query for composite key defined using #IdClass annotation

My table VENDORBRANCH has composite keys: "vendorCode" and "vendorBranchCode" which I have defined using the #Id annotation and using #IdClass. The field "vendorCode" is referenced as a foreign key in VENDORCRTERMS class. I'm using postgresql db.
Right now my sql query in the service implimentation looks like this but i want to include composite keys in the query:
Query<?> query = session.createQuery("from VENDORBRANCH where vendorCode = ?");
query.setParameter(0, mf01_vendorCode);
I'm very new to hibernate so tried a few options for the select query but I'm not sure if it's correct to do it this way. So, what would be the best select statement to use for a composite key??
VENDORBRANCH class:
import java.io.Serializable;
import java.util.Date;
import javax.persistence.Embeddable;
import javax.persistence.EmbeddedId;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.IdClass;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import com.parkson.poMain.backend.data.VENDORBRANCH.VBpk;
#SuppressWarnings("serial")
#Entity
#IdClass(VBpk.class)
public class VENDORBRANCH implements Serializable {
#Id
private String vendorCode;
#Id
private String vendorBranchCode;
//getters and setters
// inner class defined for primary key(composite keys)
public static class VBpk implements Serializable {
protected String vendorCode;
protected String vendorBranchCode;
public String getvendorCode() {
return vendorCode;
}
public void vendorCode(String vendorCode) {
this.vendorCode = vendorCode;
}
public String vendorBranchCode() {
return vendorBranchCode;
}
public void vendorBranchCode(String vendorBranchCode) {
this.vendorBranchCode = vendorBranchCode;
}
public VBpk(){}
public VBpk(String vendorCode,String vendorBranchCode){
this.vendorCode = vendorCode;
this.vendorBranchCode = vendorBranchCode;
}
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((vendorBranchCode == null) ? 0 : vendorBranchCode.hashCode());
result = prime * result + ((vendorCode == null) ? 0 : vendorCode.hashCode());
return result;
}
#Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
VBpk other = (VBpk) obj;
if (vendorBranchCode == null) {
if (other.vendorBranchCode != null)
return false;
} else if (!vendorBranchCode.equals(other.vendorBranchCode))
return false;
if (vendorCode == null) {
if (other.vendorCode != null)
return false;
} else if (!vendorCode.equals(other.vendorCode))
return false;
return true;
}
}
}
My other class: VENDORCRTERMS
import java.io.Serializable;
import java.util.Date;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
#SuppressWarnings("serial")
#Entity
public class VENDORCRTERMS implements Serializable {
#Id
private String vcrId ;
//This is the foreign key referenced from **VENDORBRANCH class**
#ManyToOne
#JoinColumns( {
#JoinColumn(name="vendorbranch_vendorcode", nullable = false),
#JoinColumn(name="vendorbranch_vendorBranchCode", nullable = false)} )
private VENDORBRANCH vendorbranch_vendorcode = new VENDORBRANCH();
// foreign key referenced from a different class
#ManyToOne
#JoinColumn(name= "creditterms_credittermscode" , nullable = false)
private CREDITTERMS creditterms_credittermscode = new CREDITTERMS();
//getters and setters
}

why result not getting in spring data application

I am newbie to spring and java,
I have a case, where i am trying to fetching rows from the mysql table
This is my Controller:
#RequestMapping(value = "/pharmacy/order/dates", method = RequestMethod.POST,
produces = MediaType.APPLICATION_JSON_VALUE)
public PharmacyOrderDateResponse orderDates(#Valid #RequestBody PharmacyOrderDateRequest request) {
List<PrescriptionOrder> pharmacyOrders = prescriptionOrderService.orderDatesByPharmacyId(request.getPharmacyId(), request.getOrderStatus(), true);
if(pharmacyOrders.size() == 0) {
throw new EntityNotFoundException("No pharmacy orders found");
}
PharmacyOrderDateResponse response = new PharmacyOrderDateResponse();
Set<Date> orderDateSet = new HashSet<>();
for(PrescriptionOrder pharmacyOrder : pharmacyOrders) {
//orderDateSet.add(longToDate(pharmacyOrder.getCreatedAt().getTime()));
}
response.setPharmacyId(pharmacyOrders.get(0).getPharmacyId());
response.setStatus(ResponseStatusCode.SUCCESS);
response.setPharmacyOrderDateDetails(orderDateSet);
response.setTotalDates(orderDateSet.size());
return response;
}
The above controller is used to call the service by the function, so that to get the list of prescription orders.
This is my Service:
package com.axonytes.corporate.service;
import java.util.Date;
import java.util.List;
import com.axonytes.corporate.entity.PrescriptionOrder;
public interface PrescriptionOrderService {
List<PrescriptionOrder> orderDatesByPharmacyId(Long labId, String orderStatus, Boolean status);
}
This is my ServiceImpl:
#Service
#Transactional(readOnly = true)
public class PrescriptionOrderServiceImpl implements PrescriptionOrderService {
private PrescriptionOrderRepository prescriptionOrderRepository;
#Autowired
public PrescriptionOrderServiceImpl(PrescriptionOrderRepository prescriptionOrderRepository) {
this.prescriptionOrderRepository = prescriptionOrderRepository;
}
#Override
public List<PrescriptionOrder> orderDatesByPharmacyId(Long pharmacyId, String orderStatus, Boolean status) {
OrderStatusEnum orderStatusEnum = OrderStatusEnum.fromString(orderStatus);
List<PrescriptionOrder> prescriptionOrder = prescriptionOrderRepository
.findByPharmacyIdAndOrderStatus(pharmacyId, orderStatusEnum.getStatus());
return prescriptionOrder;
}
}
The above service is a implementation function to list the orders, where it calls the repository function.
This is my Repository:
package com.axonytes.corporate.repository;
import java.util.Date;
import java.util.List;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Repository;
import com.axonytes.corporate.entity.PrescriptionOrder;
#Repository
public interface PrescriptionOrderRepository extends JpaRepository<PrescriptionOrder, Long>{
//#Query(value = "select * from PrescriptionOrder po WHERE po.pharmacyId = :pharmacyId AND po.orderStatus = :orderStatus AND po.active = :active ORDER BY po.createdAt ASC")
//List<PrescriptionOrder> findByPharmacyIdAndOrderStatus(#Param("pharmacyId") Long pharmacyId, #Param("orderStatus") int orderStatus, #Param("active") Boolean active);
List<PrescriptionOrder> findByPharmacyIdAndOrderStatus(#Param("pharmacyId") Long pharmacyId, #Param("orderStatus") int orderStatus);
}
This is my Entity:
package com.axonytes.corporate.entity;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Table;
import org.hibernate.annotations.DynamicInsert;
import org.hibernate.annotations.DynamicUpdate;
#Entity
#DynamicInsert
#DynamicUpdate
#Table(name = "prescription_orders")
public class PrescriptionOrder extends BaseEntity {
private static final long serialVersionUID = -3853355500806579362L;
#Column(name = "prescription_id")
private Long prescriptionId;
#Column(name = "pharmacy_id")
private Long pharmacyId;
#Column(name = "order_status")
private int orderStatus;
public Long getPrescriptionId() {
return prescriptionId;
}
public void setPrescriptionId(Long prescriptionId) {
this.prescriptionId = prescriptionId;
}
public Long getPharmacyId() {
return pharmacyId;
}
public void setPharmacyId(Long pharmacyId) {
this.pharmacyId = pharmacyId;
}
public int getOrderStatus() {
return orderStatus;
}
public void setOrderStatus(int orderStatus) {
this.orderStatus = orderStatus;
}
}
This ismy OrderStatusEnumClass:
package com.axonytes.corporate.util;
public enum OrderStatusEnum {
PENDING(0, "pending"), DESPATCHED(1, "dispatched");
private int status;
private String name;
OrderStatusEnum(int status, String name) {
this.status = status;
this.name = name;
}
public static OrderStatusEnum fromString(String name) {
if(name != null) {
for(OrderStatusEnum orderStatusEnum : OrderStatusEnum.values()) {
if(name.equalsIgnoreCase(orderStatusEnum.toString())) {
return orderStatusEnum;
}
}
}
return null;
}
#Override
public String toString() {
return name;
}
public int getStatus() {
return status;
}
public void setStatus(int status) {
this.status = status;
}
}
I have row values in the mysql:
id prescription_id pharmacy_id order_Status is_active
1 1 6 0 1
I am trying to list a orders by the following api.
http://localhost:8080/pharmacy/order/dates
POST METHOD with JSON VALUE:
{
"pharmacyId":"6",
"orderStatus":"pending"
}
Eventhough i am having 1 rows in the mysql db table, Output i am getting is:
{
"status": "FAILURE",
"errorCode": 0,
"errorMessage": "No pharmacy orders found"
}
Here you are using spring data and name method resolving. So is spring who translate the name of your method with each property in your entity, in that case you don't have to declare any parameter name so change your method to this:
#Repository
public interface PrescriptionOrderRepository extends JpaRepository<PrescriptionOrder, Long>{
List<PrescriptionOrder> findByPharmacyIdAndOrderStatus(Long pharmacyId, int orderStatus);
}
Note: You have an enum OrderStatusEnum but you are saving into the database an integer, I highly recommend you to modify the object to store and change the int for the enum, would be easier to read

how does ".merge(entity)" work?

i'm creating a java EE (web) application using JPA and EJB for model-tier.
i think i have to use Session Beans for CRUD.
this is my BrandFacade.java (session bean)
package model.business;
import model.localinterface.BrandFacadeLocal;
import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import model.entities.Brand;
#Stateless
public class BrandFacade extends AbstractFacade<Brand> implements BrandFacadeLocal, BrandFacadeRemote {
#PersistenceContext(unitName = "MyWheelEE-ejbPU")
private EntityManager em;
#Override
protected EntityManager getEntityManager() {
return em;
}
public BrandFacade() {
super(Brand.class);
}
#Override
public boolean CreateBrand(String name) {
Brand brand=new Brand(0, name);
boolean result=true;
try {
em.persist(brand);
} catch (Exception e) {
result=false;
}
em.close();
return result;
}
#Override
public void deleteBrand(int brandOid) {
em.remove(getBrandByOid(brandOid));
em.flush();
}
#Override
public Brand getBrandByOid(int brandOid) {
em.flush();
return em.find(Brand.class, brandOid);
}
#Override
public void editBrand(Brand brand) {
em.merge(brand);
em.flush();
}
}
and this is my Brand.java class (entity)
package model.entities;
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.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
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
#Table(name = "brand")
#XmlRootElement
#NamedQueries({
#NamedQuery(name = "Brand.findAll", query = "SELECT b FROM Brand b"),
#NamedQuery(name = "Brand.findByOid", query = "SELECT b FROM Brand b WHERE b.oid = :oid"),
#NamedQuery(name = "Brand.findByName", query = "SELECT b FROM Brand b WHERE b.name = :name")})
public class Brand implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Basic(optional = false)
#Column(name = "oid")
private Integer oid;
#Basic(optional = false)
#Column(name = "name")
private String name;
#OneToMany(cascade = CascadeType.ALL, mappedBy = "brandOid")
private List<Wheelchair> wheelchairList;
public Brand() {
}
public Brand(Integer oid) {
this.oid = oid;
}
public Brand(Integer oid, String name) {
this.oid = oid;
this.name = name;
}
public Integer getOid() {
return oid;
}
public void setOid(Integer oid) {
this.oid = oid;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
#XmlTransient
public List<Wheelchair> getWheelchairList() {
return wheelchairList;
}
public void setWheelchairList(List<Wheelchair> wheelchairList) {
this.wheelchairList = wheelchairList;
}
#Override
public int hashCode() {
int hash = 0;
hash += (oid != null ? oid.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 Brand)) {
return false;
}
Brand other = (Brand) object;
if ((this.oid == null && other.oid != null) || (this.oid != null && !this.oid.equals(other.oid))) {
return false;
}
return true;
}
#Override
public String toString() {
return "model.entities.Brand[ oid=" + oid + " ]";
}
}
i wish to know how does .merge method work... i think it search in the DB the entity which has the primary key of the entity passed and then it works on edited fields right?
but how i can edit a brand knowing only the name?
It's quite simple really, here your answers:
I wish to know how does .merge method work...
When you call merge method, JPA will verify if the field marked as primary key (#Id) is not null:
- IF YES: JPA will create a new record in your database
- IT NOT: JPA will update your record using the id field value, something like (UPDATE table_name ..... WHERE id=?)
So, you are right :)
but how i can edit a brand knowing only the name?
If you wanna edit a record knowing another field rather than Id field, you will have 2 options:
1. Write JPQL, something like:
UPDATE Person p SET p.lastName = 'New Last Name' WHERE p.name = 'his name'
Write a Native Query, in this case, you will write PLAIN SQL and the run it
In both cases, you will need to do something like:
Query query = em.createQuery or em.createNativeQuery
and then just execute it

Categories