Hibernate select id of join column without join - java

The problem is I need to select an object from database which has a join column inside, and I need the Id of that foreign object. But hibernate joins those two tables or if in lazy mode , It queries again on my database.
How do I access that Id with no other join or query than the primary select query.
Note that I am using Hibernate version +5 and I want an approach via JPA CriteriaBuilder.
Thank you in advance.

You can map the foreign key to the entity twice in this case, one for actual ORM and another for getting the FK without actually firing a new query.
public class Answer {
#JoinColumn(name = "question_id")
#ManyToOne(targetEntity = Question.class, fetch = FetchType.LAZY)
private Question question;
#Column(name = "question_id", insertable = false, updatable = false)
private Long questionId;
}
Here question_id is present in the answer table.
This way that foreign key will be already available in the result of the first query(in the questionId field) and the new query won't be fired for getting the FK value.

Related

JPA secondary table as read only view - hibernate still tries to insert rows

I've got the following entity:
#Entity
#Table(name = "ONE")
#SecondaryTable(name = "VIEW_TWO", pkJoinColumns = #PrimaryKeyJoinColumn(name="ONE_ID"))
public class CpBracket {
#Id
private Long id;
#Column(name="progress", table="VIEW_TWO", updatable = false, insertable = false)
private int progress = 0;
(...)
}
As you see, this entity uses table ONE and (read only) view VIEW_TWO. When I'm persisting the entity, hibernate is performing insert into view:
insert into VIEW_TWO (ONE_ID) values (?)
It is ignoring the non-updatable and non-insertable column progress (that's good) and it is still trying to insert value of ONE_ID column. As far as I know, the annotation #PrimaryKeyJoinColumn marks selected column as insertable=false and updatable=false.
How can I prevent hibernate from inserting rows into secondary table (view)?
As far as I know, the annotation #PrimaryKeyJoinColumn marks selected
column as insertable=false and updatable=false.
I do not believe this can be the case: how then do we get records inserted into the #SecondaryTable when it is an actual table rather than a view?
As neither #SecondaryTable or #PrimarykeyJoinColumn have a means to prevent insert then it would appear that your original solution is not going to work and an alternative is required.
One option is to map VIEW_TWO as an #Entity and link to your class CPBracket as a #OneToOne relationship with cascade options set to none.
#Entity
#Table(name ="VIEW_TWO")
private CpBracketSummaryData(){
}
#Entity
#Table(name = "ONE")
public class CpBracket {
#OneToOne
#PrimaryKeyJoinColumn
private CPBracketSummaryData summaryData;
public int getSomeValue(){
return summaryData.getSomeValue();
}
}
The second option would be to use the non JPA compliant, Hibernate specific #Formula annotation.
#Entity
#Table(name = "ONE")
public class CpBracket {
#Formula("native sql query")
private int someValue;
}
Update October 2016
I have revisited this in both Hibernate 4.3.10.Final and 5.1.0.Final and it is possible to have the view as a #SecondaryTable without the insert: if you have the correct mappings.
Scenario 1
Load an entity for edit and do not touch any fields mapped to the secondary table. No update is issued to the secondary table
Scenario 2
Create and save a new entity and do not set any fields mapped to the secondary table. No insert is issued for the secondary table
Scenario 3
Create or update an entity including a field mapped to a secondary table and where this field is marked as insertable = false and updateable = false. An insert is made to the secondary table only for the ID field -the behaviour reported in the original question.
The issue with the mapping in the original question is the fact that the secondary table field is a primitive type and therefore when saving a new entity Hibernate does think a record has to be written to the secondary table with a value of zero.
#Column(name="progress", table="VIEW_TWO", updatable = false, insertable = false)
private int progress = 0;
The solution then is to replace primitives with the corresponding wrapper types and leave them as null. Then when saving a new record there is nothing to write to the secondary table and no insert will be made:
#Column(name="progress", table="VIEW_TWO")
private Integer progress;
I solved a similar problem with #SecondaryTable, which was a database view. So maybe it will help someone else.
The problem was on cascade delete to #SecondaryTable, when record from primary table was deleted.
As a solution, I implemented RULE on view for delete
CREATE RULE on_delete AS ON DELETE TO my_view DO INSTEAD(
select 1;
)
Similar solution can be used for INSERT and UPDATE operation on view.

Collection isn't filled with OneToMany relationship - EclipseLink

I'm mapping a database (Oracle 11g) to JPA entities using EclipseLink. I have mapped almost every table to JPA objects but I've just found a problem:
In the \Curve\ entity I have the following fields:
#Id
#Column(name = "COD_CURVE")
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "seq.gen")
#SequenceGenerator(name = "seq.gen.curve", sequenceName = "SEQCURVE", allocationSize = 1)
private long codCurve;
#Id
#Column(name = "FEC_HISTORIC")
#Temporal(javax.persistence.TemporalType.DATE)
private Date fecHistoric;
#OneToMany(mappedBy="codCurve", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
private Collection<CurveDetail> detailsCollection;
In the \CurveDetail\ entity I have this:
#ManyToOne
#JoinColumns({
#JoinColumn(name = "COD_CURVE", referencedColumnName = "COD_CURVE"),
#JoinColumn(name = "FEC_HISTORIC", referencedColumnName = "FEC_HISTORIC")
})
private Curve codCurve;
The problem is that when I query the \Curve\ entity, the details always are null, despite the fact that there is valid data in both tables. Checking the database I've noticed that there are no foreign key constraints in the \CurveDetail\ table, so I wonder ¿Are these constraints required to map the database correctly? I haven't tried to add the FK constraint myself because I'm not allowed to (have to ask a DBA to do it, and it'll take a week).
Thanks in advance!
Having a foreign key is not required.
Check the SQL that is generated by enabling logging ("eclipselink.logging.level"="finest")
Try executing the same SQL with the same database to see if the data exists.
Also ensure you are not corrupting the shared cache by inserting/updating an object with a null collection. You must maintain both sides of a bi-directional relationship. You could try disabling the cache to see if this is what you are doing.
As I know having a FK constraint is not mandatory. Once I had the same problem (but it was Oracle 9i) and found out that the name of Entity class should match the name of the table you want to map, and also JPA SQL and Hibernate HQL are both case sensitive so be careful in writing #Column tag.

ManyToOne relation in Hibernate, not in Database

I have an entity named 'Department' and another entity named 'student'. I know the department will have many students and there shoulld be relation between these two tables in database. But in my project, the DB tables are already there and there is no relation (foreign key) between department and student tables.
In entity class, student.java , there is a relation written as,
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = 'DeptId', nullable = false, insertable = false, updatable = false)
Department department
I am confused about this existing code.
When I wrote a test, I am fetching the department from DB by deptId and set the student entity as,
student.setDepartment(department);
This doesn't populate the DB column 'DEPTID' in student table.
Since there's no student collection in Department, I cannot set the student as,
department.addStudents(student);
I am not sure whether we can insist a #ManyToOne relation without a relation between the tables in DB.
Please let me know how I can fix this issue so that the 'DEPTID' column in student table is populated with the correct data.
Thanks in advance,
BS
you r having
#JoinColumn(name = 'DeptId', nullable = false, insertable = false, updatable = false)
instead why dont you try
#JoinColumn(name = 'DeptId', nullable = false)
Hibernate wont check whether the mapping constraints that you are putting are valid at db level. It just assumes it is valid and executes queries based on that assumption.
Hi sorry for responding to your question so late but I think the reply could equally help another person. Now you said the tables existed already in the database, if they haven't yet got some data then I suggest you drop them, activate your Table Generation Strategy in your persistence.xml file to Create, in that case, it will recreate those tables with your desired relationship columns. Do not also forget to use the #OneToMany annotation on the Department.java class to indicate its capabilities of reception of many students. It is used together with the #ManyToOne

Java Hibernate DataException: cannot be converted to BIGINT

I'm trying to join one table, with two other tables, using a single column in Java using Hibernate and JPQL.
For example, I have table A with an id column. I want to join table B and table C with table A on the id column.
However, when I try to do that I get the following error:
org.hibernate.exception.DataException: The value supplied cannot be converted to BIGINT. I have seen some answer say that there may be null values, but these id columns are primary id columns, and contain no nulls.
My code is as follows:
#OneToOne(fetch = fetchType.LAZY)
#JoinColumn(name="id", insertable=false, updatable=false)
private TableB tableB
#OneToOne(fetch = fetchType.LAZY)
#JoinColumn(name="id", insertable=false, updatable=false)
private TableC tableC
When I remove one of the two joins everything works fine again.
What am I doing wrong that's causing this issue?
I don't know what type id is, but is but I think it must be a Long in order for Hibernate to convert it to a BIGINT

How can I ask Hibernate to create an index on a foreign key (JoinColumn)?

Here is my model:
class User {
#CollectionOfElements
#JoinTable(name = "user_type", joinColumns = #JoinColumn(name = "user_id"))
#Column(name = "type", nullable = false)
private List<String> types = new ArrayList<String>();
}
As you can imagine there would be a table called "user_type", which has two columns, one is "user_id" and the other is "type".
When I use hbm2ddl to generate the ddls, I want to have this table, along with the foreign key constraint on "user_id".
However, there is no index for this column. How can I get hibernate to generate the index for me?
Try an #Index annotation.
#Index(name="user_type_index")
There is also an #IndexColumn annotation used with join tables, but it doesn't seem to actually create an index, but controls which field defines order in list semantics.
The #Index column in this context does seem to create an index on the join table.
I'm dealing with a similar issue and I've found that some dialects will automatically index foreign keys and others wont.
Hibernate Dialect class and all subclasses which do not override the getAddForeignKeyConstraintString method (Oracle, SQL Server, etc) will not create an index on the foreign key.
MySQLDialect overrides that method and adds an index to every foreign key

Categories