how hibernate manage serialization id while saving/fetching object in/from DB - java

As per my understanding to manage consistency serialization algo maintain one serialization id as private static final long serialVersionUID = 3170588813843556321L; in class while saving/fetching object from stream. and that id will be saved in that file/stream.
But with DB while we are NOT saving this in DB at all, so how hibernate check consistency during deserialization and throw java.io.InvalidClassException.
Please correct me if i am wrong at my understanding....

hibernate does not use serialization to store your classes into the database. it works by way of object relational mapping and (simplistically) maps every attribute of your object to a column in a table.
only if you have specific types of attributes (say public Image getImage()) will it store "real" binary - it might map this attribute to a blob to use serialization/deserialization to store/load the image attribute of your mapped class.
checking for data consistency in hibernate is done either via explicit locking (it locks the rows that make up your entity as long as your entity is in use) or via optimistic locking - where it will add a "version" field to your entity, update it every time you modify the entity, and use sql of the form "update table set ... where version=:myVersion" to ensure that no 2 processes modify the same entity at the same time.

Related

Mapping derived columns to POJOs with RecordMapper in JOOQ

i have a table tickets where i insert ticket and have a field createdBy which stores the UserId Integer of the creator of that record. During fetching I join with users table and concat firstname and last name and my DTO has field createdBy of the concatenated name of creator. How can i map the derived field? this is my reference https://www.jooq.org/doc/3.13/manual/sql-execution/fetching/pojos/ and I cant seem to find such a scenario provided
the issue is not the join. the issue is mapping the string createdBy derived after the join whereas in the record class generated by jooq is an Integer because in the database table i store the userId.
List<MyTickets> mytickets = create.select(....FIELDS).from(TICKETS_).fetch().into(MyTickets.class);
#Override
public Field<Integer> field9() {
return Tickets.TICKETS_.CREATEDBY;
}
In my answer, I will assume that your computed column is going to be called CREATED_BY_NAME, not CREATED_BY, which is a name that's already taken, and to avoid confusion.
If this is something you do frequently, you have a few options that could be interesting to you:
Use views to generate this alternative CREATED_BY_NAME column. A lot of databases can insert into / update views as well, so you won't have a big penalty in using views to replace your tables. To your client logic, the origin of this column will be transparent. If you want to work with UpdatableRecord, you will have to tell jOOQ's code generator what the view's underlying primary key is using the synthetic primary key flag.
Similar to the above views, you could use computed columns on your tables, using the GENERATED ALWAYS AS ... syntax (or whatever your dialect uses for the syntax). Not all dialects support this, but it is a nice feature that turns tables into views without the extra view object.
If you want to keep computing this column manually in your jOOQ code, you could either write your own DTO / POJO objects, or extend the code generator with a custom code section, where you generate the relevant attribute / getter / setter. This approach only works for mutable POJOs, as you cannot modify the constructor of an immutable POJO.
You can also specify a base class for all of your affected POJOs and inject that base class using a generator strategy (programmatic or configurative). The base class could then implement all the getters / setters for columns like CREATED_BY_NAME.
You can also use structural typing instead. You don't have to map all the columns into your POJO. You could also map some columns into your generated POJO (excluding CREATED_BY_NAME) and map the CREATED_BY_NAME column separately. Just keep a reference to your jOOQ Result and/or Record, and perform several map / intoXYZ() calls on it.

How to prevent Spring Data MongoDB from mapping id field as object id?

I have set up my own mechanism for assigning identities to my domain objects, and so when persisting them, there really isn't much value for me to keep track of what MongoDB assigns to them. However, I name the identity fields for my domain classes id because, well, it's concise and understandable. The problem is that, according to the documentation, Spring will automatically map this field to MongoDB's assigned ObjectID. How do I prevent this from happening without having to rename my id field, or defining a custom identity field annotated with #Id just for the sake of working around this?
Use #MongoId instead of #Id
#MongoId(targetType = FieldType.STRING)
protected String id;
It will store String even if the "shape" is an ObjectId
Well, you can't do that with Spring data I am afraid. Mongodb (and in turn, Spring data) needs a field to uniquely identify each document. If you have an id field already, and if it's unique for each and every object then yes, you can annotate it with #Id and mongo will take care of the rest.
If not, you will have to create a new field and map it to _id.

JAVA DAO/Hibernate: persist & retrieve generic hashmap into/from Database field

I'm new to hibernate and I would like to store a hashmap of primitive objects into a oracle DB field.
In fact, depending on the process, different keys are put inside the map so I cannot create a DB field for each key (as I don't know them upfront. also I would like to put all the information in a single DB field).
Is it possible to do so? should data be compressed?

Can I override generated IDs?

I'm using JPA 1, Hibernate and Oracle 10.2.0 and my entities are defined like this:
#Entity
#Table(name="TERMS")
public class Term implements Serializable {
#Id
#GenericGenerator(name = "generator", strategy = "guid", parameters = {})
#GeneratedValue(generator = "generator")
#Column(name="TERM_ID")
private String termId;
}
I have a situation where an XML representation of the Entity (and child entities) will be coming in through a web service to update/replace existing ones. My thought was to just delete the old ones and re-create it from the incoming XML.
However, doing a persist when my entities having existing IDs seem to make Hibernate very angry. So is this actually possible or is it better to avoid deleting them and just trying to do it with merge?
Angriness from hibernate:
org.hibernate.PersistentObjectException: detached entity passed to persist: com.idbs.omics.catalog.entity.Term
Thanks
My thought was to just delete the old ones and re-create it from the incoming XML. However, doing a persist when my entities having existing IDs seem to make Hibernate very angry..
Indeed, you cannot assign an Id when it is supposed to be generated, at least not with Hibernate that won't consider the entity as new but as detached (the JPA specification is a bit blurry on the exact rules in this case but that's how Hibernate behaves, see 5.1.4.5. Assigned identifiers for more hints).
So is this actually possible or is it better to avoid deleting them and just trying to do it with merge?
To make the delete/insert possible for the web service use case, you'd have to either:
not assign the id ~or~
use a special version of the entity without a generated identifier ~or~
use bulk operations(?)
The alternative if you're actually updating detached entities would be indeed to use a merge (but have a look at these previous questions just in case).
Which approach is better? I don't know, it think it depends on your needs. The later seems more natural if you're updating existing entities. With the former, you'd really get "new" entities (including a new value for the optimistic locking column). Depending on the exact implementation of the process, performances might also vary. And, by the way, what about concurrency (just to mention it, I'm not really expecting an answer)?
You can use EntityManager.merge to save an updated version of the entity. Be aware that this returns another object than the one you pass to it, because it basically fetches the entity from the database, updates the persistent properties from the object you pass and saves the persistent object.
See http://blog.xebia.com/2009/03/23/jpa-implementation-patterns-saving-detached-entities/ for more information on this problem.

How to inject custom object ids into JPA entities

I am using JPA 2 for an enterprise application, and my DBA's just hit me with a twist.
They want me to use the group's centralized object ID generator for all my tables. This means rather than using table values or a sequence table, I will need to call a web service to get a batch of ~50 ids.
Then, as I persist any new object, I would need to inject this id first, and save that to the table.
So how would I manipulate the #Id column of an entity to handle this.
Is it as simple as setting a key before I persist? I suspect that would throw some sort of unmanaged entity with ID set error.
Update:
The better method is to actually specify a Sequence strategy on Generated fields and specify a custom Sequence class.
JPA will then call this class's nextId() method every time it inserts a new object.
This method allows full graphs to be persisted without intervening on each entity manually.
Figured it out. Amazingly complex ;) - just remove the GeneratedValue annotation from the key field.
It is intended for Native Ids like SSN or email, but works regardless of source.
#Entity
public class Client{
#Id
#Column(name="CLNT_ID")
private long key;
#Column(name="CLNT_NUM")
private String clientNumber;
...
}

Categories