I'm facing a trouble where I've my transactions controlled by Spring Tx and when I do a merge and after flush, my implementation does not print the command neither the Spring Tx commit them.
Follows my code:
#Named
#Transactional(propagation = Propagation.MANDATORY, readOnly = false)
class AverbacaoDAOImpl extends AbstractDAOImpl<Averbacao, Long> implements AverbacaoDAO{
private List<Averbacao> atualizarAverbacoes(final List<Averbacao> averbacoes, final EtapaAverbacao etapa) {
int counter = 0;
for(Averbacao averbacao : averbacoes) {
averbacao.setEtapa(etapa);
atualizar(averbacao);
counter += 1;
}
entityManager.flush();
LOGGER.debug("Atualizado {} averbacoes para a etapa {}", counter, etapa);
return averbacoes;
}
}
private atualizar(Averbacao averbacao) {
entityManager.merge(averbacao);
}
Every objects in the list are managed by JPA (or I think that they're)
Follows logs:
Spring Transaction/Hibernate:
08:37:06,102 DEBUG [BilhetagemProcessManagerExecutor-1hread] [AbstractFlushingEventListener] Processing flush-time cascades
08:37:07,576 DEBUG [BilhetagemProcessManagerExecutor-1hread] [AbstractFlushingEventListener] Dirty checking collections
08:37:08,703 DEBUG [BilhetagemProcessManagerExecutor-1hread] [Collections] Collection found: [br.com.company.bilhetagem.brms.model.Proposta.propostaTaxaAplicaveis#35340], was: [br.com.company.bilhetagem.brms.model.Proposta.propostaTaxaAplicaveis#35340] (initialized)
08:37:08,706 DEBUG [BilhetagemProcessManagerExecutor-1hread] [AbstractFlushingEventListener] Flushed: 0 insertions, 0 updates, 0 deletions to 26047 objects
08:37:08,707 DEBUG [BilhetagemProcessManagerExecutor-1hread] [AbstractFlushingEventListener] Flushed: 0 (re)creations, 0 updates, 0 removals to 1 collections
08:37:08,707 DEBUG [BilhetagemProcessManagerExecutor-1hread] [EntityPrinter] Listing entities:
08:37:08,707 DEBUG [BilhetagemProcessManagerExecutor-1hread] [EntityPrinter] br.com.company.bilhetagem.brms.model.tarifas.TipoTarifaPercentual{percentualMultiplicador=1.0, tipo=OCD}
08:37:08,713 DEBUG [BilhetagemProcessManagerExecutor-1hread] [EntityPrinter] More......
Averbacao
#Entity
#Table(name = "TBIL_RELAC_AVERB_PROPT", schema = "BILHET")
#SecondaryTable(name = "TBIL_AVERBACAO", schema = "BILHET", pkJoinColumns = { #PrimaryKeyJoinColumn(name = "SEQ_NUMER_AVB") })
public final class Averbacao implements Serializable {
/**
*
*/
private static final long serialVersionUID = -3229114271975034004L;
#Id
#Column(name = "SEQ_NUMER_AVB")
private long numeroAverbacao;
#ManyToOne(optional = false, targetEntity = Proposta.class)
#JoinColumn(name = "SEQ_NUMER_PRS", nullable = false)
private Proposta proposta;
#Column(name = "VLR_IS", scale = 15, precision = 2, nullable = true)
private Double valorIS;
#ManyToOne(optional = false)
#JoinColumn(name = "CTL_LOCAL_ORI", nullable = false, table = "TBIL_AVERBACAO")
private Localidade origem;
#ManyToOne(optional = false)
#JoinColumn(name = "CTL_LOCAL_DES", nullable = false, table = "TBIL_AVERBACAO")
private Localidade destino;
#ManyToOne(optional = true)
#JoinColumn(name = "CTL_LOCAL_FIM", nullable = true, table = "TBIL_AVERBACAO")
private Localidade destinoFinal;
#Column(name = "DHR_EMBAR", nullable = false, table = "TBIL_AVERBACAO")
#Temporal(TemporalType.DATE)
private Date dataEmbarque;
#Column(name = "IDT_CARGA_DSC", nullable = false, table = "TBIL_AVERBACAO")
private char tipoCargaDescarga;
#Column(name = "IDT_VEICU", nullable = false, table = "TBIL_AVERBACAO")
private String tipoVeiculo;
#Column(name = "STA_AVARI", nullable = false, table = "TBIL_AVERBACAO")
private char indicadorAvaria;
#Column(name = "STA_FLUVI", nullable = false, table = "TBIL_AVERBACAO")
private char indicadorTrechoFluvial;
#Column(name = "NUM_ETAPA_AVB", nullable = false, table = "TBIL_AVERBACAO")
#Type(type = "br.com.company.bilhetagem.brms.dao.jpa.types.EtapaAverbacaoUserType")
private EtapaAverbacao etapa;
public Averbacao() {
}
public Averbacao(final Proposta proposta) {
this.proposta = proposta;
}
#Transient
public AverbacaoPropostaKey getAverbacaoPropostaKey() {
final long numeroProposta =
this.proposta == null ? 0 : this.proposta.getNumeroProposta();
return new AverbacaoPropostaKey(this.numeroAverbacao, numeroProposta);
}
public Date getDataEmbarque() {
return new DateTime(dataEmbarque).toDate();
}
public Localidade getDestino() {
return destino;
}
public long getNumeroAverbacao() {
return numeroAverbacao;
}
public Localidade getOrigem() {
return origem;
}
public Proposta getProposta() {
return proposta;
}
public Double getValorIS() {
return valorIS;
}
public char getTipoCargaDescarga() {
return tipoCargaDescarga;
}
public String getTipoVeiculo() {
return tipoVeiculo;
}
public char getIndicadorAvaria() {
return indicadorAvaria;
}
public char getIndicadorTrechoFluvial() {
return indicadorTrechoFluvial;
}
public Localidade getDestinoFinal() {
return destinoFinal;
}
public final EtapaAverbacao getEtapa() {
return etapa;
}
public final void setEtapa(EtapaAverbacao etapa) {
this.etapa = etapa;
}
#Override
public String toString() {
return toStringHelper(this).addValue(this.numeroAverbacao)
.add("Proposta", this.proposta).add("Origem", this.origem)
.add("Destino", this.destino).addValue(this.dataEmbarque)
.addValue(this.valorIS).toString();
}
#Override
public int hashCode() {
return Objects.hashCode(this.dataEmbarque, this.destino,
this.numeroAverbacao, this.origem, this.proposta, this.valorIS,
this.tipoCargaDescarga, this.indicadorAvaria,
this.indicadorTrechoFluvial, this.destinoFinal);
}
#Override
public boolean equals(Object obj) {
if (obj == null) {
return false;
}
if (obj == this) {
return true;
}
if (obj.getClass() != getClass()) {
return false;
}
final Averbacao that = (Averbacao) obj;
return equal(this.numeroAverbacao, that.getNumeroAverbacao())
&& equal(this.destino, that.getDestino())
&& equal(this.origem, that.getOrigem())
&& equal(this.proposta, that.getProposta());
}
}
EtapaAverbacao
public enum EtapaAverbacao implements Serializable, PersistentEnum {
NAO_PROCESSADO(1),
PROCESSANDO(2),
PROCESSADO(3);
private int id;
private EtapaAverbacao(final int id) {
this.id = id;
}
#Override
public int getId() {
return this.id;
}
}
public abstract class AbstractPersistentEnumUserType implements UserType {
public AbstractPersistentEnumUserType() {
}
public static List<Integer> toIdList(final List<? extends PersistentEnum> enumList) {
final List<Integer> ids = new ArrayList<Integer>();
if(enumList == null) {
return ids;
}
for(PersistentEnum e : enumList) {
ids.add(e.getId());
}
return ids;
}
public static List<Integer> toIdList(final PersistentEnum[] enumList) {
return toIdList(Arrays.asList(enumList));
}
#Override
public final int[] sqlTypes() {
return new int[] { Types.INTEGER };
}
#Override
public abstract Class<T> returnedClass();
#Override
public final boolean equals(Object obj1, Object obj2) {
if(obj1 == null) {
return false;
}
return obj1.equals(obj2);
}
#Override
public final int hashCode(Object obj) {
return obj == null ? 0 : obj.hashCode();
}
#Override
public final Object nullSafeGet(ResultSet rs, String[] names, SessionImplementor session, Object owner) throws SQLException {
if (rs.wasNull()) {
return null;
}
for (PersistentEnum value : returnedClass().getEnumConstants()) {
final int id = rs.getInt(names[0]);
if (id == value.getId()) {
return value;
}
}
throw new IllegalStateException("Unknown " + returnedClass().getSimpleName() + " id");
}
#Override
public final void nullSafeSet(PreparedStatement stmt, Object value, int index, SessionImplementor session) throws SQLException {
if (value == null) {
stmt.setNull(index, Types.INTEGER);
} else {
stmt.setInt(index, ((PersistentEnum) value).getId());
}
}
#Override
public final Object deepCopy(Object value) {
return value;
}
#Override
public final boolean isMutable() {
return false;
}
#Override
public final Serializable disassemble(Object value) {
return (Serializable) value;
}
#Override
public final Object assemble(Serializable cached, Object owner) {
return cached;
}
#Override
public final Object replace(Object original, Object target, Object owner) {
return original;
}
}
public class EtapaAverbacaoUserType extends
AbstractPersistentEnumUserType<EtapaAverbacao> {
#Override
public Class<EtapaAverbacao> returnedClass() {
return EtapaAverbacao.class;
}
}
After much effort I discovered with my team that the objects returned from query they were fetched as read only.
So, we get out the hint READ_ONLY in the query and now the objects can be updated
Related
I'm trying to implement the use of reflection and annotations, just like the solution suggested by ardayigit on how to create a JTable with POJOs with a single table model, but the problem comes with the first field of Person, which is a two-field composite key of type PersonId.
Here is the extract for creating the JTable:
//List<Person> persons
ModelDAO model = new ModelDAO(persons);
JTable table = new JTable(model) {
#Override
public Class getColumnClass(int column) {
try {
return getValueAt(0, column).getClass();
} catch (NullPointerException e) {
return String.class;
}
}
};
here is the code of the POJO Person:
#Entity
#Table(name = "Person",
schema = "dbo",
catalog = "DB"
)
public class Person implements Serializable {
private PersonId id;
#ColumnAttribute(columnName = "t_name", order = 2, updatable = true)
private String tName;
#ColumnAttribute(columnName = "t_address", order = 4, updatable = true)
private String tAddress;
#ColumnAttribute(columnName = "t_single", order = 5, updatable = true)
private boolean tSingle;
public Person(PersonId id, String tName, String tAddress, boolean tSingle) {
this.id = id;
this.tName = tName;
this.tAddress = tAddress;
this.tSingle = tSingle;
}
#EmbeddedId
#AttributeOverrides({
#AttributeOverride(name = "tKey", column = #Column(name = "t_key", nullable = false, length = 8)),
#AttributeOverride(name = "tReg", column = #Column(name = "t_reg", nullable = false, length = 2))
})
public PersonId getId() {
return id;
}
public void setId(PersonId id) {
this.id = id;
}
#Column(name = "t_name", length = 100)
public String getTName() {
return tName;
}
public void setTName(String tName) {
this.tName = tName;
}
#Column(name = "t_address", length = 60)
public String getTAddress() {
return tAddress;
}
public void setTAddress(String tAddress) {
this.tAddress = tAddress;
}
#Column(name = "t_single", nullable = false, columnDefinition = "BIT")
public boolean getTSingle() {
return tSingle;
}
public void setTSingle(boolean tSingle) {
this.tSingle = tSingle;
}
}
here is PersonId:
#Embeddable
public class PersonId implements Serializable {
#ColumnAttribute(columnName = "t_key", order = 1, updatable = false)
private String tKey;
#ColumnAttribute(columnName = "t_reg", order = 3, updatable = false)
private String tReg;
public PersonId() {
}
public PersonId(String tKey, String tReg) {
this.tKey = tKey;
this.tReg = tReg;
}
#Column(name="t_key", nullable=false, length=8)
public String getTKey() {
return tKey;
}
public void setTKey(String tKey) {
this.tKey = tKey;
}
#Column(name="t_reg", nullable=false, length=2)
public String getTReg() {
return tReg;
}
public void setTReg(String tReg) {
this.tReg = tReg;
}
#Override
public int hashCode() {
int hash = 7;
hash = 79 * hash + Objects.hashCode(this.tKey);
hash = 79 * hash + Objects.hashCode(this.tReg);
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 PersonId other = (PersonId) obj;
if (!Objects.equals(this.tKey, other.tKey)) {
return false;
}
if (!Objects.equals(this.tReg, other.tReg)) {
return false;
}
return true;
}
}
As you can see, I´ve modified a little the proposal of ardaigit and created ColumnAttributes and ColumnAttribute to get it work the way it does AttributeOverrides and AttributeOverride, but not sure if got it right.
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
#Retention(RetentionPolicy.RUNTIME)
#Target(ElementType.FIELD)
public #interface ColumnAttributes {
public ColumnAttribute[] value();
}
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
#Retention(RetentionPolicy.RUNTIME)
#Target(ElementType.FIELD)
public #interface ColumnAttribute {
String columnName();
int order();
boolean updatable();
}
At this point, the method getColumnCount of ModelDAO returns 4, because tName and tReg are counted as 1 --> id:
public class ModelDAO extends AbstractTableModel {
private final List<?> data;
public ModelDAO(List data) {
this.data = data;
}
#Override
public int getRowCount() {
return this.data.size();
}
#Override
public int getColumnCount() {
return data.get(0).getClass().getDeclaredFields().length;
}
#Override
public Object getValueAt(int rowIndex, int columnIndex) {
try {
Method[] methods = data.get(rowIndex).getClass().getDeclaredMethods();
Arrays.sort(methods, new ComparatorReflection<>());
return methods[columnIndex].invoke(data.get(rowIndex), (Object[]) null);
} catch (IllegalAccessException | IllegalArgumentException | SecurityException | InvocationTargetException ex) {
ex.printStackTrace();
}
throw new UnsupportedOperationException("Not supported yet.");
}
#Override
public Class<?> getColumnClass(int columnIndex) {
Field[] fields = data.get(0).getClass().getDeclaredFields();
Arrays.sort(fields, new ComparatorReflection<>());
return fields[columnIndex].getType();
}
#Override
public String getColumnName(int column) {
Field[] fields = data.get(0).getClass().getDeclaredFields();
Arrays.sort(fields, new ComparatorReflection<>());
return fields[column].getAnnotation(ColumnAttribute.class).columnName();
}
#Override
public boolean isCellEditable(int rowIndex, int columnIndex) {
Field[] fields = data.get(rowIndex).getClass().getDeclaredFields();
Arrays.sort(fields, new ComparatorReflection<>());
return fields[columnIndex].getAnnotation(ColumnAttribute.class).updatable();
}
}
Is there a way to "extract" the fields of PersonId in order to get the right column counts, values, classes and names to show them in an editable JTable?
public class AfpProcessSummaryDetail implements Serializable {
private String srNo;
private String fileName;
private String status;
private String location;
private String comments;
private Character convertStatus;
private AfpProcessDetail afpProcessDetail;
public AfpProcessSummaryDetail() {
}
public AfpProcessSummaryDetail(String srNo, String fileName, String status, String location, String comments,
AfpProcessDetail afpProcessDetail) {
this.srNo = srNo;
this.fileName = fileName;
this.status = status;
this.location = location;
this.comments = comments;
this.afpProcessDetail = afpProcessDetail;
}
#ManyToOne
#JoinColumn(name = "PROCESSDETAIL")
public AfpProcessDetail getAfpProcessDetail() {
return afpProcessDetail;
}
AfpProcessDetail
public class AfpProcessDetail implements Serializable {
private String processID;
private String processDate;
private Integer fileCount;
private Integer successCount;
private Integer failureCount;
private Character active;
private Set<AfpProcessSummaryDetail> processSummaryDetails = new HashSet<AfpProcessSummaryDetail>(0);
public AfpProcessDetail() {
}
public AfpProcessDetail(String processID, String processDate, Integer fileCount, Integer successCount,
Integer failureCount) {
this.processID = processID;
this.processDate = processDate;
this.fileCount = fileCount;
this.successCount = successCount;
this.failureCount = failureCount;
}
public AfpProcessDetail(String processID, String processDate, Integer fileCount, Integer successCount,
Integer failureCount, Set<AfpProcessSummaryDetail> processSummaryDetails) {
this.processID = processID;
this.processDate = processDate;
this.fileCount = fileCount;
this.successCount = successCount;
this.failureCount = failureCount;
this.processSummaryDetails = processSummaryDetails;
}
#Column(name = "FAILURECOUNT")
public Integer getFailureCount() {
return failureCount;
}
public void setFailureCount(Integer failureCount) {
this.failureCount = failureCount;
}
#Column(name = "FILECOUNT")
public Integer getFileCount() {
return fileCount;
}
public void setFileCount(Integer fileCount) {
this.fileCount = fileCount;
}
#Column(name = "PROCESSDATE")
public String getProcessDate() {
return processDate;
}
public void setProcessDate(String processDate) {
this.processDate = processDate;
}
#Id
#Column(name = "PROCESSID", unique = true, nullable = false)
public String getProcessID() {
return processID;
}
public void setProcessID(String processID) {
this.processID = processID;
}
#Column(name = "SUCESSCOUNT")
public Integer getSuccessCount() {
return successCount;
}
public void setSuccessCount(Integer successCount) {
this.successCount = successCount;
}
#JoinColumn(name="PROCESSDETAIL")
#OneToMany(cascade=CascadeType.ALL,fetch = FetchType.EAGER)
public Set<AfpProcessSummaryDetail> getProcessSummaryDetails() {
return processSummaryDetails;
}
public void setProcessSummaryDetails(Set<AfpProcessSummaryDetail> processSummaryDetails) {
this.processSummaryDetails = processSummaryDetails;
}
Code for updating
public String updateSummaryDetails(ViewFile viewFile, String codeID) {
if (viewFile != null && codeID != null) {
HibernateTemplate transactionTemplate = new HibernateTemplate(sessionFactory, true);
Object result = transactionTemplate.execute(new HibernateCallback<Object>() {
#Override
public Object doInHibernate(org.hibernate.Session session) throws HibernateException, SQLException {
AfpProcessSummaryDetail processSummary =null,newProcessSummary =null;
AfpProcessDetail processDetail = (AfpProcessDetail)session.get(AfpProcessDetail.class,codeID);
List<FileProperty> fileList = viewFile.getFileList();
Set<AfpProcessSummaryDetail> setProcessSummary=new HashSet<AfpProcessSummaryDetail>();
Set<AfpProcessSummaryDetail> modSetProcessSummary=new HashSet<AfpProcessSummaryDetail>();
setProcessSummary =processDetail.getProcessSummaryDetails();
Iterator<AfpProcessSummaryDetail> itrProcessSumm=setProcessSummary.iterator();
int srNo = 0;
while (itrProcessSumm.hasNext()){
processSummary =(AfpProcessSummaryDetail)itrProcessSumm.next();
for (FileProperty fileProperty : fileList) {
newProcessSummary =new AfpProcessSummaryDetail();
newProcessSummary.setSrNo(codeID + "" + srNo);
newProcessSummary.setFileName(fileProperty.getName());
newProcessSummary.setLocation(fileProperty.getPath());
newProcessSummary.setComments(fileProperty.getComment());
newProcessSummary.setStatus(fileProperty.getStatus());
newProcessSummary.setConvertStatus(fileProperty.getConvertStatus());
newProcessSummary.setAfpProcessDetail(processDetail);
modSetProcessSummary.add(newProcessSummary);
/*if (processSummary.getFileName().trim().equals(fileProperty.getName().trim())){
System.out.println("Element removed");
itrProcessSumm.remove();
modSetProcessSummary.add(newProcessSummary);
break;
}*/
srNo++;
}
}
// setProcessSummary.addAll(modSetProcessSummary);
processDetail.setProcessSummaryDetails(modSetProcessSummary);
processDetail.setFailureCount(viewFile.getExceptionNo());
processDetail.setSuccessCount(viewFile.getSuccessNo());
processDetail.setActive(viewFile.getActive());
transactionTemplate.flush();
session.merge(processDetail);
System.out.println("updated successfully");
return codeID;
}
});
Desired result
I want to perform a one to many update -AfpProcessSummaryDetail which is related to AfpProcessDetail via Set. When I try to replace the set values for update it tries to update the primary key to null. If I don't replace the updates don't take place. If I set cascade it gives error -a different object with the same identifier value was already associated with the session:
[com.aurionpro.convertor.dto.AfpProcessSummaryDetail#15a236ffc961];
nested exception is org.hibernate.NonUniqueObjectException: a
different object with the same identifier value was already associated
with the session.
Please suggest
I have a Client.class which has a OneToMany relation with Posto.class.
#Entity
#Table(name = "client", catalog = "SMARTPARK")
public class Client implements java.io.Serializable {
/**
*
*/
private static final long serialVersionUID = 1L;
private int idClient;
private String nomeClient;
private int numPosti;
private int numLuci;
private String currentIp;
private boolean online;
private String prop;
private SortedSet<Posto> posti = new TreeSet<>();
private SortedSet<Luce> luci = new TreeSet<>();
public Client() {
}
public Client(int idClient, String nomeClient, int numPosti, int numLuci,
String currentIp, boolean online, String prop,
SortedSet<Posto> posti, SortedSet<Luce> luci) {
this.idClient = idClient;
this.nomeClient = nomeClient;
this.numPosti = numPosti;
this.numLuci = numLuci;
this.currentIp = currentIp;
this.prop = prop;
this.online = online;
this.posti = posti;
this.luci = luci;
}
#Id
#Column(name = "id_client", unique = true, nullable = false)
public int getIdClient() {
return this.idClient;
}
public void setIdClient(int idClient) {
this.idClient = idClient;
}
#Column(name = "nome_client", nullable = false, length = 65535)
public String getNomeClient() {
return this.nomeClient;
}
public void setNomeClient(String nomeClient) {
this.nomeClient = nomeClient;
}
#Transient
public int getNumPosti() {
return this.numPosti;
}
public void setNumPosti(int numPosti) {
this.numPosti = numPosti;
}
#Transient
public int getNumLuci() {
return this.numLuci;
}
public void setNumLuci(int numLuci) {
this.numLuci = numLuci;
}
#Column(name = "client_ip", nullable=true)
public String getCurrentIp() {
return currentIp;
}
public void setCurrentIp(String currentIp) {
this.currentIp = currentIp;
}
#Column(name="online")
public boolean isOnline() {
return online;
}
public void setOnline(boolean online) {
this.online = online;
}
#Column(name="prop")
public String getProp() {
return prop;
}
public void setProp(String prop) {
this.prop = prop;
}
#OneToMany(fetch = FetchType.EAGER, cascade=CascadeType.ALL, mappedBy = "client", orphanRemoval=true)
#OrderBy("numeroPosto ASC")
public Set<Posto> getPosti() {
return posti;
}
public void setPosti(SortedSet<Posto> posti) {
this.posti = posti;
}
#OneToMany(fetch = FetchType.EAGER, cascade=CascadeType.ALL, mappedBy = "client", orphanRemoval=true)
#OrderBy("numeroLuce ASC")
public SortedSet<Luce> getLuci() {
return luci;
}
public void setLuci(SortedSet<Luce> luci) {
this.luci = luci;
}
This was made because a use the Set in a responseEntity Controller and I need to preserve the order of how postiis displayed in the Json output.
So in Posto.class I implemented Comparable interface, overrding the compareTo method
#Override
public int compareTo(Posto o) {
if(this.numeroPosto == o.numeroPosto){
return 0;
} else {
return this.numeroPosto > o.numeroPosto ? 1 : -1;
}
Now, when calling my controller, i got this error from Hibernate:
2016-03-30 16:18:07.486 ERROR [http-nio-8080-exec-6]: HHH000123: IllegalArgumentException in class: it.besmart.models.Client, setter method of property: posti
2016-03-30 16:18:07.486 ERROR [http-nio-8080-exec-6]: HHH000091: Expected type: java.util.SortedSet, actual value: org.hibernate.collection.internal.PersistentSet
How can i solve it? Hibernate changes my SortedSet in a PersistentSet, do I have to use this one to set my posti with the order i want?
The problem is you defined your posti and Luci as concrete SortSet. Hibernate PersistentSet implements generic Set interface. All you need to do is changing SortSet to generic Set and modify getters, setters accordingly.
private Set<Posto> posti;
private Set<Luce> luci;
I want to get my profile in class Tournee (profil_tournee) list based on my tours ("tournee"). However, I have an exception. Can anyone help me?
Exception in thread "AWT-EventQueue-0"
java.lang.IllegalArgumentException: Type specified for TypedQuery
[fr.galettedebroons.domain.Profil] is incompatible with query return
type [interface java.util.Collection]
Request:
List<List<Profil>> listProfil = Arrays.asList(manager_.createQuery("select t.profil_tournee "
+ "FROM Tournee t WHERE t.nom LIKE :tournee", Profil.class)
.setParameter("tournee", tournee)
.getResultList());
Model :
#Entity
public class Tournee {
private int id;
private String nom;
private boolean lundi = false;
private boolean mardi = false;
private boolean mercredi = false;
private boolean jeudi = false;
private boolean vendredi = false;
private boolean samedi = false;
private boolean dimanche = false;
private List<Profil> profil_tournee;
public Tournee(){}
public Tournee(String nom, boolean lundi, boolean mardi, boolean mercredi, boolean jeudi,
boolean vendredi, boolean samedi, boolean dimanche, List<Profil> profil_tournee) {
this.nom = nom;
this.lundi = lundi;
this.mardi = mardi;
this.mercredi = mercredi;
this.jeudi = jeudi;
this.vendredi = vendredi;
this.samedi = samedi;
this.dimanche = dimanche;
this.profil_tournee = profil_tournee;
}
public Tournee(String nom, boolean lundi, boolean mardi, boolean mercredi, boolean jeudi,
boolean vendredi, boolean samedi, boolean dimanche) {
this.nom = nom;
this.lundi = lundi;
this.mardi = mardi;
this.mercredi = mercredi;
this.jeudi = jeudi;
this.vendredi = vendredi;
this.samedi = samedi;
this.dimanche = dimanche;
}
#Id #GeneratedValue(strategy = GenerationType.AUTO)
public int getId() {
return id;
}
public void setId(int id_tournee) {
this.id = id_tournee;
}
public String getNom() {
return nom;
}
public void setNom(String nom) {
this.nom = nom;
}
public boolean isLundi() {
return lundi;
}
public void setLundi(boolean lundi) {
this.lundi = lundi;
}
public boolean isMardi() {
return mardi;
}
public void setMardi(boolean mardi) {
this.mardi = mardi;
}
public boolean isMercredi() {
return mercredi;
}
public void setMercredi(boolean mercredi) {
this.mercredi = mercredi;
}
public boolean isJeudi() {
return jeudi;
}
public void setJeudi(boolean jeudi) {
this.jeudi = jeudi;
}
public boolean isVendredi() {
return vendredi;
}
public void setVendredi(boolean vendredi) {
this.vendredi = vendredi;
}
public boolean isSamedi() {
return samedi;
}
public void setSamedi(boolean samedi) {
this.samedi = samedi;
}
public boolean isDimanche() {
return dimanche;
}
public void setDimanche(boolean dimanche) {
this.dimanche = dimanche;
}
#OneToMany(mappedBy="profil_tournee", cascade=CascadeType.PERSIST)
public List<Profil> getProfil_tournee() {
return profil_tournee;
}
public void setProfil_tournee(List<Profil> profil_tournee) {
this.profil_tournee = profil_tournee;
}
}
#Entity
public class Profil {
private String code_client;
private Client client_profil;
private Gamme gamme_profil;
private List<Livraison> livraison_profil;
private Boolean actif;
private Tournee profil_tournee;
private List<MargeLivraison> marge_profil;
private List<Prevision> prevision_profil;
public Profil(){}
public Profil(Gamme code_gamme, List<Livraison> livraison, Boolean actif) {
this.gamme_profil = code_gamme;
this.livraison_profil = livraison;
this.actif = actif;
}
#Id
public String getCode_client() {
return code_client;
}
public void setCode_client(String code_client) {
this.code_client = code_client;
}
public Boolean getActif() {
return actif;
}
public void setActif(Boolean actif) {
this.actif = actif;
}
#ManyToOne
public Gamme getGamme_profil() {
return gamme_profil;
}
public void setGamme_profil(Gamme gamme_profil) {
this.gamme_profil = gamme_profil;
}
#OneToMany(mappedBy="livraison_profil", cascade=CascadeType.PERSIST)
public List<Livraison> getLivraison_profil() {
return livraison_profil;
}
public void setLivraison_profil(List<Livraison> livraison_profil) {
this.livraison_profil = livraison_profil;
}
#ManyToOne
public Client getClient_profil() {
return client_profil;
}
public void setClient_profil(Client client) {
this.client_profil = client;
}
#ManyToOne
public Tournee getProfil_tournee() {
return profil_tournee;
}
public void setProfil_tournee(Tournee profil_tournee) {
this.profil_tournee = profil_tournee;
}
#OneToMany(mappedBy="marge_profil", cascade=CascadeType.PERSIST)
public List<MargeLivraison> getMarge_profil() {
return marge_profil;
}
public void setMarge_profil(List<MargeLivraison> marge_profil) {
this.marge_profil = marge_profil;
}
#OneToMany(mappedBy="prevision_profil", cascade=CascadeType.PERSIST)
public List<Prevision> getPrevision_profil() {
return prevision_profil;
}
public void setPrevision_profil(List<Prevision> prevision_profil) {
this.prevision_profil = prevision_profil;
}
Your expected result list will contain elements that are list of profiles, not profiles.
I would replace Profil.class by List.class for the Query creation :
List<List<Profil>> listProfil = Arrays.asList(manager_.createQuery("select t.profil_tournee "
+ "FROM Tournee t WHERE t.nom LIKE :tournee", List.class)
.setParameter("tournee", tournee)
.getResultList());
Your error gives you a hint that the returning type should be consistent with declared type when invoking EntityManager.createQuery(query, Type) method:
List<SomeType> em.createQuery("SELECT s FROM SomeType", SomeType.class);
However your real problem is that your query is illegal. In JPA collection-valued expressions cannot be part of SELECT clause. Please see another answer of mine https://stackoverflow.com/a/25890863/3796586.
The solution in your case would be to reverse the query like this:
List<Profil> result = em.createQuery("SELECT p FROM Profil p WHERE" +
"p.profil_tournee.norm LIKE :tournee", Profil.class)
.setParameter("tournee", tournee)
.getResultList());
I'm facing the following problem. Imagine this data model:
As you can see project_function entity is association many to many entity.
Here are my entity classes.
PeronalCard:
#Entity
#Table(name = "personal_card")
#XmlRootElement
public class PersonalCard implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Basic(optional = false)
#Column(name = "id_person")
private Integer idPerson;
/* SOME OTHER ATTRIBUTES */
#OneToMany(cascade = CascadeType.ALL, mappedBy = "projectFunctionPK.personalCard")
private Set<ProjectFunction> projectFunctionSet;
public PersonalCard() {
}
public Integer getIdPerson() {
return idPerson;
}
public void setIdPerson(Integer idPerson) {
this.idPerson = idPerson;
}
#XmlTransient
public Set<ProjectFunction> getProjectFunctionSet() {
return projectFunctionSet;
}
public void setProjectFunctionSet(Set<ProjectFunction> projectFunctionSet) {
this.projectFunctionSet = projectFunctionSet;
}
#Override
public int hashCode() {
int hash = 0;
hash += (idPerson != null ? idPerson.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 PersonalCard)) {
return false;
}
PersonalCard other = (PersonalCard) object;
if ((this.idPerson == null && other.idPerson != null) || (this.idPerson != null && !this.idPerson.equals(other.idPerson))) {
return false;
}
return true;
}
}
Project:
#Entity
#Table(name = "project")
#XmlRootElement
public class Project implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Basic(optional = false)
#Column(name = "id_project")
private Integer idProject;
/* OTHER ATTRIBUTES*/
#OneToMany(cascade = CascadeType.ALL, mappedBy = "projectFunctionPK.project")
private Set<ProjectFunction> projectFunctionSet;
public Project() {
}
public Integer getIdProject() {
return idProject;
}
public void setIdProject(Integer idProject) {
this.idProject = idProject;
}
#XmlTransient
public Set<ProjectFunction> getProjectFunctionSet() {
return projectFunctionSet;
}
public void setProjectFunctionSet(Set<ProjectFunction> projectFunctionSet) {
this.projectFunctionSet = projectFunctionSet;
}
#Override
public int hashCode() {
int hash = 0;
hash += (idProject != null ? idProject.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 Project)) {
return false;
}
Project other = (Project) object;
if ((this.idProject == null && other.idProject != null) || (this.idProject != null && !this.idProject.equals(other.idProject))) {
return false;
}
return true;
}
}
ProjectFunction:
#Entity
#Table(name = "project_function")
#XmlRootElement
#AssociationOverrides({
#AssociationOverride(name = "projectFunctionPK.project",
joinColumns = #JoinColumn(name = "id_project", referencedColumnName = "id_project")),
#AssociationOverride(name = "projectFunctionPK.personalCard",
joinColumns = #JoinColumn(name = "id_person", referencedColumnName = "id_person")) })
public class ProjectFunction implements Serializable {
private static final long serialVersionUID = 1L;
protected ProjectFunctionPK projectFunctionPK;
private Date fromd;
private Date tod;
public ProjectFunction() {
this.projectFunctionPK = new ProjectFunctionPK();
}
#EmbeddedId
public ProjectFunctionPK getProjectFunctionPK() {
return projectFunctionPK;
}
public void setProjectFunctionPK(ProjectFunctionPK projectFunctionPK) {
this.projectFunctionPK = projectFunctionPK;
}
#Column(name = "fromd")
#Temporal(TemporalType.DATE)
public Date getFromd() {
return fromd;
}
public void setFromd(Date fromd) {
this.fromd = fromd;
}
#Column(name = "tod")
#Temporal(TemporalType.DATE)
public Date getTod() {
return tod;
}
public void setTod(Date tod) {
this.tod = tod;
}
#Transient
public Project getProject() {
return projectFunctionPK.getProject();
}
public void setProject(Project project) {
this.projectFunctionPK.setProject(project);
}
#Transient
public PersonalCard getPersonalCard() {
return this.projectFunctionPK.getPersonalCard();
}
public void setPersonalCard(PersonalCard personalCard) {
//this.personalCard = personalCard;
this.projectFunctionPK.setPersonalCard(personalCard);
}
#Override
public int hashCode() {
int hash = 0;
hash += (projectFunctionPK != null ? projectFunctionPK.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 ProjectFunction)) {
return false;
}
ProjectFunction other = (ProjectFunction) object;
if ((this.projectFunctionPK == null && other.projectFunctionPK != null) || (this.projectFunctionPK != null && !this.projectFunctionPK.equals(other.projectFunctionPK))) {
return false;
}
return true;
}
}
And finally my embedded Primary Key ProjectFunctionPK:
#Embeddable
public class ProjectFunctionPK implements Serializable {
#ManyToOne
private Project project;
#ManyToOne
private PersonalCard personalCard;
public ProjectFunctionPK() {
}
public Project getProject() {
return project;
}
public void setProject(Project project) {
this.project = project;
}
public PersonalCard getPersonalCard() {
return personalCard;
}
public void setPersonalCard(PersonalCard personalCard) {
this.personalCard = personalCard;
}
#Override
public int hashCode() {
int hash = 3;
hash = 41 * hash + Objects.hashCode(this.project);
hash = 41 * hash + Objects.hashCode(this.personalCard);
return hash;
}
#Override
public boolean equals(Object obj) {
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
final ProjectFunctionPK other = (ProjectFunctionPK) obj;
if (!Objects.equals(this.project, other.project)) {
return false;
}
if (!Objects.equals(this.personalCard, other.personalCard)) {
return false;
}
return true;
}
}
First I save the Project. It works fine. Then i want to connect it using project_function - so I create project_function set them existing project and personal_card and after trying to persist I get following error:
Caused by: org.postgresql.util.PSQLException: ERROR: column projectfun0_.personalcard does not exist
Position: 8
at org.postgresql.core.v3.QueryExecutorImpl.receiveErrorResponse(QueryExecutorImpl.java:2198)
at org.postgresql.core.v3.QueryExecutorImpl.processResults(QueryExecutorImpl.java:1927)
at org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:255)
at org.postgresql.jdbc2.AbstractJdbc2Statement.execute(AbstractJdbc2Statement.java:561)
at org.postgresql.jdbc2.AbstractJdbc2Statement.executeWithFlags(AbstractJdbc2Statement.java:419)
at org.postgresql.jdbc2.AbstractJdbc2Statement.executeQuery(AbstractJdbc2Statement.java:304)
at org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.extract(ResultSetReturnImpl.java:82)
... 119 more
So apparently Hibernate does not know projectfun0_.personalcard . But I dont know why. Do you see any error in the entity classes? Or could the error possibly be somewhere else ?
Thank you very much for all your answers :)
EmbeddedId documentation
Relationship mappings defined within an embedded id class are not supported.
So, ProjectFunctionPK should contain only basic mappings, and entity mappings should be done in the entity itself. Here are some related posts
https://stackoverflow.com/a/9760808/4074715
https://stackoverflow.com/a/4692144/4074715