Composite Foreign Key Issue while using Inheritance in JPA - java

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.

Related

EmbeddableId should be mapped with insert="false" update="false"

I have the following entities: Match with embeddableId MatchKey and a polymorphic entity OrganisationMatch
Hibernate is blowing up with Repeated column in mapping for entity: net.satago.web.entities.OrganisationMatch column: referenceKind (should be mapped with insert="false" update="false")
I don't know what is wrong, can I not use #DiscriminatorColumn annotations on #EmbeddableIds parts and make them not insertable nor updatable?
It works fine if the column to discriminate by is not part of an #EmbeddableId but just a regular column on the Match entity.
#Embeddable
#ParametersAreNonnullByDefault
public class MatchKey implements Serializable
{
private static final long serialVersionUID = 7619427612022530146L;
#Column(insertable = false, updatable = false)
#Enumerated(STRING)
private MatchableEntityKind referenceKind;
private Long referenceId;
public MatchKey()
{
// For JPA
}
public MatchKey(OrganisationId organisationId)
{
this.referenceKind = ORGANISATION;
this.referenceId = organisationId.getId();
}
public MatchableEntityKind getReferenceKind()
{
return referenceKind;
}
public void setReferenceKind(MatchableEntityKind referenceKind)
{
this.referenceKind = referenceKind;
}
public Long getReferenceId()
{
return referenceId;
}
public void setReferenceId(Long referenceId)
{
this.referenceId = referenceId;
}
#Override
public boolean equals(Object obj)
{
if (obj instanceof MatchKey)
{
MatchKey that = (MatchKey) obj;
return this.referenceKind == that.referenceKind &&
Objects.equals(this.referenceId, that.referenceId);
}
return false;
}
#Override
public int hashCode()
{
return Objects.hash(referenceKind, referenceId);
}
}
#Entity
#Table(name = TABLE_NAME)
#Inheritance(strategy = SINGLE_TABLE)
#DiscriminatorColumn(name = "reference_kind", discriminatorType = DiscriminatorType.STRING)
#ParametersAreNonnullByDefault
public class Match implements EntityModel<MatchKey>
{
static final String TABLE_NAME = "matches";
#EmbeddedId
private MatchKey id;
#Version
private Long version;
... generic match columns
}
and
#Entity
#DiscriminatorValue(OrganisationMatch.REFERENCE_KIND)
#ParametersAreNonnullByDefault
public class OrganisationMatch extends Match
{
static final String REFERENCE_KIND = "ORGANISATION";
#JoinColumn(name = "reference_id")
#OneToOne(fetch = LAZY, optional = false)
private Organisation organisation;
public OrganisationMatch()
{
setReferenceKind(MatchableEntityKind.valueOf(REFERENCE_KIND));
}
public OrganisationMatch(OrganisationId organisationId)
{
super(new MatchKey(organisationId));
setReferenceKind(MatchableEntityKind.valueOf(REFERENCE_KIND));
}
public Organisation getOrganisation()
{
return organisation;
}
}

How does hibernate decide update/save associated objects

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

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.

Foreign Key Problems with Hibernate (Bug?)

at our current project we are experiencing some difficulties. I recently changed some Hibernate Beans (our Article Bean and some underlying stuff) and I ran some tests and everything looked fine. Now my teammate is having exceptions with this message:
Foreign key (FK_09fd525ae6654c059394d22cc15:ARTBILDER [artikel_fk,servdat_fk])) must have same number of columns as the referenced primary key (ARTIKEL [AUTOIN_FIX])
The annotations are definitely correct. I had the same problem and decided to setup the project on my computer from scratch and the problems were gone. What can be the reason for these problems?
We are working on a legacy database and are only mapping our objects to the database and not generating the database with hibernate. And we are using HibernateSearch for full-text search (maybe this is related, because the first time this occured was after I added the HibernateSearch Annotations).
We are using a Firebird 2.5 instance.
EDIT:
here is the property the error is coming from:
The ID Class:
#Embeddable
public class ID implements Serializable {
private static final long serialVersionUID = 1810044174631580834L;
private Long autoin;
private Integer serverId;
public ID() {
}
public ID(Long autoin, Integer serverId) {
this.autoin = autoin;
this.serverId = serverId;
}
#Column(name = "autoin_fix")
public Long getAutoin() {
return this.autoin;
}
#Column(name = "servdat_fk")
public Integer getServerId() {
return this.serverId;
}
public void setAutoin(Long autoin) {
this.autoin = autoin;
}
public void setServerId(Integer serverId) {
this.serverId = serverId;
}
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result
+ ((this.autoin == null) ? 0 : this.autoin.hashCode());
result = prime * result
+ ((this.serverId == null) ? 0 : this.serverId.hashCode());
return result;
}
#Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (this.getClass() != obj.getClass()) {
return false;
}
ID other = (ID) obj;
if (this.autoin == null) {
if (other.autoin != null) {
return false;
}
} else if (!this.autoin.equals(other.autoin)) {
return false;
}
if (this.serverId == null) {
if (other.serverId != null) {
return false;
}
} else if (!this.serverId.equals(other.serverId)) {
return false;
}
return true;
}
#Override
public String toString() {
return new StringBuilder().append("ID [").append(this.autoin)
.append("_").append(this.serverId).append("]").toString();
}
}
The Article class:
#Indexed
#Entity
#Table(name = "ARTIKEL")
public class Article {
private ID id;
private List<Picture> pictures;
...
#DocumentId
#EmbeddedId
#FieldBridge(impl = IDBridge.class)
public ID getId() {
return id;
}
#OneToMany
#JoinColumns({
#JoinColumn(name = "artikel_fk", referencedColumnName = "autoin_fix"),
#JoinColumn(name = "servdat_fk", referencedColumnName = "servdat_fk") })
#IndexedEmbedded
public List<Picture> getPictures() {
return pictures;
}
}
The Picture class:
#Entity
#Table(name = "ARTBILDER")
public class Picture extends BasePicture {
...
protected ID id;
#EmbeddedId
#FieldBridge(impl = IDBridge.class)
#Field(store = Store.YES, index = Index.YES)
public ID getId() {
return id;
}
...
}
EDIT2: I may have a clue where this comes from, please standby.
EDIT3: Nope, not the error.
EDIT4: Here is the DDL:
CREATE TABLE ARTIKEL
(
AUTOIN_FIX NUM10_0 DEFAULT 0,
SERVDAT_FK NUM10_0 DEFAULT 0,
...
PRIMARY KEY (AUTOIN_FIX,SERVDAT_FK)
);
CREATE TABLE ARTBILDER
(
AUTOIN_FIX NUM10_0 DEFAULT 0,
ARTIKEL_FK NUM10_0 DEFAULT 0,
SERVDAT_FK NUM10_0 DEFAULT 0,
...
PRIMARY KEY (AUTOIN_FIX,SERVDAT_FK)
);
Here is full link and description
OneToMany(fetch = FetchType.LAZY)
#JoinTable(name = "DATA_VALUE", joinColumns = {
#JoinColumn(name = "DATA_ID"),
}, inverseJoinColumns = {
#JoinColumn(name = "COLUMN_NM")
})
List<DataValue> dataValueList;
OR more Descriptive
#Entity
public class Parent implements Serializable {
#Id
public ParentPk id;
public int age;
#OneToMany(cascade=CascadeType.ALL)
#JoinColumns ({
#JoinColumn(name="parentCivility", referencedColumnName = "isMale"),
#JoinColumn(name="parentLastName", referencedColumnName = "lastName"),
#JoinColumn(name="parentFirstName", referencedColumnName = "firstName")
})
public Set<Child> children; //unidirectional
...
}

A Foreign key referring Triple from Annotation has the wrong number of columns.

Although I made a little research on this, and I found a lot of threats opened in Internet, I couldn't solve my problem. I attach my code:
Triple.java the primary key is made by 3 URIs from three different concepts, but it is the same column (is it a problem?)
#Entity
#IdClass(ConceptPk.class)
#Table(name = "triple")
public class TripleDBModel {
protected List<Annotation> annotations;
public String conceptUriSubject;
public String conceptUriObject;
public String conceptUriPredicate;
public String id;
#ManyToMany(
cascade={CascadeType.ALL},
fetch=FetchType.LAZY
)
#JoinTable(name = "triple_has_annotation",
joinColumns=#JoinColumn(name="annotation_id"),
inverseJoinColumns={#JoinColumn(name="uri_concept_subject", referencedColumnName="triple_id"), #JoinColumn(name="uri_concept_object", referencedColumnName="triple_id"), #JoinColumn(name="uri_concept_predicate", referencedColumnName="triple_id")
})//EDIT
public List<Annotation> getAnnotations() {
return annotations;
}
public void setAnnotations(List<Annotation> annotations) {
this.annotations = annotations;
}
#Id
#Column(name = "uri_concept_subject", length = 100)
public String getConceptUriSubject() {
return conceptUriSubject;
}
public void setConceptUriSubject(String conceptUriSubject) {
this.conceptUriSubject = conceptUriSubject;
}
#Id
#Column(name = "uri_concept_object", length = 100)
public String getConceptUriObject() {
return conceptUriObject;
}
public void setConceptUriObject(String conceptUriObject) {
this.conceptUriObject = conceptUriObject;
}
#Id
#Column(name = "uri_concept_predicate", length = 100)
public String getConceptUriPredicate() {
return conceptUriPredicate;
}
public void setConceptUriPredicate(String conceptUriPredicate) {
this.conceptUriPredicate = conceptUriPredicate;
}
#Id
#Column(name = "triple_id", unique = true, nullable = false)
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
}
ConceptPk.java
#Embeddable
public class ConceptPk implements java.io.Serializable {
private static final long serialVersionUID = 1L;
public String conceptUriSubject;
public String conceptUriObject;
public String conceptUriPredicate;
#Id
#Column(name = "uri", length = 100, unique = true, nullable = false)
public String getConceptUriSubject() {
return conceptUriSubject;
}
public void setConceptUriSubject(String conceptUriSubject) {
this.conceptUriSubject = conceptUriSubject;
}
#Id
#Column(name = "uri", length = 100, unique = true, nullable = false)
public String getConceptUriObject() {
return conceptUriObject;
}
public void setConceptUriObject(String conceptUriObject) {
this.conceptUriObject = conceptUriObject;
}
#Id
#Column(name = "uri", length = 100, unique = true, nullable = false)
public String getConceptUriPredicate() {
return conceptUriPredicate;
}
public void setConceptUriPredicate(String conceptUriPredicate) {
this.conceptUriPredicate = conceptUriPredicate;
}
Annotation.java
#Entity
#Table(name = "annotations")
public class Annotation {
private Integer id;
private List<TripleDBModel> triples;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "annotation_id", unique = true, nullable = false)
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
#ManyToMany(
cascade={CascadeType.ALL},
mappedBy = "annotations", //EDIT
fetch=FetchType.LAZY
)
public List<TripleDBModel> getTriples() {
return triples;
}
public void setTriples(List<TripleDBModel> triples) {
this.triples = triples;
}
But I am getting this error:
Caused by: org.hibernate.AnnotationException: A Foreign key refering TripleDBModel from Annotation has the wrong number of column. should be 3
What am I doing wrong?? Thanks in advance
The final solution is:
ConceptPk.java
#Embeddable
public class ConceptPk implements java.io.Serializable {
private static final long serialVersionUID = 1L;
public Concept conceptUriSubject;
public Concept conceptUriObject;
public Concept conceptUriPredicate;
#Id
#ManyToOne(cascade=CascadeType.MERGE)
#JoinColumn(name="uri_concept_subject")
public Concept getConceptUriSubject() {
return conceptUriSubject;
}
public void setConceptUriSubject(Concept conceptUriSubject) {
this.conceptUriSubject = conceptUriSubject;
}
#Id
#ManyToOne(cascade=CascadeType.MERGE)
#JoinColumn(name="uri_concept_object")
public Concept getConceptUriObject() {
return conceptUriObject;
}
public void setConceptUriObject(Concept conceptUriObject) {
this.conceptUriObject = conceptUriObject;
}
#Id
#ManyToOne(cascade=CascadeType.MERGE)
#JoinColumn(name="uri_concept_predicate")
public Concept getConceptUriPredicate() {
return conceptUriPredicate;
}
public void setConceptUriPredicate(Concept conceptUriPredicate) {
this.conceptUriPredicate = conceptUriPredicate;
}
Triple.java
#Entity
#IdClass(ConceptPk.class)
#Table(name = "triple")
public class TripleDBModel {
protected List<Annotation> annotations;
public Concept conceptUriSubject;
public Concept conceptUriObject;
public Concept conceptUriPredicate;
#ManyToMany(
cascade={CascadeType.ALL },
fetch=FetchType.LAZY
)
#JoinTable(name = "triple_has_annotation",
joinColumns={#JoinColumn(name="uri_concept_subject"), #JoinColumn(name="uri_concept_object"), #JoinColumn(name="uri_concept_predicate") },
inverseJoinColumns=#JoinColumn(name="annotation_id") )
public List<Annotation> getAnnotations() {
return annotations;
}
public void setAnnotations(List<Annotation> annotations) {
this.annotations = annotations;
}
#Id
#Column(name = "uri_concept_subject", length = 100)
public Concept getConceptUriSubject() {
return conceptUriSubject;
}
public void setConceptUriSubject(Concept conceptUriSubject) {
this.conceptUriSubject = conceptUriSubject;
}
#Id
#Column(name = "uri_concept_object", length = 100)
public Concept getConceptUriObject() {
return conceptUriObject;
}
public void setConceptUriObject(Concept conceptUriObject) {
this.conceptUriObject = conceptUriObject;
}
#Id
#Column(name = "uri_concept_predicate", length = 100)
public Concept getConceptUriPredicate() {
return conceptUriPredicate;
}
public void setConceptUriPredicate(Concept conceptUriPredicate) {
this.conceptUriPredicate = conceptUriPredicate;
}
}
I'm not sure this is the cause of the error message you get, but your mapping has several errors:
Each of the #JoinColumn in your inverseJoinColumns attribute should have their referencedColumnName attribute specified.
The values of the joinColumns and inverseJoinColumns attributes should be switched. joinColumns is used to reference the source entity. inverseJoinColumns is used to reference the target entity.
The mappedBy attribute should be annotations, and not annotation
(unrelated, but probably incorrect) : cascade=CascadeType.ALL is probably not what you want on a many-to-many. You don't want to delete all the annotations of a triple when this triple is deleted, since these annotations are referenced by other triples.
#ManyToMany(
cascade={CascadeType.ALL},
mappedBy = "annotation",
fetch=FetchType.LAZY
)
public List<TripleDBModel> getTriples() {
return triples;
}
The mappedBy should be "annotations"
Edit: Have a look at this wikibook, especially the bottom section. This is a quite good reference for association mappings etc.

Categories

Resources