I have a base entity class
where one of the fields(Timestamp) has #version attribute, so Jpa will automatically increment the value.
But, sometimes the timestamp value is not getting updated, the edited date is less than the created date, but this should never happen theoretically.
I am not setting the edited value programmatically.
Here is my entity class:
public class BaseEntity implements Serializable {
#Column(name = "CREATED")
private Timestamp created;
#Column(name = "EDITED")
#Version
private Timestamp edited;
// other fields, getters and setters
}
Have read many articles about this #version annotation, but I don't understand why this value will not update, what are the reasons behind this.
If some one help me, would be great
Thanks
Here are some basic guidelines:
Check if you imported the right package javax.persistence.Version.
Use obj = entityManager.merge(obj); when saving changes to already persisted entities.
Never change the value of your version-field manually. The entity-manager will take care of it.
For further debugging edit your persitence.xml and add following lines to properties:
<property name="eclipselink.logging.level" value="FINE"/>
<property name="eclipselink.logging.parameters" value="true"/>
<property name="eclipselink.logging.sql.level" value="FINE"/>
This will enable fine logging and generate a lot of output. You'll be able to see the update queries and what exactly happens.
Related
I have to create a simple database using Hibernate, but whatever i did, i got this error:
org.hibernate.MappingException: Repeated column in mapping for entity: tr.com.ozer.datastructures.GameObject column: x (should be mapped with insert="false" update="false")
Firstly i am using PostgreSQL 11, and Hibernate 5.4
Here is what i am trying to do:
#Embeddable
public class Position {
private Integer x;
private Integer y;
// Setters end getters
}
#Entity
public class GameObject {
#Id
private Integer id;
#Embedded
private Position absPosition;
#Embedded
private Position relativeToBaseA;
#Embedded
private Position relativeToBaseB;
// Setters and getters
}
I do not want to use #AttributeOverrride since my Position class have more fields then here and i dont want to define all of them for every field. Instead i would just write seperate fields.
And I dont care database column names so much atm. Are there any auto-naming mechanisim in Hibernate? Like absPosition_x, absPosition_y, relativeToBaseA_x, relativeToBaseA_y etc.
Note: Despite that i have the "implicit_naming_strategy" conf in my hibernate.cfg.xml, i still get the error. Here is the line:
<property name="hibernate.implicit_naming_strategy">org.hibernate.boot.model.naming.ImplicitNamingStrategyComponentPathImpl</property>
Ok, the error is on my part. But i will post my solution in case anyone has it.
I have been using Hibernate 5 and initializing it with the old method.
After i initialized with StandardServiceRegistry, the error perished.
It is actually interesting, the old way initializing metod works normal without #Embedded annotations on version 5.4. It should give "wrong way initialition error" or something and i wouldnt have spend hours on this one!
I've already asked this question on the Hibernate's forum, but I thought I'd ask it here too.
I'm trying to map the following model while preserving the value semantics of the TranslatedText and Translation value objects:
Both values as dependent objects
Ideally I'd map TranslatedText as a <component> within Question and Translation as a <bag> of <composite-element> within TranslatedText.
It would have been simple to map if Question was only referencing one TranslatedText, but since it references two I need some kind of discriminator based on the name of the property holding the value (title or description) in order to map the Translation with a foreing key composed of (question_id,property_name,language_code).
One problem with that is that the propertyName isin't part of the model and shouldn't, but I haven't found a way to force Hibernate to insert a value that doesn't come from the model.
Therefore, I tried to change the model and introduce specialized Title and Description classes so that I'd have a type in there that I could use as a discriminator.
At the end that did not really help much:
<component name="title" class="TranslatedText">
<bag name="translations" table="Translation">
<key>
<!-- PROBLEM: Could not find a way to create a custom join expression on question.id and question.title.type in here. -->
</key>
<composite-element class="Translation">
<!-- PROBLEM: Could not found a way to make Hibernate insert title.type from here, without having this value on the Translation object. -->
<property name="languageCode" type="string" column="language_code"/>
<property name="text" type="string"/>
</composite-element>
</bag>
</component>
TranslatedText with <many-to-one>
I managed to get something close to what I need by mapping TranslatedText as an entity within Question using a <many-to-one> and then map Translation as a collection of values within TranslatedText, but the main problem with that approach is that there is no easy way to get rid of the orphaned TranslatedText and Translation. I'd either have to do this with a DB trigger or a scheduled process.
Conclusion
At this point I'm under the impression that Hibernate is not flexible enough to map the initial model with the proper semantics, but hopefully I'm wrong and there is a way to do it.
I have not found a way to map them as values. However the next solution works and it might be helpful for you. I removed TranslatedText and linked Question directly with collection of Translation.
#Entity
public class Question {
#Id
private String id;
#JoinTable
#OrderColumn
#OneToMany(fetch = EAGER, cascade = ALL)
private List<Translation> titleTranslations;
#JoinTable
#OrderColumn
#OneToMany(fetch = EAGER, cascade = ALL)
private List<Translation> descriptionTranslations;
}
The drawback here is that Translation has to be Entity class.
#Entity
public class Translation {
#Id
private String id;
private String languageCode;
private String text;
}
I'm developing an application using:
Java 1.7
JPA (included in javaee-api 7.0)
Hibernate 4.3.8.Final
PostgreSQL-JDBC 9.4-1200-jdbc41
PostgreSQL 9.3.6
And I would like to use the PostgreSQL text datatype for some String attributes. As far as I know, in JPA this should be the correct annotation, to use text in PostgreSQL:
#Entity
public class Product{
...
#Lob
private String description;
....
}
When I annotate my entity like this, I run into errors which look like this:
http://www.shredzone.de/cilla/page/299/string-lobs-on-postgresql-with-hibernate-36.html
In short: It seems that hibernate and jdbc go not hand in hand for clob/text-types.
The solution described is working:
#Entity
public class Product{
...
#Lob
#Type(type = "org.hibernate.type.TextType")
private String description;
...
}
But this has a significant downside: The source code needs hibernate at compile time, which should be unnecessary (That's one reason for using JPA in the first place).
Another way is to use the column annotation like this:
#Entity
public class Product{
...
#Column(columnDefinition = "text")
private String description;
...
}
Which works nicely, BUT:
Now I'm stuck with databases which have a text type (and is also called text ;) ) and if another database will be used in the future the annotations can be overlooked easily. Thus the possible error can be hard to find, because the datatype is defined in a String and therefore can not be found before runtime.
Is there a solution, which is so easy, I just don't see it? I'm very sure that I'm not the only one using JPA in combination with Hibernate and PostgreSQL. So I'm a little confused that I can't find more questions like this.
Just to complete the question, the persistence.xml looks like this:
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="1.0"
xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence
http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd">
<persistence-unit name="entityManager">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<class>com.app.model.Product</class>
<properties>
<property name="javax.persistence.jdbc.driver" value="org.postgresql.Driver" />
<property name="javax.persistence.jdbc.url"
value="jdbc:postgresql://localhost:5432/awesomedb" />
<property name="javax.persistence.jdbc.user" value="usr" />
<property name="javax.persistence.jdbc.password" value="pwd" />
<property name="hibernate.dialect" value="org.hibernate.dialect.PostgreSQLDialect" />
<property name="hibernate.jdbc.use_streams_for_binary" value="false" />
<property name="hibernate.hbm2ddl.auto" value="create-drop" />
<property name="show_sql" value="true" />
</properties>
</persistence-unit>
</persistence>
UPDATE:
This problem is more or less equivalent with this question, the picked answer is the second way to do it described in this question, which I don't like due to the hibernate runtime dependency:
store strings of arbitrary length in Postgresql
This seems to be kind of related to: https://hibernate.atlassian.net/browse/JPA-48
Since the text type is not a part of the SQL standard there is no official JPA way I guess.
However, the text type is quite similar to varchar, but without the length limit. You can hint the JPA implementation with the length property of #Column:
#Column(length=10485760)
private String description;
Update: 10 MiB seems to be the maximum length for varchar in postgresql. The text is almost unlimited, according the documentation:
In any case, the longest possible character string that can be stored
is about 1 GB.
I just had to add this annotation:
#Column(columnDefinition="TEXT")
It did not work on its own. I had to recreate the table in the database.
DROP TABLE yourtable or just alter column type to text with ALTER TABLE statement
If you want to use plain JPA you could just remap the used CLOB type on the Dialect like this:
public class PGSQLMapDialect extends PostgreSQL9Dialect {
#Override
public SqlTypeDescriptor remapSqlTypeDescriptor(SqlTypeDescriptor sqlTypeDescriptor) {
if (Types.CLOB == sqlTypeDescriptor.getSqlType()) {
return LongVarcharTypeDescriptor.INSTANCE;
}
return super.remapSqlTypeDescriptor(sqlTypeDescriptor);
}
}
So it won't use the CLOB mapping from the JDBC driver which uses a OID for the column and stores/loads the text via large object handling.
This would just result in setString and getString calls on the createt text column on the Postgres JDBC Driver via the VarcharTypeDescriptor class.
I would go with simple private String description;. The column type is only a problem if you are generating the database from your code, because it will be generated as varchar instead of text.
It is great to code in database agnostic way, and without any JPA vendor specific things, but there are cases where this just isn't possible. If the reality is that you will have to support multiple database types with all their specifics, then you have to account for those specifics somewhere. One option is to use columnDefinition for defining column type. Another is to leave the code as it is, and just change the column type in the database. I prefer the second one.
I am currently working on a JavaSE project that I would like to build in the most effective way. My project is an employeeManagementSystem which has several schemas. For example I have one schema called employees which contains employee data and another schema called company which contains the company data.
Currently I have implemented my entities and tested these using hibernate.cfg.xml to make sure they are implemented correctly. For example, one such entity in the employee schema is
#Entity
#Table(name="employees", uniqueConstraints= {
#UniqueConstraint(columnNames="idEmployees"),
#UniqueConstraint(columnNames="idCardNumber"),
#UniqueConstraint(columnNames="niNumber")
})
public class Employee {
#Id
#GeneratedValue
#Column(unique=true, nullable=false, updatable=false)
private int idEmployees;
#Column(unique=true, nullable=false, updatable=false)
#Size(min=1, max=15)
private String idCardNumber;
#Column(unique=true, nullable=false, updatable=false)
#Size(min=1, max=15)
private String niNumber;
#Column(nullable=false, updatable=false)
#Size(min=1, max=20)
private String name;
#Column(nullable=false)
#Size(min=1, max=20)
private String surname;
// Other class variables
//Constructors
//getters & setters
}
I an now trying to use an EntityManager to manage my schemas. My persistence.xml for the employee schema is
<persistence xmlns="http://java.sun.com/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd"
version="2.0">
<persistence-unit name="EmployeesDAO" transaction-type="RESOURCE_LOCAL">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<class>com.shopmanagementsystem.employeesdao.entities.Employee</class>
//Other classes in this schema
<properties>
<property name="hibernate.dialect" value="org.hibernate.dialect.MySQLDialect"/>
<property name="javax.persistence.jdbc.driver" value="com.mysql.jdbc.Driver"/>
<property name="javax.persistence.jdbc.user" value="root"/>
<property name="javax.persistence.jdbc.password" value="root"/>
<property name="javax.persistence.jdbc.url" value="jdbc:mysql://localhost:3306/employees"/>
</properties>
</persistence-unit>
</persistence>
I want to create a Service and ServiceImpl class to manage the processes related to the entities.
Q1) Should I have a Service and ServiceImpl for each entity?
Some of my questions were answered already in a previous post JPA EntityManager Construction
Q2) I further asked about using #PersistenceContext and was kindly advised to ask another question with a more detailed description of my project.
I am happy to add more details if I've left anything out and thank you for your advice and help.
Q1) Should I have a Service and ServiceImpl for each entity?
Not necessarily. Based on the name of the persistence unit: EmployeesDAO, I'm assuming that Service and ServiceImp are intended to implement DAO pattern, right? In this context you have to offer a contract (INSERT / UPDATE/ DELETE / QUERY) just for those entities that actually require it. For example you can have a table called Category which has a relationship with Employee like this:
#Entity
#Table(name="categories")
public class Category implements Serializable {
...
#Id private BigInteger idCategory;
#Basic private String description;
...
}
#Entity
#Table(name="employees")
public class Employee implements Serializable {
...
#ManyToOne
#JoinColumn(name="idcategory", referencedColumnName="idcategory")
private Category category;
...
}
In this example you would have a Service to manage Category entities only if you need to. If those entities are managed by another application then you just need to have read privileges on categories table so the entity manager can map this data and that's it.
Q2) I further asked about using #PersistenceContext and was kindly advised to ask another question with a more detailed description of my
project.
First of all please beware that #PersistenceContext annotation is intended to be used with container-based persistence, as part of a Java EE application. You cannot use this annotation in plain Java SE platform.
On the other hand it doesn't mean you can't use JPA. Yes, it's perfectly possible, but you have to take care of the whole entity managers life-cycle. It is a common practice in this case to implement design patterns (such as Abstract Factory or Factory method or Singleton) in order to instantiate/access your entity managers manually.
In addition if you want to develop the top level layers of your application using Java SE and use container-managed persistence, then you can code the persistence layer using JPA and Enterprise JavaBeans architecture. This approach is not simple but has several advantages:
You can offer the persistence layer as a service through EJB modules.
Database connections and pools can be managed by the EJB container. This is extremely useful to separate database connection info from persistence.xml file.
As already mentioned, the EJB container will manage the whole entity manager life-cycle.
You can go further and leave container use Java Transaction API so you can forget (more or less) about transactional stuff.
Other comments
I know that posted persistence.xml is probably just an example but I have to mention that connect to the database as root user is not a good practice at all. Due to security reasons you should have several users with the right privileges to access your database, and likely none of them will ever need super-user privileges.
Finally, applications design is a really broad topic and it can be simple or complex based on your requirements. In addition there are several frameworks/technologies that can be used and is very very easy to get lost if you don't have any experience. My suggestion if you never did something like this before is to start with a very basic application and then go further.
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.