Hibernate - #JoinTable - extract foreign keys via classMetaData [duplicate] - java

i need to get the column names for foreign keys for all mapped hibernate entities. Does anyone know how to do that?
I tried by sessionFactory.getClassMetadata - i can see all the properties names and types for all entities there, but i cannot find information about foreign keys.
Does anyone have any idea? I may not use direct database query - i must extract it from hibernate metadata.

You can use Java Reflection:
// Loop through joined columns that has #JoinColumn annotation
for (Method method : testClass.getMethods())
{
if (method.isAnnotationPresent(JoinColumn.class))
{
// name parameter is foreign key
String foreignKey = method.getAnnotation(JoinColumn.class).name;
// if the referencedColumnName is explicitly defined
String foreignKey = method.getAnnotation(JoinColumn.class).referencedColumnName;
}
}

Related

How does hibernate work with existing tables without adding existing columns(ColumnName to column_name)

When I run my app hibernate creates duplicates of the column and I don't want that to happen. I want it to check if the columns exist and if exist it should ignore them and move.
I want to avoid this duplicate and use the first option.
I tried specifying the name of the column I want on the column annotation. and also updatable = false, insertable = false and also
First you need to get the list of the columns in that class. You can do that by using org.hibernate.metadata.ClassMetadata Entity :
ClassMetadata classMetadata = sessionFactory.getClassMetadata(AppTaskConfig.class);
String[] propertyNames = classMetadata.getPropertyNames();
where propertyNames is an array of Strings representing the property names of AppTaskConfig.
Now using Hibernate org.hibernate.cfg.Configuration object you can find the column names of the properties:
for (String property : propertyNames) {
Configuration configuration = sessionFactoryBean.getConfiguration();
PersistentClass persistentClass = configuration
.getClassMapping(Details.class.getName());
String columnName = ((Column) persistentClass.getProperty(property)
.getColumnIterator().next()).getName();
}
Also to skip the mapping you can simply use #Transient annotation on your entity.

Hibernate get all foreign keys for mapped entities

i need to get the column names for foreign keys for all mapped hibernate entities. Does anyone know how to do that?
I tried by sessionFactory.getClassMetadata - i can see all the properties names and types for all entities there, but i cannot find information about foreign keys.
Does anyone have any idea? I may not use direct database query - i must extract it from hibernate metadata.
You can use Java Reflection:
// Loop through joined columns that has #JoinColumn annotation
for (Method method : testClass.getMethods())
{
if (method.isAnnotationPresent(JoinColumn.class))
{
// name parameter is foreign key
String foreignKey = method.getAnnotation(JoinColumn.class).name;
// if the referencedColumnName is explicitly defined
String foreignKey = method.getAnnotation(JoinColumn.class).referencedColumnName;
}
}

ManyToOne relationship with a String field

I have two classes: TranscriptionService and TranscriptionConfig.
TranscriptionConfig has a serviceName variable, that is a string, with setters and getters.
TranscriptionService has no variables or references in the class to TranscriptionConfig.
There are two database tables: transcriptionConfig and transcriptionServices. transcriptionConfig has a foreign key between its field serviceName, and name inside transcriptionServices.
An admin should be able to set the string value of serviceName inside transcriptionConfig. This then references the equivalent string inside name in transcriptionServices. The transcriptionServices entries in the database are pre defined manually, so they never need to be set using an object.
My current hibernate code inside transcriptionConfig for the serviceName is as follows:
#ManyToOne
#JoinColumn(name = "serviceName", nullable = false)
private String transcriptionService;
However, it will not allow me to do this, as a String is not an entity. I have tried adding target-entity to no avail.
It seems to have a manyToOne relationship, it would need to have an instance of the TranscriptionService class, but I do not want transcriptionConfig to contain this object. It just needs a reference with the names.
How I can use this ManyToOne relationship, but just pass around the string for the name?
If you treat this column as a string value, you don't need to define mapping #ManyToOne and use #JoinColumn. Just mark it by#Column.
You'll need probably to catch SQLException in your DAO to handle foreign key constraint.
Edit:
You get this exception, because you don't have this key in foreign table. First you need to create row in TranscriptionService table.

JPA 2: how to declare primary-key columns in #ElementCollection tables

in JPA2 when we are using Embed-able (Basic Type like String.. etc ) object in Entity using with #ElementCollection and #CollectionTable annotation , the new table is created , but in new table how to declare primary-key contraint in column ? following is my code
public class Employee {
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
private int id;
private String name;
private String salary;
#Transient
private String phnNum;
#Enumerated(EnumType.STRING)
private EmployeeType type;
#ElementCollection
#CollectionTable(name="vacations" , joinColumns=#JoinColumn(name="Emp_Id"))
private Collection<Vacation> vacationBooking;
#ElementCollection
private Set<String> nickNames;
...................
with this code the "vacation" and "employee_nickname" two tables are created in schema. but i want to declare the one primary-key column in both table . what i do for this?
It looks like a primary key per se is not supported by JPA 2.0:
From Wikibooks:
The JPA 2.0 specification does not provide a way to define the Id in the Embeddable. However, to delete or update an element of the ElementCollection mapping, some unique key is normally required. Otherwise, on every update the JPA provider would need to delete everything from the CollectionTable for the Entity, and then insert the values back. So, the JPA provider will most likely assume that the combination of all of the fields in the Embeddable are unique, in combination with the foreign key (JoinColumn(s)). This however could be inefficient, or just not feasible if the Embeddable is big, or complex.
Some JPA providers may allow the Id to be specified in the Embeddable, to resolve this issue. Note in this case the Id only needs to be unique for the collection, not the table, as the foreign key is included. Some may also allow the unique option on the CollectionTable to be used for this. Otherwise, if your Embeddable is complex, you may consider making it an Entity and use a OneToMany instead.
Do you mean that you want to assign 'id' from Employee table as foreign key to the Vacation table?
In that case, you should use #OneToMany instead of #ElementCollection

JPA composite key #OneToMany

I have the following existing DB schema, which I'd like to recreate with Java and plain JPA annotations (using hibernate as provider, so hibernate specific annotations would work as a last resort):
CREATE TABLE users (
user_id NUMBER NOT NULL -- pk
);
CREATE TABLE userdata_keys (
userdata_key_id NUMBER NOT NULL, -- pk
key VARCHAR2(128) NOT NULL
);
CREATE TABLE users_userdata (
user_id NUMBER NOT NULL, -- fk users.user_id
userdata_key_id NUMBER NOT NULL, -- fk userdata_keys.userdata_key_id
value VARCHAR2(256)
);
I've thus created the following classes and annotations:
class User {
#Id
Long id;
#OneToMany
Set<Userdata> userdata;
}
class UserdataKey {
#Id
Long id;
String key;
}
class Userdata {
String value;
#EmbeddedId
UserdataId userdataId;
}
#Embeddable
class UserdataId {
User user;
UserdataKey userdataKey;
}
I left out columnName attributes and other attributes of the entities here.
It does however not quite work as intended. If I do not specify a mappedBy attribute for User.userdata, hibernate will automatically create a table USERS_USERS_USERDATA, but as far as I've seen does not use it. It does however use the table which I specified for the Userdata class.
Since I'm rather new to Java and hibernate as well, all I do to test this currently is looking at the DB schema hibernate creates when persisting a few sample entries.
As a result, I'm entirely puzzled as to whether I'm doing this the right way at all. I read the hibernate documentation and quite a bunch of Google results, but none of them seemed to deal with what I want to do (composite key with "subclasses" with their own primary key).
The mappedBy attribute is mandatory at one of the sides of every bidirectional association. When the association is a one-to-many, the mappedBy attribute is placed ot the one- side (i.e. on the User's userdata field in your case).
That's because when an association is bidirectional, one side of the association is always the inverse of the other, so there's no need to tell twice to Hibernate how the association is mapped (i.e. which join column or join table to use).
If you're ready to recreate the schema, I would do it right (and easier), and use a surrogate auto-generated key in users_userdata rather than a composite one. This will be much easier to handle, in all the layers of your application.

Categories

Resources