JPA Entity mapping with no foreign keys available - java

I dont really get to work with entity beans, but they are staring at me right now.
We have a couple of tables that are related to each other, but there are no foreign keys, and we cannot add any. For this question, the database cannot change, it's just not possible, but as a different solution we might create views. Anyways...
I have 3 tables.
LOCATION , LINKS and ENDPOINT and for extra salt, we a a LINKS_TYPE table.
LOCATION table has a primary key LOCATIONID which is a string containing the location id.
LINKS table has a LINKID as primary key
a column LINK_ATTR_VALUE_A which contains ENDPOINT's primary key
a column LINK_ATTR_VALUE_B which contains LOCATION's primary key.
a column LINKTYPEID which contains a LINKS_TYPE primary key
ENDPOINT table has a primary key POINTID
LINKS_TYPE has primary key LINKTYPEID
a column LINKTYPEA (text string defining the table name it's linked to)
a column LINKTYPEB (text string defining the table name it's linked to)
Now even though LINKS_TYPE is mentioned, I dont need to worry about that now, because there are no other links in this instance of the database.
I would like to define a member in my LOCATION entity 'List endPoints'
Which would be a #OneToMany from my understanding.
Do keep in mind, there is no foreign key to help here, and there wont ever be.
This is the mapping I defined...
#OneToMany ( cascade=CascadeType.ALL)
#JoinTable ( name = "ENDPOINT",
joinColumns = #JoinColumn (
name = "LINK_ATTR_VALUE_B"
),
inverseJoinColumns =
#JoinColumn (
name = "LINK_ATTR_VALUE_A"
)
)
private List<EndPoint> endPoints;
It's very likely from this you might realize I have no clue what I'm doing :D
But the documentation aint too great, and Ive ordered a book for help with ejb 3, but I just dont have the time to finish the book before this mapping :D
We are using TopLink with jdeveloper 11g and that weblogic server thing and oracle 10g as database.
When using a serviceFacade client to query, everything did seem right (since then workspace died and I have to recreate the project to get the client working).
It generates the perfect query in my opinion to retrieve the right data.
Yet, it ends with no results.
I'm willing to give as much info as possible, just not sure what is needed.
But I know my mapping is most probably wrong, and it's because I do not understand the mapping.
Could someone help me?
Thank you.

Your LINKS table looks like many-to-many mapping table between LOCATION and ENDPOINT rather than one-to-many. The big question here is whether it has any additional columns aside from LINKID, LINK_ATTR_VALUE_A and LINK_ATTR_VALUE_B that you listed?
If it does, then you would have to map it as a separate entity:
Location would have a collection of Links mapped as bi-directional one-to-many
Link would have many-to-one relationships with both Location and EndPoint
If, OTOH, LINKS has no other columns AND you're willing to forgo its primary key (which is neither needed nor can be mapped for many-to-many join table) then you can map it as many-to-many collection of EndPoints on Location.
If you can clarify your question I'll update my answer to include the actual mapping if you need it.

Here is the mapping I ended on.
#OneToMany(cascade=CascadeType.ALL)
#JoinTable(name = "LINK",
joinColumns = {
#JoinColumn(name="LINK_ATTR_VALUE_B")
},
inverseJoinColumns = {
#JoinColumn(name="LINK_ATTR_VALUE_A")
}
)
private List<EndPoint> endPoints;
There just isnt truly any values needed right now in the LINK table.
But when it' time, our DBA's will need to create materialized views for us or something.
But when attemting the mapping, I initialy kept the LINK, rather than going straight to the endPoint. I was being returned 5000+ links where there should only be 133. So again there is a mapping I dont understand,but I'll leave that for later.
At the moment our database only contains 1 link type. This will change, and I really which there was a way for me to add an additional where clause to the mapping, so I could have different attribute mappings for different types.
I'm in a typing mood today :-D

Related

JPA Single foreign Key ID to refer to two (or more) tables

Simple question really. This is using JPA on Java and what I what to do is to have a table with and column which can refer to one of two tables. To make this clearer I can have a 'User' table and a 'TempPerson' table. I don't want to pollute my User table (as I use it for security as well, plus has other info as well). Now lets say I have a third table called 'Game'. Now when someone stars a game against someone, they can play against someone in the system already ie. User or someone where they can type a name and new entry for TempPerson is created and used. So the game for player2 (or player1) will be a mapped id to either User.id or TempPerson.id. Now I understand that a determining column may need to be placed into Game to determine what the Id is for but I hope JPA will cater for it somehow. Any ideas will be helpful, i could use inheritance but not sure about it.
Here is another example:
Lets say I have a table which holds information about images => id, resolution, width, height, location, bucket .... id_in_the_table_where_used, table_name_of_where_used. Now, this one table can hold the images for profiles, places, etc... and the profiles, places will have an id referring to the images table, but I also would like the images table to have an id back to where the images is used, which table and which id is using it.
It almost I am asked i 'one to many tables' solution. Although I could have many in between tables etc... Seems overkill to so something quite simple, although many DBAs may be cursing this idea. It does minimise queries, number of tables etc...
Thanks in advance
It is possible to use single FK to target multiple tables. You would have to use #JoinColumn for that
#Entity
public class User{
#OneToOne
#JoinColumn("universalId", targetEntity=Avatar.class)
private Avatar
#oneToMany
#JoinColumn("universalId", targetEntity=Log.class)
private List<Log> logs;
}
This would use universalId column of User's table to lookup related records from Avatar and Log tables
This however is rather anti-pattern, causing a lot of consequences when for example universalId will have to be changed etc. 1 column = 1 FK - go that way.

JDBI how can I delete data from two tables in one #SqlUpdate

I have two tables:
entities:
- id
- someValues
and other table, with foregin key on id field
connectedEntities:
- entityId (foregin)
- otherObjectId (foregin)
I need to delete entity by id, but when I tried to delete just from entities table, there's FK violation.
Also, I want to use #SqlUpdate or other annotation from JDBI framework.
Does anybody know how to do something like this?
Thanks to #G_H , I found what I was looking for.
I just needed to add ON DELETE CASCADE to my foregin key definition, and everything worked just fine.
Here's the tutorial - mysqltutorial.org/mysql-on-delete-cascade

How change hibernate association mapping from 'one to many' into 'many to many'?

The relation between the entities must be changed and I'd like to know is it normal to change the association mapping type and whether the data that already exist in db will be transfered normally? I tried to find information about it but didn't found. Or if the mapping will be changed the data that already exists must be transfered manually via sql queries? Thanks
If the association already uses a join table, and the mapping of the many-to-many keeps using the same join table with the same column names, you won't have to do anything except removing the unicity constraint you could have on one of the ci=olumns of the join table.
Otherwise, yes, obviously, you'll have to migrate your schema, using SQL, or any other tool (FlywayDB, Liquibase, etc.).
I could do it simply:
Let A and B be the original tables.
A->B (N-1) was moved to A<-AB->B (N-N).
I had to
- "remove" the foreignkey column from table A,
in favor of records to be inserted into AB
(made of the two foreign keys leading to A and B)
That's all.
Step one: Replace your Many-to-One annotation by your Many-to-Many annotations.
and lauch hibernate in append mode to generate the N-N table
Step two: Insert record in this N-N table given what is found in the remaining foreign-key column of you 1-N relationship.
Step three: Delete this foreign-key column.

Dynamic Tree Creation in Java

I am using Spring-hibernate Framework and Oracle database. Now there is a table named project. each record has got an unique id,name and a parent_id column. Say the table has got these following records...
ID NAME PARENT_ID
1 A NULL
2 B 1
3 C NULL
4 D 3
5 E 3
now i have create a tree view where these records will be displayed in according to their Parent-Child relationship. Like This..
1---P
ch---2
3---P
ch--4
ch--5
Now can anyone help me how to create the tree dynamically fetching records from the database dynamically. And what will be the Data Access Object(DAO) and the Implementation of the DAO..
any help or suggestion will be very helpful.
First select only PARENT_ID. Then for select everything where ID is IN the previous array of results (http://www.w3schools.com/sql/sql_in.asp).
From this you can then create parent in the tree and then lazy load children on expand.
Or you can populate tree with children immidiately. You just select all where PARENT_ID is NOT NULL and attach them to appropriate parent (by PARENT_ID).
I'm not sure what DAO has to do with it. But in case you just want some abstraction you can use DAO pattern.
DAO could have methods like: getAllParents, getChildrenForParentId, getAllChildren, ...
Just made self table reference in POM (.java class) with List type one to many annotation.
#OneToMany(fetch = FetchType.EAGER)
#JoinColumn(name = "PARENT_ID",nullable=true)
#OrderBy(clause = "NAME")
#ForeignKey(name = "fk_child_project")
private List<Project> projects= new ArrayList<Project>();
What you need is a Oracle Hierarchical query. Since you are using Oracle DB, you are in luck.
But the only way this can done thru Hibernate is by using a native query and mapping the results back to Objects.
Too many questions, I'll try to steer you in the right direction -- this might not drop you to your destination.
Create your Entities, See the docs
You may not need a DAO, just create a business class to query the database. (Hint: use EntityManager in case you are using Hibernate's JPA implementation), See the docs
Then display it as a tree in your browser, assuming you are working on a webapp
Note: You can come again and ask specific questions regarding how, as a separate question.
Related thread
How to implement self join in JPA

Hibernate #ManyToOne on inconsistent database

Let's say I have two tables, employee and department where emp has a #ManyToOne key to dept. Now I want to be able to delete rows from the dept table but keep the emp records pointing to it; basically saving the relationship so that when the dept table is recreated the relationship is restored. (This actually happens in our system, but not with hibernate, but by using composed, reproducable keys).
The question is: Will hibernate crash on #ManyToOne relationships which seem to be there but with no record in the #One part of the relationship? (basically an inconsistent database state).
I probably should solve this by removing the #ManyToOne relationship and simply map the foreign key to a String or so. I just wondered whether we can pull it off to leave the relationship in place..
Now I want to be able to delete rows from the dept table but keep the emp records pointing to it;
Then you'll have to delete them logically, not physically (and FK constraints will actually prevent you from deleting departments).
Will hibernate crash on #ManyToOne relationships which seem to be there but with no record in the #One part of the relationship?
Don't you have referential integrity (see above)? But let's say you broke the integrity... Maybe you'll be able to load employees but something is going to crash at some point (when loading the association, if not before).
I probably should solve this by removing the #ManyToOne relationship and simply map the foreign key to a String or so. I just wondered whether we can pull it off to leave the relationship in place..
Delete the departments logically.

Categories