Hibernate one to many relationship annotation - java

I have problem with settings relationship one to many. I want to create relationship between FindingAid and FindingAidVersion. I tried example in Hibernate documentation and many examples in the Internet but I don't know what is wrong.
FindingAid.java
Public class FindingAid implements Serializable {
private String id;
....
#OneToMany
#JoinColumn(name="id")
private Set<FindingAidVersion> listVersion = new HashSet<FindingAidVersion();
...... generate getter and setter .....
}
FindingAidVersion.java
Public class FindingAidVersion implements Serializable {
private String id;
private Date closeDate;
private FindingAid findingAid;
.......
#ManyToOne
#JoinColumn(name = "id", nullable = false)
public FindingAid getFindingAid() {
return findingAid;
}
...... generate getter and setter .....
}
Application code is:
FindingAid data = new FindingAid();
data.setCreateDate(new Date());
data.setName("daniel");
FindingAidVersion verse = new FindingAidVersion();
verse.setCloseDate(new Date());
verse.setIsClose(false);
data.getListVersion().add(verse);
this.getSession().save(data);
this.getTx().commit();
Error is:
Repeated column in mapping for entity: cz.tacr.elza.api.model.FindingAidVersion column: id (should be mapped with insert="false" update="false")
I know that problem is in annotation #JoinColumn but I am lost.
Thanks for your suggestions.

Have you tried to do what the error message suggest ?
#JoinColumn(name = "id", nullable = false, insert=false, update=false)
And in FindindAid for the listVersion attribute try
#OneToMany(mappedBy="findingAid")
Look at your new error:
foreign key constraint "fk_3o68boae9f3oamcm6dfy77tfw" cannot be implemented Detail: Key columns "findingaid" and "id" are of incompatible types: bytea and character varying
On one table (finding_aid_version ) you have "findingAid bytea" and on the other (finding_aid) "id varchar(255)",

Related

Representing #EmbeddedId as SQL for H2 database

I am currently working on a Java project with Hibernate entities (more below). In order to test my data access object layers, I am using H2 database to populate an in-memory database and throwing queries at it. Until this point, everything is fine.
However, the problem comes when simulating the #EmbeddedId annotation.
#Entity
#Table(name = "BSCOBJ")
public class BasicObject extends AbstractDomainObject {
#EmbeddedId // This annotation here
private RestrainPK restrain;
#Embeddable
public static class RestrainPK implements Serializable {
private static final long serialVersionUID = 1L;
#Column(name = "CODI", nullable = false)
private String coDi;
#Column(name = "COGA", nullable = false)
private String coGa;
#Column(name = "TYOR", nullable = false)
private String tyOr;
public RestrainPK() {
}
... // Getters and setters
}
}
"Simply" creating the table BSCOBJ and populating it gives no value when fetching data (of course, I checked that the request would give result "normally"). How do I represent this nested class in a SQL table creation / value insertion request ? Is that even possible ?
Thanks in advance,
EDIT
As requested, here is some samples about the SQL / Hibernate ran.
Creation request:
CREATE TABLE BSCOBJ (CODI VARCHAR(5) NOT NULL, COGA VARCHAR(5) NOT NULL, TYOR VARCHAR(5) NOT NULL);
Insertion request:
INSERT INTO BSCOBJ (CODI, COGA, TYOR) VALUES
('HELLO', 'MAT', 'REF'),
('BONJ', 'SOME', 'DAIL'),
('SOPA', 'KDA', 'RATIO');
Request given by Hibernate when trying to run the test code:
select r.restrain.tyOr from mypackage.BasicObject r where r.restrain.coDi = :coDi and r.restrain.coGa = :coGa
With the following values:
coDi = "BONJ";
coGa = "SOME";
Throws a NoResultException. I am expecting DAIL, from the second line of the INSERT request.
I have used #EmbeddedId only one time, but I think that you need #AttributeOverrides under your #EmbeddedId
#EmbeddedId
#AttributeOverrides({
#AttributeOverride(name = "idpk", column = #Column(name="IDPK", nullable = false),
#AttributeOverride(name = "code", column = #Column(name="CODE")
})
and remove your #Column annotations from FormulePK

Hibernate Unidirectional OneToMany Not Working with composite id

I've been bashing my head on my keyboard for two days trying to figure this out...
Some background: We have a data model set up with a Perl code base that runs straight native SQL statements to the database via ODBC. For certain reasons, we decided to rewrite the code in Java... I thought it would be a good idea to use Hibernate to define all of the mappings. We don't want to edit the data model.
For simplicity sake, I can express the problem with only part of our data model. We have the entities "Job","JobDatabase" and "JobTable".
Job has a PK of job_name. Database has a PK of job_name,name. Table has a PK of job_name,src_database_name,name. As you may expect, Job has a OneToMany relationship with JobDatabase, and Database has a OneToMany with JobTable.
For purposes of this test, I'm starting with empty tables and trying to create some sample data. I can insert a Job and a JobDatabase, but when I try to insert the JobTable, Hibernate throws an error. Or more accurately, that is where it complains. It doesn't start executing my code because it detects the mapping error. However, if I remove the association between JobDatabase and JobTable, it will insert all Job and JobDatabase records correctly with no errors.
Sample Classes (all fields have getters/setters... there are also many other fields):
#Entity
#Table(name="Job")
public class Job implements Serializable {
#Id
#Column(name="job_name",nullable = false)
private String jobName;
#OneToMany(cascade = CascadeType.ALL)
#JoinColumn(name = "job_name", referencedColumnName = "job_name")
private Set<JobDatabase> databases;
}
#Entity
#Table(name="JobDatabase")
public class JobDatabase implements Serializable {
#Id
#Column(name="job_name",nullable = false)
private String jobName;
#Id
#Column(name="name",nullable = false)
private String name;
#OneToMany(cascade = CascadeType.ALL)
#JoinColumns({
#JoinColumn(name = "job_name", referencedColumnName = "job_name"),
#JoinColumn(name = "name", referencedColumnName = "src_database_name")
})
private Set<JobTable> tables;
}
#Entity
#Table(name="JobTable")
public class JobTable implements Serializable{
#Id
#Column(name="job_name",nullable = false)
private String jobName;
#Id
#Column(name="src_database_name",nullable = false)
private String srcDatabaseName;
#Id
#Column(name="name",nullable = false)
private String name;
}
The error:
Exception in thread "main" org.hibernate.MappingException: Unable to find column with logical name: src_database_name in JobDatabase
I keep getting this error. I do not understand why it is looking for the referenced column in the entity "owning" the mapping. src_database_name does indeed only exist in JobTable - it is referred to as "name" in JobDatabase. JobTable also has a "name" field, but it refers to the name of the Table.
You need to have src_database_name column in your JobDatabase table. Or you can change src_database_name to other column name.
For composite key reference column must be present in your source table.

org.hibernate.QueryException: could not resolve property: composite key in query

I am trying to fetch the list of records from a view which has a composite primary key with three columns.
I tried to embed the composite key in the entity class. But I am getting the below mentioned errors. The columns of the views (VW_ALERTS) are C_ID, MAT_ID, P_MONTH, CO_TYPE, CO_SUBTYPE.
Here the composite keys are C_ID, MAT_ID, P_MONTH. I am making the property of them in the embeddable class.
Please help to resolve the issue
org.hibernate.QueryException: could not resolve property: coreId of: com.sp.cpem.dto.VwAlerts [FROM com.ct.cpem.dto.VwAlerts d ORDER BY d.cId ASC]
This following code is used to execute the hql.
Session session = sessionFactory.openSession();
String hql = "FROM VwAlerts d ORDER BY d.coId ASC";
Query query = session.createQuery(hql);
return query.list();
The entity class :
#SuppressWarnings("unchecked")
#Entity
#Table(schema = "TIGER", name = "VW_ALERTS")
public class VwAlerts {
#Embedded
private VwAlertsPK vwAlertsPK;
#Basic
#Column(name = "CO_TYPE", nullable = true)
private String coType;
#Basic
#Column(name = "CO_SUBTYPE", nullable = true)
private String coSubType;
Class used to get the composite key
#Embeddable
public class VwAlertsPK implements Serializable {
#Basic
#Column(name = "C_ID", nullable = false)
private BigDecimal cId;
#Basic
#Column(name = "MAT_ID", nullable = true)
private BigDecimal matId;
#Basic
#Column(name = "P_MONTH", nullable = true)
private BigDecimal pMonth;
I am expecting to get all the records from the view.
I tried with the #Id column in the entity class, it failed by returning only the duplicate records of the first row from the view.
Your entity VwAlerts has only 3 properties --> vwAlertsPK, coType, coSubType
but in your HQL you are trying to access a property coreId which does not exist in your entity.
FROM com.ct.cpem.dto.VwAlerts d ORDER BY d.coreId ASC
So add the property coreId to your entity or else just update the ORDER BY clause so you are pointing to correct properties of your entity.

Jpa - Two #OneToOne relations with same 'mappedBy'

I have two java-classes / db-tables: 'message' and 'thirdparty'
#Entity
public class Message {
#OneToOne(mappedBy = "message")
private ThirdParty source = null;
#OneToOne(mappedBy = "message")
private ThirdParty target = null;
....
}
#Entity
public class ThirdParty {
#OneToOne(targetEntity = Message.class)
#JoinColumn(name = "Message", referencedColumnName = "mess_id", nullable = false)
private Message message = null;
#Column(name = "isSource", nullable = false)
private Boolean isSource = null;
}
Message has two references to ThirdParty, which could be differenced by isSource (if they are source or target).
This cannot be resolved by jpa they way it is designed / annotiated. But is there a way to to this by adding some annotiation or some kind of special sql-statement?
This is conceptually wrong. You cannot do this. OneToOne mapping occurs when there are two entities mapped in the following way :
Entity1 : Has a primary key(PK1) and others along with a foreign key(FK)
Entity2 : Has a primary key (PK2).
Now the FK is mapped to PK2 in such a way that for each occurence of PK there must be a one and only one matching occurence of FK.

Hibernate: getting too many rows

I have problem with getting rows from my database using Hibernate. When I would like to get only one row, I am receiving 20. When I would like to get all of rows from table with about 1.5k rows, I am receiving exactly 15.2k rows.
Entity class of this table has composite primary key.
This is my code for getting all rows:
Criteria criteria = getSession().createCriteria(type);
criteria.setCacheable(true).setCacheRegion(BaseEntity.PACKAGE);
criteria.list();
And this is my Entity class:
#javax.persistence.Entity
#Table(name = "my_table")
public class My extends MyEntity<MyPK> {
#EmbeddedId
private MyPK id;
#Column(name = "text", nullable = false)
protected String text;
#ManyToOne
#JoinColumn(name = "property", nullable = false, insertable = false, updatable = false)
protected Option option;
#Override
public MyPK getId() {
return id;
}
#Override
public void setId(MyPK id) {
this.id = id;
}
//getters and setter
}
And this is MyPK class:
#Embeddable
public class MyPK implements Serializable {
#Column(name = "qwerty")
protected String qwerty;
#Column(name = "property")
protected String property;
//constructors, getters and setters
}
MyEntity class is abstract class with #MappedSuperclass annotation. This is this class header:
#MappedSuperclass
public abstract class MyEntity<T extends Serializable>
What am I doing wrong? Is this problem with EmbeddedId?
EDIT #1
As I have realized this is problem with this:
#ManyToOne
#JoinColumn(name = "property", nullable = false, insertable = false, updatable = false)
protected Option option;
This object contains foreign key to another table. And this another table has reference to another. And this last table has 10 rows for previous table. In the result I am getting rows amount * 10. The problem is probably with Hibernate annotation in my entities.
It looks like you're probably eagerly joining a many-to-one relationship somewhere. The default behavior is that you get one entity for each row returned by the database. If you don't want to change the eager fetching, but do want to remove duplicates in your result, you need to use this ResultTransformer:
criteria.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);
#Embeddable only means that MyPK 's columns will be columns in the My class.
Your problem might be #ManyToOne #JoinColumn(name = "property") since it's the same with "property" in MyPK
You can set the maximum number of results by setting this on the criteria with this method: setMaxResults(int maxResults)
Primary key classes need to define equals() and hashCode(), in terms of the aggregated values (qwerty and property, here). Most likely when process the ResultSet, Hibernate is not seeing the entity keys across multiple rows as equal.
From Section 2.4 of the JPA 2.0 specification (in case it helps):
The primary key class must define equals and hashCode methods. The semantics of value
equality for these methods must be consistent with the database equality for the database types
to which the key is mapped

Categories