EclipseLink : EntityManager.merge() : Why TENANT_ID not added runtime for UPDATE operation? - eclipselink

I have gone through EclipseLink Single Table Multi-Tenancy feature spec.
BELOW is some portion by reading, I am little bit surprised.
Task 4: Perform Operations and Queries
The tenant discriminator column is used at runtime through entity manager operations and querying. The tenant discriminator column and value are supported through the following entity manager operations:
persist()
find()
refresh()
The tenant discriminator column and value are supported through the following queries:
Named queries
Update all
Delete all
Why TENANT_ID is not used at runtime for below operations.
merge()
delete()
Why It is not needed for below operations? I need it because when updating any record , I need to append TENANT_ID in WHERE clause of UPDATE query.
Because, In a single table multi-tenancy, there will be users with same user for more than one tenant and I need TENANT_ID to update only specific tenant record.
Please help me in this, as I am stuck only in merge() operation.

We had the same symptoms and the answer for us was to add primaryKey=true to the tenant discriminator annotation to indicate that the tenant_id must be included as a part of the primary key used in delete and merge operations:
#Multitenant
#TenantDiscriminatorColumn(name = "tenant_id", contextProperty = "tenant_id", primaryKey=true)

Related

Is it possible to define a field that auto-increments within the value of a foreign key?

Is it possible to define a field that auto-increments within the value of a foreign key?
E.g. if we define Company and Department models in Django:
class Company(models.Model):
name = models.CharField(max_length=25)
class Department(models.Model):
company = models.ForeignKey(Company)
department_number = ...? # should start from 1 for each company
in a pure SQL implementation the pair (company_id, department_number) would be a composite primary key.
I'm looking for solutions in Django or SQL that are safe (in terms of multiple processes creating departments simultaneously) and efficient. I'm using MySQL, but comparisons with other databases are also welcome.
On SQL server one can use TRIGGER to do something extra after insert. Trigger is transaction safe and could be rolled back. Another way is to use an intermediate sequence table.

Prevent duplicates for a certain GraphCool model

I have a GraphCool model called Student which has a field called studentNumber. How can I prevent two (or more) different Student nodes with the same studentNumber? In SQL databases I was able to create a unique index to accomplish this.
The easiest way to do so is by enabling the "Unique" constraint for a certain field (studentNumber in your case for the Student model). You can enable constraints in the structure view when editing a model.
Note: Under the hood, this creates a unique index in the database just like you suggested.

Domain Driven Design Auto Incremented Entity Key

Just starting with Domain Driven Design and I've learned that you should keep your model in a valid state and when creating a new instance of a class it's recomended to put all required attributes as constructor parameters.
But, when working with auto incremented keys I just have this new ID when I call an Add method from my persistent layer. If I instanciate my objects without a key, I think they will be in a invalid state because they need some sort of unique identifier.
How should I implement my architecture in order to have my IDs before creating a new instance of my entity ?
Generated Random IDs
The pragmatic approach here is to use random IDs and generate them before instantiating an entity, e.g. in a factory. GUIDs are a common choice.
And before you ask: No, you won't run out of GUIDs :-)
Sequential IDs with ID reservation
If you must use a sequential ID for some reason, then you still have options:
Query a sequence on the DB to get the next ID. This depends on your DB product, Oracle for example has them).
Create a table with an auto-increment key that you use only as key reservation table. To get an ID, insert a row into that table - the generated key is now reserved for you, so you can use it as ID for the entity.
Note that both approaches for sequential IDs require a DB round-trip before you even start creating the entity. This is why the random IDs are usually simpler. So if you can, use random IDs.
DB-generated IDs
Another possibility is to just live with the fact that you don't have the ID at creation time, but only when the insert operation on the DB succeeds. In my experience, this makes entity creation awkward to use, so I avoid it. But for very simple cases, it may be a valid approach.
IN adition to theDmi's comments
1) You can in your factory method make sure your entity gets stored to the database. This might or might not be applicable to your domain but if you are sure that entity is going to be saved that might be a valid approach
2) You can separate the ID from the primary key from the database. I've worked with a case there something was only an order if the customer payed and at that point it would be identified by it's invoice id (a sequentual ID). that doesn't mean in the database i would need an column ID which was also the primary key of the object. You could have a primary key in the database (random guid) and till have an ID (int?) to be sequentual and null if it hasn't be filled yet.

Modifying Postgres SQL queries with rules

I'm trying to determine if it's possible to write rules for Postgres to dynamically alter queries at runtime.
Essentially, I have a multitenancy solution that uses a mapping table to determine if a row is owned by a tenant. I've simplified the examples below for easy reading.
In these examples, "car" table is scoped to a particular tenant by a carmapping table which has foreign keys scoped_model_id pointing at the car table and scoping_model_pk pointing at the tenant/customer/whatever model that can generically be considered a "scoping model" used to scope various tables in the application.
Example scoped query:
SELECT "car"."id" FROM "car" WHERE
("car"."id" IN (SELECT U0."scoped_model_id" FROM "carmapping" U0 WHERE U0."scoping_model_pk" IN (1));
Original query:
SELECT "car"."id" FROM "car";
Is there a way to use rules to dynamically add these WHERE clauses?
It would need to be capable of determining what scoping_model_pk is active in the current request - whether that is passed to Postgres as an additional piece of metadata for all db cursor connections or embedded as a noop string somehow within the SQL statement itself. And will also need to determine what the mapping table is for the model currently targeted by the SELECT statement - in this case, carmapping.
We can do this easily at the application level within the ORM, but it would be best to do at the db level for consistency (because we have some code not using the ORM and don't want to have to remember to update any raw SQL code).

Can I use nHibernate with a legacy-database with no referential-integrity?

If I have a legacy database with no referential-integrity or keys and it uses stored procedures for all external access is there any point in using nHibernate to persist entities (object-graphs)?
Plus, the SP's not only contain CRUD operations but business logic as well...
I'm starting to think sticking with a custom ado.net DAL would be easier :(
Cheers
Ollie
You most likely CAN. But you probably shouldn't :-)
Hibernate does not care about referential integrity per se; while it obviously needs to have some sort of link between associated tables, it does not matter whether actual FK constraint exists. For example, if Product is mapped as many-to-one to Vendor, PRODUCTS table should have some sort of VENDOR_ID in it but it doesn't have to be a FK.
Depending on your SP signatures, you may or may not be able to use them as custom CRUD in your mappings; if SPs indeed have business logic in them that is applied during all CRUD operations, that may be your first potential problem.
Finally, if your SPs are indeed used for ALL CRUD operations (including all possible queries) it's probably just not worth it to try and introduce Hibernate to the mix - you'll gain pretty much nothing and you'll have a yet another layer to deal with.
okay, an example of the problem is this:
A SP uses a sql statement similar to the following to select the next Id to be inserted into the 'Id' column of a table (this column is just an int column but NOT an identity column),
statement: 'select #cus_id = max(id) + 1 from customers',
so once the next id is calculated it's inserted into table A with other data, then a row is inserted into table B where there is ref to table A (no foreign key constraint) on another column from table A, then finally a row is inserted into table C using the same ref to table A.
When I mapped this into NH using the fluent NH the map generated a correct 'insert' sql statement for the first table but when the second table was mapped as a 'Reference' an 'update' sql statement was generated, I was expecting to see an 'insert' statement...
Now the fact there is no identity columns, no keys and no referential-integrity means to me that I can't guarantee relationship are one-to-one, one-to-many etc...
If this is true, how can NH (fluent) configured either...
Cheers
Ollie