How does hibernate decide update/save associated objects - java

Anyone could help me explain about hibernate. How do it save/update child objects when we save/update parent object. Especially, Child Object with #EmbeddedId look like my mapping
#Embeddable
public class BomLevelKey implements Serializable{
/**
*
*/
private static final long serialVersionUID = 1L;
Item item;
long organizationId;
Item componentItem;
#Column(name = "organization_id")
public long getOrganizationId() {
return organizationId;
}
public void setOrganizationId(long organizationId) {
this.organizationId = organizationId;
}
#ManyToOne
#JoinColumn(name = "inventory_item_id")
public Item getItem() {
return item;
}
public void setItem(Item item) {
this.item = item;
}
#ManyToOne
#JoinColumn(name = "component_item_id")
public Item getComponentItem() {
return componentItem;
}
public void setComponentItem(Item componentItem) {
this.componentItem = componentItem;
}
#Override
public boolean equals(Object obj) {
if (obj == null || !(obj instanceof BomLevelKey)) {
return false;
}
BomLevelKey key = (BomLevelKey) obj;
if (key.getItem().getInventoryItemID() == this.getItem()
.getInventoryItemID()
&& key.getComponentItem().getInventoryItemID() == this
.getComponentItem().getInventoryItemID()
&& key.getOrganizationId() == this.getOrganizationId()) {
return true;
}
return false;
}
}
#Entity
#Table(name = "es_bom_levels", schema = "xx_vms")
public class ItemConversionAttributes implements Serializable{
/**
*
*/
private static final long serialVersionUID = 1L;
private Double componentRoutingYield;
private Double forwardRoutingYield;
private Double conversionFactor;
private Double cumulativeLeadTime;
private Integer organizationID;
private Item componentItem;
private BomLevelKey id;
#EmbeddedId
public BomLevelKey getId() {
return id;
}
public void setId(BomLevelKey id) {
this.id = id;
}
/**
* #hibernate.property
* column="component_routing_yield"
*
**/
#Column(name="component_routing_yield")
public Double getComponentRoutingYield(){ return componentRoutingYield; }
public void setComponentRoutingYield(Double componentRoutingYield){ this.componentRoutingYield= componentRoutingYield; }
/**
* #hibernate.property
* column="forward_routing_yield"
*
**/
#Column(name="forward_routing_yield")
public Double getForwardRoutingYield(){ return forwardRoutingYield; }
public void setForwardRoutingYield(Double forwardRoutingYield){ this.forwardRoutingYield = forwardRoutingYield; }
/**
* #hibernate.property
* column="conversion_factor"
*
**/
#Column(name="conversion_factor")
public Double getConversionFactor(){ return conversionFactor; }
public void setConversionFactor(Double conversionFactor){ this.conversionFactor = conversionFactor; }
/**
* #hibernate.property
* column="cumulative_lead_time"
*
**/
#Column(name="cumulative_lead_time")
public Double getCumulativeLeadTime(){ return cumulativeLeadTime; }
public void setCumulativeLeadTime(Double cumulativeLeadTime){ this.cumulativeLeadTime = cumulativeLeadTime; }
/**
* #hibernate.property
* column="organization_id"
*
**/
#Column(name="organization_id", insertable = false, updatable = false)
public Integer getOrganizationID(){ return organizationID; }
public void setOrganizationID(Integer organizationID){ this.organizationID = organizationID; }
/**
* #hibernate.many-to-one
* column="component_item_id"
* insert="false"
* update="false"
*
**/
#ManyToOne(targetEntity=Item.class)
#JoinColumn(name="component_item_id", insertable=false, updatable=false)
#NotFound(action=NotFoundAction.IGNORE)
public Item getComponentItem(){ return componentItem; }
public void setComponentItem(Item componentItem){ this.componentItem = componentItem; }
}
In class Item, I've this mapping:
#OneToMany(mappedBy = "id.item")
#MapKey(name = "id.componentItem")
public Map<Item, ItemConversionAttributes> getConversionAttributes(){ return conversionAttributes; }
public void setConversionAttributes(Map<Item, ItemConversionAttributes> conversionAttributes) {
this.conversionAttributes = conversionAttributes;
}
save/update do nothing.

Its based on DAO Objects primary key's value.
If its set default value , hibernate will add otherwise update

Related

JPA Hibernate Saving ManyToOne field is null

I have a servlet method that creates a JPA entity and assigns an existing JPA entity to a #ManyToOne field
When I persist it, it saves the entity but the foreign key is NULL. Why?
Here are my entities:
#Entity
public class SimpleEntity implements java.io.Serializable {
/**
*
*/
private static final long serialVersionUID = -5930519292861829894L;
#Id #GeneratedValue
Long id;
String name;
#ManyToOne()
#JoinColumn(name="simple_entity_group_id", insertable=false, updatable=false, nullable=true)
SimpleEntityGroup group;
/**
*
*/
public SimpleEntity() {
}
/**
* #return the id
*/
public Long getId() {
return this.id;
}
/**
* #param id the id to set
*/
public void setId(Long id) {
this.id = id;
}
/**
* #return the name
*/
public String getName() {
return this.name;
}
/**
* #param name the name to set
*/
/**
* #param name the name to set
*/
public void setName(String name) {
this.name = name;
}
/* (non-Javadoc)
* #see java.lang.Object#toString()
*/
#Override
public String toString() {
return "SimpleEntity [id=" + this.id + ", name=" + this.name + ", group=" + this.getGroup() + "]";
}
/**
* #return the group
*/
public SimpleEntityGroup getGroup() {
return this.group;
}
/**
* #param group the group to set
*/
public void setGroup(SimpleEntityGroup group) {
this.group = group;
}
}
#Entity
public class SimpleEntityGroup implements Serializable {
/**
*
*/
private static final long serialVersionUID = -1680386377742600266L;
#Id #GeneratedValue
Long id;
String name;
#OneToMany(mappedBy="group")
java.util.List<SimpleEntity> simpleEntities;
/**
*
*/
public SimpleEntityGroup() {
simpleEntities = new ArrayList<SimpleEntity>();
}
/**
* #return the id
*/
public Long getId() {
return this.id;
}
/**
* #param id the id to set
*/
public void setId(Long id) {
this.id = id;
}
/**
* #return the name
*/
public String getName() {
return this.name;
}
/**
* #param name the name to set
*/
public void setName(String name) {
this.name = name;
}
/**
* #return the simpleEntities
*/
public java.util.List<SimpleEntity> getSimpleEntities() {
return this.simpleEntities;
}
/**
* #param simpleEntities the simpleEntities to set
*/
public void setSimpleEntities(java.util.List<SimpleEntity> simpleEntities) {
this.simpleEntities = simpleEntities;
}
public void addSimpleEntity(SimpleEntity e) {
if(this.getSimpleEntities() != null) {
this.getSimpleEntities().add(e);
return;
}
throw new RuntimeException("Entity list is null!!!");
}
/* (non-Javadoc)
* #see java.lang.Object#toString()
*/
#Override
public String toString() {
return "SimpleEntityGroup [id=" + this.id + ", name=" + this.name + "]";
}
/* (non-Javadoc)
* #see java.lang.Object#hashCode()
*/
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((this.id == null) ? 0 : this.id.hashCode());
return result;
}
/* (non-Javadoc)
* #see java.lang.Object#equals(java.lang.Object)
*/
#Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
SimpleEntityGroup other = (SimpleEntityGroup) obj;
if (this.id == null) {
if (other.id != null) {
return false;
}
} else if (!this.id.equals(other.id)) {
return false;
}
return true;
}
}
Here is how I persist it:
SimpleEntity e = new SimpleEntity();
e.setName("Mike");
SimpleEntityGroup g = dao.getGroupById(1l);
e.setGroup(g);
dao.persist(e);
System.out.println(e);
System.out.println(dao.findAll());
Here is the output from the Java code, the group is set on the entry but it is not saved. Why?!?!
SimpleEntity [id=4, name=Mike, group=SimpleEntityGroup [id=1,
name=Group 1]]
[SimpleEntity [id=4, name=Mike, group=null]]
Of course I just figured it out, needed to do:
#ManyToOne()
#JoinColumn(name="simple_entity_group_id")
SimpleEntityGroup group;
-- Got rid of the insert=false, update=false
You only posted your child class but I think will be better if you also include the parent class code. I had the same problem when I tried make saves in cascade using only auto generated ids. I could solve it using the next annotations.
In my parent class I have
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name="IDCOBPRES", unique=true, nullable=false)
public Long getIdcobpres() {
return this.idcobpres;
}
//....
#OneToMany(fetch=FetchType.LAZY, mappedBy="cobpresGestion")
#Cascade({CascadeType.ALL})
public Set<CobpresOptionDet> getCobpresOptionDets() {
return this.cobpresOptionDets;
}
In my child class I have
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name="IDOPTIONDET", unique=true, nullable=false)
public Long getIdoptiondet() {
return this.idoptiondet;
}
//...
#ManyToOne(fetch=FetchType.LAZY, optional=false)
#JoinColumn(name="IDCOBPRES", nullable=false, insertable=true, updatable=true)
public CobpresGestion getCobpresGestion() {
return this.cobpresGestion;
}

ManyToMany relationship update?

I'm trying persist a relationship #ManyToMany. I created an association class using #IdClass for association, but doesn't work using persist, works only using merge. I need add others registers but using merge doesn't work because the register is always updated.
I want my table in the database looks like this
id_aluno | id_graduacao | grau | date
1 1 FIRST 2014-08-02
1 1 SECOND 2014-08-02
1 1 THIRD 2014-08-02
Entities
#Entity
#Table(name="aluno")
public class Aluno implements Serializable{
private static final long serialVersionUID = 1L;
#Id #GeneratedValue
private Integer id;
//informacoes gerais
#NotNull
private String nome;
//historico de graduacao
#OneToMany(mappedBy = "aluno")
private List<HistoricoDeGraduacao> listaHistoricoGraduacao;
public Aluno(){}
/** adiciona lista de HistoricoDeGraduacao para aluno */
public void addListaHistoricoGraduacao(HistoricoDeGraduacao hdg){
if(listaHistoricoGraduacao == null){
listaHistoricoGraduacao = new ArrayList<HistoricoDeGraduacao>();
}
listaHistoricoGraduacao.add(hdg);
}
public List<HistoricoDeGraduacao> getListaHistoricoGraduacao() {
return listaHistoricoGraduacao;
}
///gets e sets
#Entity
#Table(name="graduacao")
public class Graduacao implements Serializable{
private static final long serialVersionUID = 1L;
#Id #GeneratedValue
private Integer id;
#NotNull #Column(unique = true)
private String graduacao;
#ElementCollection
#CollectionTable(name="graus_graduacao", joinColumns=#JoinColumn(name="id_graduacao"))
#Column(name="graus")
private List<String> graus;
#OneToMany(mappedBy = "graduacao")
private List<HistoricoDeGraduacao> listaHistoricoGraduacao;
public Graduacao() {
}
/** adiciona historicodegraduacao a graduacao */
public void addHistoricoDeGraduacao(HistoricoDeGraduacao hdg){
if(listaHistoricoGraduacao == null){
listaHistoricoGraduacao = new ArrayList<HistoricoDeGraduacao>();
}
listaHistoricoGraduacao.add(hdg);
}
public List<HistoricoDeGraduacao> getListaHistoricoGraduacao() {
return listaHistoricoGraduacao;
}
//gets e sets
public class HistoricoDeGraduacaoId implements Serializable {
private static final long serialVersionUID = 1L;
private Aluno aluno;
private Graduacao graduacao;
public Aluno getAluno() {
return aluno;
}
public void setAluno(Aluno aluno) {
this.aluno = aluno;
}
public Graduacao getGraduacao() {
return graduacao;
}
public void setGraduacao(Graduacao graduacao) {
this.graduacao = graduacao;
}
#Entity
#IdClass(HistoricoDeGraduacaoId.class)
public class HistoricoDeGraduacao implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#ManyToOne
#JoinColumn(name = "id_aluno")
private Aluno aluno;
#Id
#ManyToOne
#JoinColumn(name="id_graduacao")
private Graduacao graduacao;
private String grau;
#Temporal(TemporalType.DATE)
private Date dataGraduou;
public HistoricoDeGraduacao() {
}
//gets e sets
//persisting
public void insert(){
//doesn't work using persist, works only with merge but record is always updated and not added
em.getTransaction().begin();
Aluno a = new Aluno();
a.setId(1); //aluno have Id
Graduacao g = new Graduacao();
g.setId(1); //graduacao have Id
HistoricoDeGraduacao hdg1 = new HistoricoDeGraduacao();
hdg1.setAluno(a);
hdg1.setGraduacao(g);
hdg1.setDataGraduou(new Date());
hdg1.setGrau("FIRST");
a.addHistoricoDeGraduacao(hdg1);
g.addHistoricoDeGraduacao(hdg1);
em.persist(hdg1);
em.getTransaction().commit();
HistoricoDeGraduacao hdg2 = new HistoricoDeGraduacao();
hdg2.setAluno(a);
hdg2.setGraduacao(g);
hdg2.setDataGraduou(new Date());
hdg2.setGrau("SECOND");
a.addHistoricoDeGraduacao(hdg2);
g.addHistoricoDeGraduacao(hdg2);
em.persist(hdg2);
em.getTransaction().commit();
HistoricoDeGraduacao hdg3 = new HistoricoDeGraduacao();
hdg3.setAluno(a);
hdg3.setGraduacao(g);
hdg3.setDataGraduou(new Date());
hdg3.setGrau("THIRD");
a.addHistoricoDeGraduacao(hdg3);
g.addHistoricoDeGraduacao(hdg3);
em.persist(hdg3);
em.getTransaction().commit();
em.close();
}
Using persist doesn't work, using merge works but the record is always updated and not add new records how I need.
Any idea how to I do this ?
after days searching and trying some solution, finally works !
here how I did
#Entity
#Table(name="aluno")
public class Aluno implements Serializable{
private static final long serialVersionUID = 1L;
#Id #GeneratedValue
private Integer id;
//informacoes gerais
#NotNull
private String nome;
//historico de graduacao
#OneToMany(mappedBy = "aluno", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
private List<HistoricoDeGraduacao> listaHistoricoGraduacao;
public Aluno() {
}
public void addListaHistoricoGraduacao(HistoricoDeGraduacao hdg){
if(listaHistoricoGraduacao == null){
listaHistoricoGraduacao = new ArrayList<HistoricoDeGraduacao>();
}
listaHistoricoGraduacao.add(hdg);
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getNome() {
return nome;
}
public void setNome(String nome) {
this.nome = nome;
}
public List<HistoricoDeGraduacao> getListaHistoricoGraduacao() {
return listaHistoricoGraduacao;
}
public void setListaHistoricoGraduacao(List<HistoricoDeGraduacao> listaHistoricoGraduacao) {
this.listaHistoricoGraduacao = listaHistoricoGraduacao;
}
#Override
public int hashCode() {
int hash = 7;
return hash;
}
#Override
public boolean equals(Object obj) {
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
final Aluno other = (Aluno) obj;
return true;
}
}
#Entity
#Table(name="graduacao")
public class Graduacao implements Serializable{
private static final long serialVersionUID = 1L;
#Id #GeneratedValue
private Integer id;
#NotNull #Column(unique = true)
private String graduacao;
#ElementCollection
#CollectionTable(name="graus_graduacao", joinColumns=#JoinColumn(name="id_graduacao"))
#Column(name="graus")
private List<String> graus;
#OneToMany(mappedBy = "graduacao", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
private List<HistoricoDeGraduacao> listaHistoricoGraduacao;
public Graduacao() {
}
public Graduacao(Integer id, String graduacao, List<String> graus) {
this.id = id;
this.graduacao = graduacao;
this.graus = graus;
}
/** adiciona historicodegraduacao a graduacao */
public void addHistoricoDeGraduacao(HistoricoDeGraduacao hdg){
if(listaHistoricoGraduacao == null){
listaHistoricoGraduacao = new ArrayList<HistoricoDeGraduacao>();
}
listaHistoricoGraduacao.add(hdg);
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getGraduacao() {
return graduacao;
}
public void setGraduacao(String graduacao) {
this.graduacao = graduacao;
}
public List<String> getGraus() {
return graus;
}
public void setGraus(List<String> graus) {
this.graus = graus;
}
public List<HistoricoDeGraduacao> getListaHistoricoGraduacao() {
return listaHistoricoGraduacao;
}
public void setListaHistoricoGraduacao(List<HistoricoDeGraduacao> listaHistoricoGraduacao) {
this.listaHistoricoGraduacao = listaHistoricoGraduacao;
}
public String toString(){
return graduacao;
}
}
#Embeddable
public class HistoricoDeGraduacaoId implements Serializable {
private static final long serialVersionUID = 1L;
#JoinColumn(name="EMP_ID")
private Integer id;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
#Override
public boolean equals(Object obj) {
return super.equals(obj); //To change body of generated methods, choose Tools | Templates.
}
#Override
public int hashCode() {
return super.hashCode(); //To change body of generated methods, choose Tools | Templates.
}
}
#Entity
public class HistoricoDeGraduacao implements Serializable {
private static final long serialVersionUID = 1L;
#EmbeddedId
HistoricoDeGraduacaoId pk;
#ManyToOne(cascade = CascadeType.ALL)
#JoinColumn(name = "id_aluno")
private Aluno aluno;
#ManyToOne(cascade = CascadeType.ALL)
#JoinColumn(name="id_graduacao")
private Graduacao graduacao;
private String grau;
#Temporal(TemporalType.DATE)
private Date dataGraduou;
public HistoricoDeGraduacao() {
}
public void begin(){
//instancia pk
pk = new HistoricoDeGraduacaoId();
//aqui insiro o id
pk.setId(new HistoricoDeGraduacaoDAO().getIndex());
}
public HistoricoDeGraduacaoId getPk() {
return pk;
}
public void setPk(HistoricoDeGraduacaoId pk) {
this.pk = pk;
}
public Aluno getAluno() {
return aluno;
}
public void setAluno(Aluno aluno) {
this.aluno = aluno;
}
public Graduacao getGraduacao() {
return graduacao;
}
public void setGraduacao(Graduacao graduacao) {
this.graduacao = graduacao;
}
public String getGrau() {
return grau;
}
public void setGrau(String grau) {
this.grau = grau;
}
public Date getDataGraduou() {
return dataGraduou;
}
public void setDataGraduou(Date dataGraduou) {
this.dataGraduou = dataGraduou;
}
#Override
public int hashCode() {
int hash = 3;
hash = 59 * hash + Objects.hashCode(this.aluno);
hash = 59 * hash + Objects.hashCode(this.graduacao);
return hash;
}
#Override
public boolean equals(Object obj) {
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
final HistoricoDeGraduacao other = (HistoricoDeGraduacao) obj;
if (!Objects.equals(this.aluno, other.aluno)) {
return false;
}
if (!Objects.equals(this.graduacao, other.graduacao)) {
return false;
}
return true;
}
}
//aqui meu jframe com seus componentes, pegando valores montando tudo para ser salvo
historico.setDataGraduou(jdp_dataGraduou.getDate());
historico.setGrau(jl_graus.getSelectedValue().toString());
//pega graduacao do jcombobox
Graduacao g = (Graduacao)cbx_graduacao.getSelectedItem();
historico.setGraduacao(g);
//bean aluno
historico.setAluno(bean);
//add a listas
bean.addListaHistoricoGraduacao(historico);
g.addHistoricoDeGraduacao(historico);
//inicia instancia de pk e insere o proximo id
historico.begin();
//salva tudo
new HistoricoDeGraduacaoDAO().update(historico);
//aqui meu DAO
public class HistoricoDeGraduacaoDAO {
private EntityManager em;
public HistoricoDeGraduacaoDAO(){
em = Persistencia.getEntityManager();
}
/** pega o ultimo valor da tabela HistoricoDeGraduacao e adiciona + 1 para o proximo indice */
public Integer getIndex(){
int count = 0;
Query query = em.createQuery("SELECT MAX(hdg.pk.id) FROM HistoricoDeGraduacao hdg");
if(query.getSingleResult() == null){
++count;
}else{
count = (int)query.getSingleResult() + 1;
}
return count;
}
/** executa update */
public void update(HistoricoDeGraduacao historico){
try{
em.getTransaction().begin();
em.merge(historico);
em.getTransaction().commit();
}catch(PersistenceException e){
JOptionPane.showMessageDialog(null, e.getMessage(), "Erro", JOptionPane.ERROR_MESSAGE);
}finally{
em.close();
}
}
}
And result is:

There are multiple properties indexed against the same field name ..., but with different indexing settings. The behaviour is undefined

Getting the following in my log when I run my Hibernate Search application:
WARN 23 Jun 2014 15:08:51,623 org.hibernate.search.engine.metadata.impl.TypeMetadata:339 - HSEARCH000120: There are multiple properties indexed against the same field name 'foo.bar', but with different indexing settings. The behaviour is undefined.
I see that the warning is being logged from:
private Map<String, DocumentFieldMetadata> keyFieldMetadata(Set<PropertyMetadata> propertyMetadataSet) {
Map<String, DocumentFieldMetadata> tmpMap = new HashMap<String, DocumentFieldMetadata>();
for ( PropertyMetadata propertyMetadata : propertyMetadataSet ) {
for ( DocumentFieldMetadata documentFieldMetadata : propertyMetadata.getFieldMetadata() ) {
DocumentFieldMetadata oldFieldMetadata = tmpMap.put(
documentFieldMetadata.getName(),
documentFieldMetadata
);
if ( oldFieldMetadata != null ) {
if ( !documentFieldMetadata.getIndex().equals( oldFieldMetadata.getIndex() ) ) {
**log.inconsistentFieldConfiguration( documentFieldMetadata.getName()** );
}
}
}
}
for ( DocumentFieldMetadata documentFieldMetadata : classBridgeFields ) {
tmpMap.put( documentFieldMetadata.getName(), documentFieldMetadata );
}
if ( idPropertyMetadata != null ) {
for ( DocumentFieldMetadata documentFieldMetadata : idPropertyMetadata.getFieldMetadata() ) {
tmpMap.put( documentFieldMetadata.getName(), documentFieldMetadata );
}
}
return Collections.unmodifiableMap( tmpMap );
}
but I'm having trouble figuring out the purpose of this code, or how my code could be causing it to meet the condition. It appears to only be happening on fields annotated with #IndexedEmbedded I've Googled and found nothing for the error.
I assume that this has always been an issue in the code, but I just recently updated from Hibernate Search 4.2.0.Final to 4.5.1.Final, and this is when the warning began to appear.
UPDATE
#Entity
#Table(name = "data_providers")
#Immutable
#Embeddable
#Cache(usage = CacheConcurrencyStrategy.READ_ONLY)
public class EDataProvider {
private static final long serialVersionUID = -4207808146855081627L;
public static final String FIELD_ASSOCIATIONS = "associations.";
public static final String FIELD_ID = "id";
private List<EDataProvider> associatedProviders;
private Long id;
private boolean isInternal;
private String name;
private Float priority;
public EDataProvider() {
this(null, null);
}
/**
* #param name
* #param id
*/
public EDataProvider(final String name, final Long id) {
super();
this.name = name;
this.id = id;
associatedProviders = new Vector<EDataProvider>();
}
/**
* #param newProvider
*/
public void addAssociatedProvider(final EDataProvider newProvider) {
associatedProviders.add(newProvider);
}
#Override
public boolean equals(final Object obj) {
if (this == obj) {
return true;
}
if ((obj == null) || !(obj instanceof EDataProvider)) {
return false;
}
final EDataProvider other = (EDataProvider) obj;
if (!ObjectUtil.equals(getId(), other.getId())) {
return false;
}
return true;
}
#ManyToMany(fetch = FetchType.LAZY,
cascade = { CascadeType.PERSIST, CascadeType.MERGE })
#JoinTable(name = "data_provider_associations",
joinColumns = { #JoinColumn(name = "parent_id") },
inverseJoinColumns = { #JoinColumn(name = "child_id") })
#IndexedEmbedded(depth = 1,
prefix = FIELD_ASSOCIATIONS)
#Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
public List<EDataProvider> getAssociatedProviders() {
return associatedProviders;
}
#Id
#Column(name = "id")
#Field(name = FIELD_ID)
public Long getId() {
return id;
}
#Column(name = "name")
public String getName() {
return name;
}
#Column(name = "boost")
public Float getPriority() {
return priority;
}
#Override
public int hashCode() {
return EncodingUtil.makeHashCode(31, getId());
}
#Column(name = "internal")
public boolean isInternal() {
return isInternal;
}
public void removeAssociatedProvider(final EDataProvider newProvider) {
associatedProviders.remove(newProvider);
}
/**
* #param newAssociatedProviders
* the associatedProviders to set
*/
public void setAssociatedProviders(
final List<EDataProvider> newAssociatedProviders) {
associatedProviders = newAssociatedProviders;
}
/**
* #param dataProviderId
* the dataProviderId to set
*/
public void setId(final Long dataProviderId) {
id = dataProviderId;
}
public void setInternal(final boolean isInternal) {
this.isInternal = isInternal;
}
/**
* #param name
* the name to set
*/
public void setName(final String name) {
this.name = name;
}
/**
* #param priority
* the priority to set
*/
public void setPriority(final Float priority) {
this.priority = priority;
}
#Override
public String toString() {
return String.format("provider:{id:%d, name:%s, priority:%f}", id, name,
priority);
}
}
The ID field was annotated in the child object with a #Field annotation as well as included in the parent object's index. The parent object uses a custom analyzer, so there was a conflict in the indexing settings. As soon as I removed the #Field annotation from the child object, the errors went away.

Composite Foreign Key Issue while using Inheritance in JPA

I have a JPA Entity StatsEntity which has a composite primary key that is also as foreign key to another Entity Roster. This is setup as a #OneToOne relationship using #JoinColumns({#JoinColumn...}) annotations.
StatsEntity extends another entity CoreStatsEntity which is setup as #MappedSuperClass where as RosterEntity extends another entity CoreRoster using SINGLE_TABLE inheritance strategy.
#Entity
#Table(name = "Stats")
#IdClass(value = StatsEntity.Key.class)
public class StatsEntity extends CoreStatsEntity implements
Stats {
#Id
private Integer competitionId;
#Id
private Integer playerId;
#Id
private Integer teamId;
#OneToOne
#JoinColumns({
#JoinColumn(name = "competitionId", referencedColumnName = "competitionId", insertable = false, updatable=false),
#JoinColumn(name = "playerId", referencedColumnName = "personId", insertable = false, updatable=false),
#JoinColumn(name = "teamId", referencedColumnName = "teamId", insertable = false, updatable=false) })
private RosterEntity roster;
....
}
StatsEntity.Key
#Embeddable
public static class Key implements Serializable {
private static final long serialVersionUID = -7349082038890396790L;
#Column(name = "competitionId", insertable = false, updatable = false)
private Integer competitionId;
#Column(name = "playerId", insertable = false, updatable = false)
private Integer playerId;
#Column(name = "teamId", insertable = false, updatable = false)
private Integer teamId;
public Key() {
super();
}
public Key(int competitionId, int playerId, int teamId) {
this.competitionId = Integer.valueOf(competitionId);
this.playerId = Integer.valueOf(playerId);
this.teamId = Integer.valueOf(teamId);
}
public int getTeamId() {
return teamId.intValue();
}
public void setTeamId(int teamId) {
this.teamId = Integer.valueOf(teamId);
}
public int getPlayerId() {
return playerId.intValue();
}
public void setPlayerId(int playerId) {
this.playerId = Integer.valueOf(playerId);
}
public int getCompetitionId() {
return competitionId.intValue();
}
public void setCompetitionId(int CompetitionId) {
this.competitionId = Integer.valueOf(CompetitionId);
}
/*
* (non-Javadoc)
*
* #see java.lang.Object#equals(java.lang.Object)
*/
#Override
public boolean equals(Object object) {
if (object == this) {
return true;
}
if (!(object instanceof Key)) {
return false;
}
Key other = (Key) object;
return Utils.equals(other.getTeamId(), this.getTeamId())
&& Utils.equals(other.getPlayerId(), this.getPlayerId())
&& Utils.equals(other.getCompetitionId(),
this.getCompetitionId());
}
/*
* (non-Javadoc)
*
* #see java.lang.Object#hashCode()
*/
#Override
public int hashCode() {
return Utils.hashCode(this.teamId, this.playerId,
this.competitionId);
}
/*
* (non-Javadoc)
*
* #see java.lang.Object#toString()
*/
#Override
public String toString() {
return Utils.toString("CompetitionPlayerStatsEntity.Key",
this.teamId, this.playerId, this.competitionId);
}
}
CoreStatsEntity.java
#MappedSuperclass
public abstract class CoreStatsEntity
{}
RosterEntity
#Entity
#DiscriminatorValue("20")
public class RosterEntity extends
CoreRosterEntity {
//.... attributes, getters, setters
}
CoreRosterEntity.java
#Entity
#DiscriminatorValue("0")
#Table(name="Roster")
#IdClass(CoreRoster.Key.class)
#Inheritance(strategy=InheritanceType.SINGLE_TABLE)
#DiscriminatorColumn(name="discriminator", discriminatorType=DiscriminatorType.INTEGER)
public class CoreRosterEntity {
private static final long serialVersionUID = 1521639115446682871L;
#Id
private Integer competitionId;
#Id
private Integer teamId;
#Id
private Integer playerId;
//.. getters, setters and other attributes
}
CoreRoster.Key.class inside CoreRoster.java
#Embeddable
public static class Key implements Serializable {
private static final long serialVersionUID = 2L;
#Column(name="competitionId", nullable=false)
private Integer competitionId;
#Column(name="teamId", nullable=false)
private Integer teamId;
#Column(name="personId", nullable=false)
private Integer playerId;
public Key() {
super();
}
public Key(int competitionId, int teamId, int playerId) {
this.competitionId = Integer.valueOf(competitionId);
this.teamId = Integer.valueOf(teamId);
this.playerId = Integer.valueOf(playerId);
}
public int getPlayerId() {
return playerId.intValue();
}
public void setPlayerId(int playerId) {
this.playerId = Integer.valueOf(playerId);
}
public int getTeamId() {
return teamId.intValue();
}
public void setTeamId(int teamId) {
this.teamId = Integer.valueOf(teamId);
}
public int getCompetitionId() {
return this.competitionId.intValue();
}
public void setCompetitionId(int competitionId) {
this.competitionId = Integer.valueOf(competitionId);
}
/*
* (non-Javadoc)
* #see java.lang.Object#equals(java.lang.Object)
*/
#Override
public boolean equals(Object object) {
if (object == this) { return true; }
if (!(object instanceof Key)) { return false; }
Key other = (Key) object;
return Utils.equals(other.getCompetitionId(), this.getCompetitionId()) &&
Utils.equals(other.getTeamId(), this.getTeamId()) &&
Utils.equals(other.getPlayerId(), this.getPlayerId());
}
/*
* (non-Javadoc)
* #see java.lang.Object#hashCode()
*/
#Override
public int hashCode() {
return Utils.hashCode(this.competitionId, this.teamId,
this.playerId);
}
/*
* (non-Javadoc)
* #see java.lang.Object#toString()
*/
#Override
public String toString() {
return Utils.toString("CoreRoster.Key",
this.competitionId, this.teamId,
this.playerId);
}
}
When I persist StatsEntity, it gets persisted. But when I try to find it using the primary key it gives me an error:
StatsEntity playerStats = new StatsEntity();
//set all values
this.persist(playerStats);
entityManager.find(StatsEntity.class, playerStats.getId()); //getId returns the composite primary key
java.lang.IllegalArgumentException: Provided id of the wrong type for class com.sports.RosterEntity. Expected: class com.sports.CoreRoster$Key, got class com.espn.sports.StatsEntity$Key
My first question here is, is the #OneToOne mapping I have given correct or not?
If it is correct then why this error appears when I try to find the entity using primarykey.
You haven't posted full source code, especially of your primary key class, but you've mapped foreign key as read-only, which is required when single column is mapped more than once.
I see however that you id columns are exactly the same 3 columns that are foreign key to RosterEntity, rights? In that case this RosterEntity should be your ID, which would simplify your design.
What is the return type of your getId() method? The problem is propably with definition or usage of IdClass.

#ManyToMany association isn't inserted in the second table

I want to insert data into a table that is associated with another table in a relationship ManyToMany. When I insert the data, it is inserted into the table but the association with the other data that is in the second table is not. This is a Java EE application using JSF2+Spring+Hibernate.
Here is the entity:
#Entity
#Table(name="USER")
public class User {
private int id;
private String nom;
private Set<Formation> mesformations;
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "USER_ID")
public int getId() {
return id;
}
/**
* #param id the id to set
*/
public void setId(int id) {
this.id = id;
}
/**
* #return the nom
*/
#Column(name="NOM",length=50)
public String getNOM() {
return nom;
}
/**
* #param nom the nom to set
*/
public void setNom(String nom) {
this.nom = nom;
}
/**
* #return the mesFormations
*/
#ManyToMany
#Cascade({CascadeType.SAVE_UPDATE, CascadeType.MERGE})
#JoinTable(name = "USER_FORM",
joinColumns = #JoinColumn(name = "user_id",
referencedColumnName = "USER_ID"),
inverseJoinColumns = #JoinColumn(name = "form_id", referencedColumnName = "ID"))
public Set<Formation> getMesFormations() {
return mesFormations;
}
/**
* #param mesFormations the mesFormations to set
*/
public void setMesFormations(Set<Formation> mesFormations) {
this.mesFormations = mesFormations;
}
public void addToFormation(Formation formation) {
if(mesFormation==null)
{
mesFormations=new HashSet<Formation>();
}
mesFormations.add(formation);
}
.....
}
Formation.java
#Entity
#Table(name="Foramtion")
public class Formation {
private int id;
private String nomFormation;
private int nombreMatiere;
private Set<User> mesUsers;
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "ID")
public int getId() {
return id;
}
/**
* #param id the id to set
*/
public void setId(int id) {
this.id = id;
}
/**
* #return the mesUsers
*/
#ManyToMany(mappedBy = "mesFormations",fetch=FetchType.LAZY)
#Cascade({CascadeType.SAVE_UPDATE, CascadeType.MERGE})
public Set<User> getMesUsers() {
return mesUsers;
}
/**
* #param mesUsers the mesUsers to set
*/
public void setMesUsers(Set<User> mesUsers) {
this. mesUsers = mesUsers;
}
/**
* #return the nomFormation
*/
#Column(name="NOM_FORMATION",length=50,unique=true)
public String getNomFormation() {
return nomForamtion;
}
/**
* #param nomFormation the nomForamtion to set
*/
public void setNomForamtion(String nomForamtion) {
this.nomForamtion = nomForamtion;
}
/**
* #return the nombreMatiere
*/
public int getNombreMatiere() {
return nombreMatiere;
}
/**
* #param nombreMatiere the nombreMatiere to set
*/
public void setNombreMatiere(int nombreMatiere) {
this.nombreMatiere = nombreMatiere;
}
public void addToUser(User user) {
if(mesUser==null)
{
mesUsers=new HashSet<User>();
}
mesUsers.add(user);
user.addToFormation(this);
}
public void removeFromUser(User user) {
this.getMesUsers().remove(user);
user.getMesUsers().remove(this);
}
}
the method of the DAO layer which allows for the persistence of a user
public User enregistrer(User user) {
// TODO Auto-generated method stub
this.getSession().beginTransaction();
this.getSession().persist(user);
this.getSession().beginTransaction().commit();
return Entity ;
}
the method of the service layer that allows to call the save method of the dao layer
public User persistUser(User user, List<Integer> idList){
for(Integer id : idList){
Formation form = iformationDao.findById(id);
form.addToUser(user);
}
return iuserDao.enregistrer(user);
thank for answering
It looks to me like you have your CascadeTypes set to:
#Cascade({CascadeType.SAVE_UPDATE, CascadeType.MERGE})
yet you are calling:
this.getSession().persist(user);
I think you will need to add CascadeType.PERSIST to your #Cascade annotation to get the behavior you desire.
change from
public User enregistrer(User user) {
// TODO Auto-generated method stub
this.getSession().beginTransaction();
this.getSession().persist(user);
this.getSession().beginTransaction().commit();
return Entity ;
}
to
public User enregistrer(User user) {
// TODO Auto-generated method stub
Transaction tx = this.getSession().beginTransaction();//change
this.getSession().persist(user);
tx.commit();//change
return Entity ;
}

Categories

Resources