Why does 'delete()' method in CrudRepository require entity with unique id? - java

In the description of the delete method in org.springframework.data.repository,CrudRepository interface it is written only that it deletes a given entity and that it accepts entity object itself.
It specifies nothing about entity's id needing to be unique.
However, this method works only when entity has an unique id. If the table may have multiple rows with the same id, this method fails when entity whose id is not unique is attempted to be deleted (at least in my case).
Now I understand that it is a very bad thing that an id is not unique in the table, but, in theory, it should work since this method accepts the entire entity as a parameter, and every entity (when all its columns are combined) in my table is unique. There are no two identical rows in a table since table has an unique constraint on a combination of all its columns.
Sure, there are other methods, like deleteById which would fail since they only accept id as a parameter and not the whole entity and since id is not unique, Spring does not know which entity to delete. Sure.
But why delete method fails when it should be able to distinguish between entities with the same id since it accepts the whole entitiy as a parameter (thus giving it access to all other columns of the entity and not just the id column)?

The requirement for the JPA id is that it is a primary key i.e. uniquely identifies the row. If you do not follow this, bad things will happen. You can have a composite primary key though, as it seems your row is identified by multiple columns. Look into #Embeddable/#EmbeddedId mappings for this purpose.

Related

What is the purpose of a primary key class (xxxPK.java) in Hibernate/Java and when is it appropriate to define one?

I am not familiar with Hibernate. I am trying to understand the purpose of defining a primary key class in Hibernate and where it would be appropriate.
I have to add new classes to some old code (early versions of Hibernate). I have a table called LOG which has the following fields among other fields
ID NUMBER
TRANS_ID VARCHAR2(40)
ID is the primary key (populated by oracle sequence). TRANS_ID is unique and populated by the application. Only search needed is by the TRANS_ID. There are no composite keys.
I believe I will need to define an entity class called Log.java and DAO class called LogDAO.java but do I need to define a LogPK.java for the Id field? I would not like to define one if this is not needed in my situation.

Does a Java Endpoints class need a Primary Key field?

Does Endpoints (Java) require a persistable class to have an id field?
Before endpoints, my JDO model itself did not have an id (primary key) field. Datastore has its own id field, and it generated a value upon inserting a new record. The model works, and I could insert records (with datastore successfully inserting and generating an id value).
I converted it to Endpoints (using Google Plugin for Eclipse), and made slight adjustments. The generated code is referencing an id that's not in the model. So I switched the parameter to another unique identifier (email address).
It compiles and deploys. But when I run API explorer, I can't insert. I'm getting "The class [class name] is not persistable."
But when I put an id field as primary key, now my inserts are asking for a value in id (which is not ideal for my situation).
Does endpoints require a class to have an id (unique identifier)? If so, is there a way to make appengine/datastore generate it for me? Thanks!
My assumption is yes, all such persistable classes need an id field. I add mine via Objetify with #Id. Here is the relevant documentation, also about autogenerating ids:
Entities must have have one field annotated with #Id. The actual
name of the field is irrelevant and can be renamed at any time, even
after data is persisted. This value (along with the kind 'Car')
becomes part of the Key which identifies an entity.
The #Id field can be of type Long, long, or String. If you use
Long and save an entity with a null id, a numeric value will be
generated for you using the standard GAE allocator for this kind. If
you use String or the primitive long type, values will never be
autogenerated.

Entities returned by Projection Queries

I'm designing an application in which I hope to use projection queries to retrieve Entity objects from the App Engine Datastore to save on latency and cost. I have two questions about this:
1) If one calls the Entity.getProperty(String propertyName) method on a returned Entity where propertyName does not correspond to one of the properties selected for by the Projection, will the return value be null or will Java throw an exception? The Entity documentation doesn't indicate what happens if propertyName does not exist. A corollary, do the not-selected-for properties no longer exist in the returned Entity or do they simply have no or null values assigned to them?
2) Is the Key of the truncated Entity that is returned the same as the Key of the original full Entity that's actually in the datastore? From what I understand, the Key is a hash of the kind, name/id property, and ancestor path of an Entity. Name/id also appears to be a property, so if one doesn't select for it, does the Key of the returned Entity differ from that of the actual Entity?
These questions seem like they would be fairly easy to answer with some testing once I'm up and running, but I'm new to App Engine and am still just designing my project, so I won't be in a position to do so for a while. Was hoping someone out there already knows the answer.
If a property does not exist in an entity, .getPropery() returns null. No exception is thrown.
If a property is not named in a projection query, the retrieved entity does not have this property even if the full entity does.
The key of an entity returned in a projection query is the same as in any other query. The key is created when an entity is first inserted in the datastore, and it does not change after that.
A little explanation. When you insert a new entity in the datastore, the datastore creates an entity and, separately, creates an entry for each indexed property, or a combination of properties (custom index), in a respective index. Projection query is just another combination of indexed properties. It retrieves all the data it needs directly from its own index without retrieving the entity itself.

No identifier specified for entity in java hibernate

I am using hibernate and i mapped my table with my bean. If i am not assign any particular column value as #id, it throws "No identifier specified for entity" error, however it is not primary key in my data table. I want to add multiple records with same data. how can i do it? When i annotated my product Name column with #id my code runs perfect.
Hibernate requires an identifier for each entity. However, it is possible to use native queries to insert new records. And, in the same way, to recover them.

Hibernate: #UniqueConstraint Across Multiple Tables?

I have a data model in which a number of entities inherit some common attributes from a single superclass entity. I am using InheritanceType.JOINED on the superclass, which causes Hibernate to create a single table for attributes defined in the superclass, with subclass tables containing only columns that are added by the subclass (so to load the attributes for a subclass instance, a join is performed between the two tables). That is all working fine.
What I'd like to do, however, is specify a unique constraint that includes fields in both the subclass and superclass tables. For instance, say that my superclass entity is something like:
Thing: {id, name}
...and then I have some subclass entities like:
Company: {address} //inherits 'id' and 'name' from 'Thing'
Employee: {company} //inherits 'id' and 'name' from 'Thing'
...and I want to configure Hibernate to automatically enforce that a given Company cannot have two Employee's with the same name. The company field is in the Employee table, but the name field is in the Thing table, so is there any way to get Hibernate to enforce this constraint, or do I need to do it programmatically whenever I add a new Employee?
If it's not possible in the Database it won't be possible with Hibernate. You can't create one constraint on multiple tables with SQL so neither in Hibernate.
You could work around this by creating a new Entity holding only the company and employee id and setting a unique constraint on those 2 fields but I would recommend enforcing this programmatically.
You could not use InheritanceType.JOINED, then everything ends up in a huge table, and you could write your constraint. As said before: What you want is just not possible in a relational DB.

Categories