Using both basic AND association mapping for one field with Doctrine? - doctrine

I have a Variable object which may belong to a group
I'm mapping the Variable field containing the FK to the Group's id and his relation association in my domain object. (using XMl).
In other words, my domain object has both a (string) field with the id and a "relation" field with the object.
The intended goal here is to retrieve a ready Group object when querying, while simply setting an id when writing
So when I create/update a Variable, I set the ID (not the relation Object).
My issue is : the value is (always) properly saved when I UPDATE, but (always) lost on INSERT.
Here's the part of my mapping :
<field name="parentId" type="string" length="36" column="parent" nullable="true"/>
<many-to-one field="parent" target-entity="App\Domain\VariablesGroup\VariablesGroup" fetch="EAGER">
<join-column name="parent" referenced-column-name="id" nullable="true"/>
</many-to-one>
Docs didn't help me much here, since those 2 mappings are described separetely, and might not be designed to be mixed this way.
--
But I'd prefer to avoid querying the Group from DB and populate the Object field when not necessary.
Since I didn't find how Doctrine handles this under the hood, I guess it might not be something supported :(
Technical precisions about this mappings-interraction (or should I say conflict ?) would be welcomed.

Well, some more testing, using inconsistent data entries in my entity seem to clearly demonstrate that such usage isn't intended.
Whild my code wouldn't allow this, if I do save my entity with groupId = 1 and Group = (group Object with ID 2), I get an alternance of values for the saved value in the "parent" column of my database.
I guess this is due to Doctrine skipping the "useless" update, and proceeding to the one which effectively changes the data value.
Since both values are different, the skipped update alternantes.
If my assumptions are right, Doctrine would better pop an error in such a mapping case. (as it does if you map one column to 2 fields).
Maybe I'll file a suggestion/issue, if this seem relevant.

Related

Hibernate shows different ID than DB

I have three database views that are mapped in Hibernate as entities.
The entities are in a parent-child relationship (1 parent (A), 2 children(B & C)).
One of the children views (B) uses Oracle's dbms_utility.get_hash_value() to calculate its ID.
This is because it does a UNION over several tables that use different ID sequences and thus the IDs from there may not be unique.
I now have the very puzzling effect that a simple entityManager.find(B.class, id) cannot find the appropriate row.
When I look at the children through a loaded parent (A) entity, I can see that the ID shown in B is completely different from the one in the database. If I use this ID with entityManager.find(B.class, hibernateId), Hibernate finds the appropriate entity.
The database, on the other hand, only returns a value when using the ID shown in the ID column there (and not with the ID Hibernate shows).
Child entity C does not use the hash function and does not show this peculiar behaviour - which means the hash must be responsible.
Does anyone have an idea why?
We found the reason:
Child view B used all of its (content containing) columns as a string concatenation for the hash function.
This included date fields, which were not explicitly formatted when creating the string.
So, when Hibernate selected from the view, it obviously used another format than SQL Developer and thus produced completely different (but consistent) IDs.
Explicitly formatting the used date fields removed the problem.

How do I use Spring Roo for referenced data

I’m new to Spring Roo and looking to build an application. I need to have combo boxes to select values into string fields – a fairly common requirement. The Spring Roo Pizza example shows this using enumerated data types enum constant, but I require the source values to be editable by an admin (ie in a table) so we can change the values in the future. Further, my preference would be to use a single table to contain all these lists for easier maintenance.
I know the SQL I want to generate the list would be something like:
Select listvals FROM listTable WHERE listtype = “status”;
Then, my dropdown box would show something like: Active, Inactive. The user would select one, and the string “Active” would be stored in the target field.
And in a second example, we might use:
Select listvals FROM listTable WHERE listtype = “State”;
The second dropdown box would show something like: Alaska, California, Florida. The user would select one, and the string “Florida” would be stored in the target field.
My CORE question is how does one achieve this sort of function in Roo?
Using the Pizza Shop quick start as a sandbox I have tried defining the target fields such as:
I changed: field reference --fieldName base --type ~.domain.Base to:
field reference --fieldName base --type ~.domain.Base --referencedColumnName name
Which returned this error:
#JoinColumn name is required if specifying a referencedColumnName
The initial problem is that at this point roo has yet to create the row ID columns for the db, so I don’t know the name of the join column on the Base table. But, if I wait until after I run the script with a 1:M join, the column pizza.base will be defined as an integer, and not the string that I want.
So, I ran the vanilla pizza shop roo script and interrogated the vanilla db. (Does roo generate an SQL script for db creation that I could look at?)
As it turns out, roo names the row id column “id” as a BigInt. (I also note that it doesn't seem to make use of the SEQUENCE feature that postgres recommends for primary indices / row Ids.)
So now I run:
field reference --fieldName base --type ~.domain.Base --referencedColumnName name --joinColumnName id
Roo likes this!
Until I perform tests where it throws out a number of undecipherable errors in the Surefire reports.
I note that solving this problem is only step 1 to meeting my overall requrement described above. Step 2 will be to try to inject some sort of filter or where clause into the reference statement. I suspect that this has to do with the --fetch option (Roo support docs (http://docs.spring.io/autorepo/docs/spring-roo/1.2.5.RELEASE/reference/html/command-index.html#command-index-finder-commands - The fetch semantics at a JPA level; no default value)
But, I can’t find an example of this to see if I’m on the right track or to model my ‘fetch semantics’ – whatever those are.
Another possibility might be to use field list to define a class containing my list of dropdown values. This has a similar modifier --fetch, but again I can’t find any examples.
I’d really appreciate some help in answering my CORE question above.
THANKS!
Fetch parameter indicates whether the association should be lazily loaded or must be eagerly fetched (https://docs.oracle.com/javaee/6/api/javax/persistence/ManyToOne.html#fetch()).
Maybe the error of tests can be because you try to find, create, delete or update elements with related elements that not exists. Check this first of all.
You can see an example of application created with gvNIX (distribution of Spring Roo) that contains relationships between some entities on https://github.com/DISID/gvnix-samples/blob/master/quickstart-app/quickstart.roo

EF5: Unused and unknown column causes problems

Ok, so I have 2 entities: Course and Industry
The industry entity is just a reference table which lists all available Industries that can be tagged to a course, to categorizing them. I put in a many to zero or one relationship (a course can choose to have an industry or not, while an industry can be tagged with many courses).
I know I've played around with the diagrams a bit, adding and removing associations in the past.
Now here is the odd part: The column mappings for Course has 2 similar columns, IndustryId and Industry_Id
I suspect it's from a past association, but thought EF would have taken care of that.
Here is the problem:
In my view that creates the course, the IndustryId is the property which needs to be populated. When I create new courses, I see the IndustryId in the database populated.
However, when I access Industry's properties through Course (Course.Industry.Description) nothing is populated. It can't seem to get the Industry entity.
I see the IndustryId populated in the db, so I tried to populate the Industry_Id column. That fixed it.
Weird enough, the property declared in the model is IndustryId, so that column is populated in the db. But when I try to get Industry entities through Course, it needs the Industry_Id, which I don't quite know where it is from.
Anyone have any ideas?
It sounds like in your updating from the database, you changed the column name on your tables from Industry_Id to IndustryId. The next time you updated from the database, EF5 (which can't determine that this is the same column, as it matches on names) dropped the mapping for Industry_Id, and added a new column called IndustryId.
However, you had already created the foreign-key mapping in your EDMX file based on the Industry_Id column - which is why you get the issue around needing it when loading related records.
In general, when using Database-First, whenever you rename a column in the database, you need to update your EF5 model and update / correct any such discrepancies.

EAV - Get value using Linq to entities

In a data model like this (http://alanstorm.com/2009/img/magento-book/eav.png) I want to get the value from an EAV_Attribute using Linq to SQL.
Assuming that an EAV_Attribute only exists in one inherited table (varchar, decimal, int, etc.) how can I get it in a linq query?
I know that I can use the Inheritance for this, but I want to execute it in the SQL Database side...
Is it possible to do a kind of Coalesce in Linq, considering that the elements have different types?
EAV and linq is not a happy marriage. I think your best shot is to create an unmapped property in eav_attribute that resolves the value (as object) from it's typed attribute child. With entity framework, you won't be able to use this property in an expression (i.e. not in a Where or Select), You must convert to IEnumerable first to access it. (Linq-to-sql may allow it because it can switch to linq-to-objects below the hood).
Another option is to create a calculated column of type sql_variant that does the same, but now in t-sql code. But... EF does not suport sql_variant. You've got to use some trickery to read it.
That's the reading part.
For setting/modifying/deleting values I don't see any shortcuts. You just have to handle the objects as any object graph with parents and children. In sql server you can't use cascaded delete because it can only be defined for one foreign key. (This may tackle that, but I never tried).
So, not really good news, I'm afraid. Maybe good to know that in one project I also work with a database that has an inevitable EAV part. We do it with EF too, but it's not without friction.
First of all, I recommend using TPH and not TPT for EAV tables. (One table with multiple nullable value columns (one per type) + discriminator vs. one table per type.)
Either way, if you modelled the value entity as an abstract class (containing the two IDs) with an inheriting entity per value data type that adds the value property, then your LINQ should look like this:
var valueEntity = context.ProductAttributes.Where(pa =>
pa.ProductId == selectedProductId
&& pa.AttributeTypeId == selectedAttributeTypeId)
.SingleOrDefault() as ProductAttributeOfDouble;
if valueEntity != null
return valueEntity.Value;
return null;
Where the entity types are: Product, AttributeType, ProductAttribute, ProductAttributeOfDouble, ... ProductAttributeOfString.

LINQ to Entities - How best to obtain the IDENTITY value after calling SaveChanges()

There have been numerous questions posed on this site relating to the retrieval of the IDENTITY after an insert is performed. The way we have been getting the identity is to make the call below, immediately after calling SaveChanges();
context.MyClass.OrderByDescending(c => c.Id).FirstOrDefault();
This seems to work consistently may be completely adequate; however, it has the appearence of opening up a potential for error, should another record be added in between the calls. So the first question is, given that EF performs withing a transacional context, is this method sound?
Secondly, the answer provided to the following question suggests there may be a better way.
Linq to SQL - How to find the the value of the IDENTITY column after InsertOnSubmit()
In that answer, after calling SubmitChanges(), the following call (where "tst" represents the user's class) retrieves the value.
Response.Write("id:" + tst.id.ToString)
This appears to work exactly the same way in LINQ to Entities, where after the call to save changes the instance of the class now includes the id.
context.MyClass.Add(myClass);
context.SaveChanges();
int myNewIdentity = myClass.Id;
Since we are asking for the the actual ID of the class instance (actual record) it would appear to be failsafe. And, it seems logical that the designers of EF should make such basic functionality available. Can anyone confirm that this is proper way to get the identity or at least a best practice?
Yes, LINQ-to-Entities (and LINQ-to-SQL for that matter) will set the generated identity column back in the entity for you after SaveChanges is called. It will also do so for any foreign keys that couldn't be set ahead of time (for instance, a new parent row + a new child row are saved together, and after SaveChanges you'll have the right value in the child row's FK value).
Your particular concern is documented in the 'Working with Entity Keys' page:
http://msdn.microsoft.com/en-us/library/dd283139.aspx
The particular section is 'Entity Keys and Added Objects' and the particular steps are:
4 - If the INSERT operation succeeds, server-generated values are written back to the ObjectStateEntry.
5 - The ObjectStateEntry updates the object with the server-generated value.

Resources