I got the answers from u all regarding the previous topic that was use of hibernate with table not having any primary key, but i have one question that can we use transient keyword prefixed to ID variable in the entity class so that not to persist that value into database???????
No. You must have a persistent ID in all your Hibernate entities. The transient keyword is used to avoid serializing it when transferring the object to another JVM (or to a file). The #Transient annotation is used to mark a field not persistent, but it can't be used for the ID, which is absolutely necessary in order to use Hibernate.
just add transient keyword in declaration
For Example
private transient Image thumbnailImage;
Same answer again.
If the ID is not stored in database, then how it will identify an unique row?
In your case, the prmiary key will be null or empty. If a primary key can be null?
I think you should take any auto increment ID as primary key. It should not affect your database design.
Related
I found that if the entity mapping without a hibernate generated primary key value, the SelectBeforeUpdate(false) will not working.
#Entity
#SelectBeforeUpdate(false)
class X {
protected X(){}
#Id
#GeneratedValue
UUID id;
int x;
}
If comment out #GeneratedValue, assign id value in X ctor, the #SelectBeforeUpdate(false) will lose its functionality.
Due to hibernate will check a detached object is transient or not by ForeignKeys.isTransient in org\hibernate\engine\internal\ForeignKeys.java which finally call IdentifierValue.isUnsaved in org\hibernate\engine\spi\IdentifierValue.java. Without #GeneratedValue, hibernate use a static UNDEFINED instance of class IdentifierValue which isUnsaved method always return null. That will cause ForeignKeys.isTransient return null so that hibernate will build the snapshot at last which will trigger a selection SQL.
However, the problem is that #GeneratedValue split the object construction to 2 phase: first new it then pass it into session.save. I don't like this, is there a workaround to make #SelectBeforeUpdate(false) works without let hibernate generated the #Id value? I use UUID to be the pk so it is unnecessary let hibernate to do this.
I use hibernate 5
Finally I figure out this mechanism. For hibernate, the #Id field are processed in an uniformed procedure whatever the type is: if you want hibernate generate the id value for you, you must call session.save, even the id value can be determined at the stage of object construction.
This is problematic: if user use UUID to be the primary key, that means user want to determine the value ahead of communicating with database. For some complex logic, after the object A create, the object A need to do some additional things, after that, the object A need along with another object B in an transaction to commit to database. If the object A's id is null till database commit, it is very inconvenient due to object is not a complete object yet.
Hibernate use the uniform id generation procedure as an assumption which used to determine the object is transient or not. If #GeneratedValue is add, hibernate consider object is transient only if the id value is null(This is quite simple, if the id value is not null, then session.save must be called). If without a generator, hibernate can not know the fact, the only way to find out is select it out from database. So it have to omit the #SelectBeforeUpdate(false)
The only way to alter the procedure is self define a Interceptor which override the Interceptor.isTransient, however doing this require user implement the transient checking. If always return false in it, the save and update must be called precisely.
Is it possible to set custom generated String ID for a Entity?
i.e
jetbrains.exodus.entitystore.Entity
Say application generates a alerady unique key using Java UUID or some kind of Object ID can it be used as value of EntityId.toString()
EntityId is an internal id used for managing links under the hood. If it doesn't meet your requirements just use your own app-level id as a property assigned to an entity. You can easily find entities by property values (searching by property value).
I get this DDL (postgres target) when I add the goal hbm2ddl using the Maven plugin hibernate3-maven-plugin:
create table listing (
id varchar(36) not null,
hash_code int4 not null,
version int4,
name varchar(100),
primary key (id)
);
I defined all the columns shown.
All examples of using that I have seen on the web of:
private static final long serialVersionUID = -8402611044513083864L;
never have a #Column annotation. My DDL does not have a column for it. Does anybody else's?
So how does the deserialization code in Java know what version of a class was serialized and stored vs the one that it is being deserialized into?
Serial version UID is used when object is serialized / deserialized.
If you annotate your object as an JPA Entity you're not using a serialization but just transforming your object to another representation - as a row in the database table.
When you fetch the row from the database, this data is used to create a new instance of object with properly set state.
Serialization, on the other hand, is used if you want to construct a binary representation of your object and then recreate the object instance using deserialization process.
Note that you can use serialization with JPA i.e. if you want to persist a field (within your JPA entity) which is neither a basic type, embeddable nor other entity but just a plain Java class which implements Serializable marker interface.
However, in this case only this given field in your entity is using serialization/deserialization to put binary data into database column. Still - the serial version UID is not stored anywhere in the database.
For more information about persistent fields (which are persisted and which are not) you can take a look at 2.2 Persistent Fields and Properties chapter in JPA 2.0 FR specification.
static values are never serialized, and JPA does not use java serialization.
Does anyone know how Hibernate knows whether to INSERT or to UPDATE a value in the database when session.saveOrUpdate() is called?
So far, I have only determined that it is not dependent on the information in the cache, and that the existence of the entity in the database is determined by the primary key.
When you use .saveOrUpdate() Hibernate will check if the object is transient (it has no identifier property) and if so it will make it persistent by generating it the identifier and assigning it to session. If the object has an identifier already it will perform .update().
From the documentation:
saveOrUpdate() does the following:
if the object is already persistent
in this session, do nothing
if another object associated with the
session has the same identifier,
throw an exception
if the object has no identifier
property, save() it
if the object's identifier has the
value assigned to a newly
instantiated object, save() it
if the object is versioned by a
"version" or "timestamp", and the
version property value is the same
value assigned to a newly
instantiated object, save() it
otherwise update() the object
Perhaps it is helpful to quote the Hibernate bible (Java Persistence with Hibernate, 2nd ed., page 528):
More experienced Hibernate users use saveOrUpdate() exclusively; it's much easier to let Hibernate decide what is new and what is old, especially in a more complex network of objects with mixed state. The only (not really serious) disadvantage of exclusive saveOrUpdate() is that it sometimes can't guess whether an instance is old or new without firing a SELECT at the database - for example, when a class is mapped with a natural composite key and no version or timestamp property.
How does Hibernate detect which instances are old and which are new? A range of options is available. Hibernate assumes that an instance is an unsaved transient instance if:
The identifier property is null.
The version or timestamp property (if it exists) is null.
A new instance of the same persistent class, created by Hibernate internally, has the same database identifier values as the given instance.
You supply an unsaved-value in the mapping document for the class, and the value of the identifier property matches. The unsaved-value attribute is also available for version and timestamp mapping elements.
Entity data with the same identifier value isn't in the second-level cache.
You supply an implementation or org.hibernate.Interceptor and return Boolean.TRUE from Interceptor.isUnsaved() after checking the instance in your code.
As stated here, saveOrUpdate either saves a transient instance by generating a new identifier or updates/reattaches the detached instances associated with its current identifier. More specifically it does:
if the object is already persistent in this session, do nothing
if another object associated with the session has the same identifier, throw an exception
if the object has no identifier property, save() it
if the object's identifier has the value assigned to a newly instantiated object, save() it
if the object is versioned by a <version> or <timestamp>, and the version property value is
the same value assigned to a newly instantiated object, save() it
otherwise update() the object
This is done based on the value of the primary key. If the primary key is undefined, it's value will default to 0 for numeric surrogate keys and save will be performed. If the primary key is filled out, it will invoke an update.
If someone not really understood in theory then there is a code
MyModel sent = myDao.myDaoImpl(id);
if(sent == null){
sent = **new MyModel();** // new Object
sent.setXX(id);
sent.setYY("Yes");
sent.setDate(new Date());
myDao.saveOrUpdate(sent); // Insert will be called
} else if(! "Yes".equalsIgnoreCase(sent.getFlag())) {
sent.setXX("Yes");
sent.setDate(new Date());
myDao.saveOrUpdate(sent); // Update will be called
}
The generator element in the hibernate mapping file is supposed to be used to determine how the primary key is generated. Why is the default value assigned bad for detached and transient objects?
If you want the application to assign identifiers, as opposed to having Hibernate generate them, you can use the assigned generator. This special generator uses the identifier value already assigned to the object's identifier property. The generator is used when the primary key is a natural key instead of a surrogate key. This is the default behavior if you do not specify a element.
The assigned generator makes Hibernate use unsaved-value="undefined". This forces Hibernate to go to the database to determine if an instance is transient or detached, unless there is a version or timestamp property, or you define Interceptor.isUnsaved().