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().
Related
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).
My understanding is that when using objectify, you can generate a datastore key in one of two ways:
Specify a unique ID to an object, which will be used to generate the datastore key (unique ID assigned to data member with annotation #Id)
Don't specify unique ID, so a datastore key will be autogenerated (Annotation #Id on data member still exists, but nothing is assigned to it)
Using option 1, in order to load a specified entity we first obtained a key using Key.create(SomeEntity.class, uniqueID) where uniqueID would be unique.
If I decide to go with option 2, how do I load a desired entity if I had let the datastore autogenerate a key?
With any other parameter? If you create an object without deciding on the key, but provide (for instance) a city, a userName, an email, then you search by city, username, email. Once you have that, you have the object. From there you can get the object's key if you need it.
If your entity #Id field is null and you save it synchronously with .now() then the #Id annotated field (assumed "id" in this example) will be set to an auto-allocated/generated value during the following call.
ofy().save().entity(someEntity).now();
Long myId = someEntity.getId();
Then someEntity.getId() would be a valid generated String/Long that you can use, note somewhere, provide to a user, return from an API etc so that later:
ofy().load().type(Entity.class).id(myId).now();
If you need to save the entity asynchronously (without .now()) then that's possible too, just use the allocateId function from ObjectifyFactory to set the id before saving to ensure a unique id - this is similar to your 1) but a safe way to generate the UniqueId that is assured to be unique.
Searching afterwards for the entry by querying a combination of fields should typically be avoided as depending on your data it may not match a single entry and you'd need to index those fields adding costs.
Currently the OpenJPA reverse mapping tool generates the foreign key for entities as object types. Is there a way to make them primitive types?
Whenever you persist a new entity, it inserts '0' in place of an uninitialized primitive type (which is in line with Java initialization defaults for primitives). It would have to be the same with foreign keys, which means OpenJPA would have to generate invalid foreign keys (with "0" id, which is perfectly valid id from DB's point of view).
So, there's only the option:
-nullableAsObject/-no <true/t | false/f>:
By default, all non-foreign key columns are mapped to primitives
but, as noted, it's valid for non-FKs only.
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
}
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.