JPA newbie here. Here's my question:
Say we have an entity like this:
#Entity
#Table(name="thingies")
public class Thingy implements Serializable {
private Long thingyId;
private String thingyName;
private Integer thingyPrice;
// Constructor, getters, setters
}
Mapped to a table like this:
create table thingies (
thingy_id serial primary key,
thingy_name text,
thingy_price smallint
);
Is there a way to make the provider aware of the attribute naming policy instead of needing to explicitly provide a #Column annotation on each getter? In other words, can we automatically map all underscored names to the corresponding camelcased names without using #Column?
(I know I can quote names, that is not an answer to my question above.)
You need to add the following property to your persistence.xml file:
<property name="hibernate.ejb.naming_strategy" value="org.hibernate.cfg.ImprovedNamingStrategy"/>
And all camelcasedproperty names will bemapped to underscored column names.
You should use #Column.
#Column(name="thingy_name")
private String thingyName;
Becouse 'thingy_name' is not equal 'thingyName'. JPA dont know what you want mapped. But in table thingyname and in entity thingyName is equal for JPA.
Use adnotation #Column, it does not take a lot of time. But you will get a explicit documentation.
Related
I have Consumer table in database where I have check constraint on consumer_type column like below:
ALTER TABLE consumer
ADD CONSTRAINT Check_consumer_consumer_type CHECK (consumer_type IN ('ACCOUNT','ORGANIZATION'))
Now from hibernate side I want to add check constraint annotation which will allow only "ACCOUNT" and "ORGANIZATION" value in consumer type table.
Which hibernate / jpa annotation I should use for this purpose?
Assuming that you have the consumer type represented using String in your entity you could easily replace it with an enum and Java's type safety would ensure that you will not be able to pass anything else to it.
Using EnumType.STRING, the values will be stored as Strings in your database (and mapped back to enum when you load the entity), so no change to your data would be required.
Example
#Entity
public class Consumer {
public static enum ConsumerType {
ACCOUNT, ORGANIZATION
}
#Enumerated(EnumType.STRING)
#Column(name="consumer_type", nullable=false)
private ConsumerType consumerType;
// Other properties, getters/setters, ...
}
We have a requirement where we need to have the column names externally configurable in Hibernate. The column names in the database will change in the future and we do not want to change the hibernate entity class (annotations) every time this happens.
What is the best approach for this scenario?
You cna either use a custom NamingStrategy (see here)
Or define dynamic maping (see here)
You can use hibernate mappings files
Check this link maybe it can help you
http://www.tutorialspoint.com/hibernate/hibernate_map_mapping.htm
You can keep column names in some class as constants, this way you would only need to update that class when column names change
public class MyEntityColumns {
public static final String COLUMN1 = "column1";
...
}
#Entity
public class MyEntity {
#Column(name = MyEntityColumns.COLUMN1)
private String someField;
}
Say I have the following Java class, which is owned by a vendor so I can't change it:
public class Entry {
private String user;
private String city;
// ...
// About 10 other fields
// ...
// Getters, setters, etc.
}
I would like to persist it to a table, using JPA 2.0 (OpenJPA implementation). I cannot annotate this class (as it is not mine), so I'm using orm.xml to do that.
I'm creating a table containing a column per field, plus another column called ID. Then, I'm creating a sequence for it.
My question is: is it at all possible to tell JPA that the ID that I would like to use for this entity doesn't even exist as a member attribute in the Entry class? How do I go about creating a JPA entity that will allow me to persist instances of this class?
EDIT
I am aware of the strategy of extending the class and adding an ID property it. However, I'm looking for a solution that doesn't involve extending this class, because I need this solution to also be applicable for the case when it's not only one class that I have to persist, but a collection of interlinked classes - none of which has any ID property. In such a scenario, extending doesn't work out.
Eventually, I ended up doing the following:
public class EntryWrapper {
#Id
private long id;
#Embedded
private Entry entry;
}
So, I am indeed wrapping the entity but differently from the way that had been suggested. As the Entry class is vendor-provided, I did all its ORM work in an orm.xml file. When persisting, I persist EntryWrapper.
I don't have much experience with JPA, but I wouldn't extend your base classes, instead I would wrap them:
public class PersistMe<T> {
#Id
private long id;
private T objToWrap;
public(T objToWrap) {
this.objToWrap = objToWrap;
}
}
I can't test it, if it doesn't work let me know so I can delete the answer.
I want to wrap id in custom class. Like this
#Entity
#Table(name = "USERS")
public class User {
#EmbeddedId
UserId id;
}
#Embeddable
public class UserId implements Serializable {
private Long value;
}
The issue in auto generation value for UserId. What I should do to make #GeneratedValue on value be workable?
BTW, It would be great if id would be initialized automatically itself.
As far as I know Hibernate only generates values for a field marked as the #Id. I found this post and Hardy's answer supports this.
We have tried to do similar and managed it via a pre-insert listener. It was fairly complex and non-ideal though. Also you might find different behaviour on different database palatforms. Using Oracle sequences would mean that you need to assign the value pre-insert (Hibernate does a select to get the value and then an insert) but with MySQL the auto incrementing field would assign the value and hibernate does an insert to generate the auto generated value and then select to find out what the value was.
I've got the following schema in DB (simplified)
MainTable(
ID primary key
SOMEFIELD
CODE_FK1 -- references OtherTable1 CODE (without declared foreign key)
CODE_FK2 -- references OtherTable2 CODE (without declared foreign key)
... Other fields used
)
OtherTable1(
CODE primary key
LABEL
... other fields not used
)
OtherTable2(
CODE primary key
LABEL
... other fields not used
)
I'm asking if there is any way to define my Entity for main table in order to use directly labels from my other tables, i.e without defining entities for these other table.
I cannot change the DB schema, which is really awful (there are labels/code couples everywhere, defined in multiples tables).
And If it was possible, this solution would allow to keep my code simple, since I don't really need these other entities.
I guess it would result something like that:
#Entity
public class MainEntity{
#Id
private Integer ID;
#Column(name="SOMEFIELD")
private String SomeField;
#SomeAnnotation to Join CODE_FK_1 with OtherTable1.CODE
#SomeAnnotation like #Column(name="LABEL", table="OtherTable1")
private String Label1;
#SomeAnnotation to Join CODE_FK_1 with OtherTable1.CODE
#SomeAnnotation like #Column(name="LABEL", table="OtherTable1")
private String Label1;
}
Thanks by advance for your help!
Another possibility would be using the #Formula annotation to fetch the value from the other table. This will automatically generate a subselect whenever you load your Entity.
I think you'll need something like this:
#Entity
public class MainEntity{
#Id
private Integer ID;
#Column(name="SOMEFIELD")
private String SomeField;
#Formula("(SELECT ot1.LABEL FROM OtherTable1 ot1 WHERE ot1.CODE = CODE_FK_1)")
private String Label1;
}
There is little information about this in the [Hibernate docs][1], so you may need some trial and error to get it right (but you should be able to work it out with hibernate.show_sql=true.
There are 2 possible downsides to this approach:
This is hibernate-specific code
This is plain SQL, and may thus be database-specific
HTH
[1]: http://docs.jboss.org/hibernate/stable/annotations/reference/en/html_single/#entity-hibspec-property hibernate docs
You can use the #SecondaryTable annotation. See this example:
https://github.com/hibernate/hibernate-orm/blob/823a5c1ede1869fd97471e3b8ebe7ec4ac8068e4/hibernate-core/src/test/java/org/hibernate/test/annotations/join/Dog.java#L20-L24