how to persist a String/Object array such that indices and values are stored into separate columns in eclipselink - eclipselink

Am using EclipseLink 2.4.2 with derby database. I have an Entity class which has a String array. Now, i need to map this array to a separate table 'MY_ARGS' such that index must be mapped to one column 'ARRAY_INDEX' and the value (at index) must be mapped to another column 'ARG'.
In hibernate we have 'array' element through which we can do this. Like below :
<array name="args" table="MY_ARGS" cascade="all">
<key column="PARENT_ID"/>
<list-index column="ARRAY_INDEX" />
<element type="string" column="ARG" length="16384" />
</array>
But in eclipse-link am not able to find any such element (am using eclipselink-orm.xml) through which i can achieve this!
Does Eclipselink support such array to table(multi-column) mapping?
I read about #Converter through which we can convert the data type while storing to/retrieving from DB. But it looks like converter deals with single column and cannot store to two columns simultaneously.
Is there a way that i can do this through converter or any such work around? (I prefer not to use collections)
Any quick help is greatly appreciated!
Thanks in Advance!
-Alekhya

Related

NHibernate Composite Index, not a key

Still a n00b in NHibernate :(
I want to add a composite index to the hbm.xml of one of my POCOs, for performance purposes. It does not relate directly to a class, but rather two common values I will be querying against.
I think I need to do a <map></map> entry in the XML, but the XSD is asking for a class name on the composite-key element, and there is no direct relationship, per se... plus it's asking for more information than I think I would need to provide. How do I do this?
<map name="PropertyKeys">
<key>
<column name="StockID" />
<column name="PropertyName" />
</key>
<composite-index class="Something?">
<key-property name="What goes here?" />
</composite-index>
<what else goes here?>
</map>
Have you read this http://ayende.com/blog/4045/nhibernate-mapping-map It explains when you would use a map and further on it explains the composite-index
However without more background info it is not 100% certain that you need a map!

Querying by property of mapped subclass in NHibernate

I'm very new to NHibernate so this may be fairly trivial, but searching is leaving me confused.
I have an AddOnAmount table as follows:
AddOnID | AddOnTypeID | Period | Amount
where AddOnTypeID is a FK. The rows have a unique constraint on AddOnTypeID and Period.
The mapping looks like this:
<id name="Id" column="AddOnId" type="long">
<generator class="native" />
</id>
<many-to-one name="AddOnType" column="AddOnTypeID" class="AddOnTypeStatic" not-null="true" />
<property name="Period" />
etc.
The AddOnTypeStatic class/table just has an Id, which is the numerical value stored on the table, and a descriptive Name.
I'm trying to write a query that will search by AddOnTypeId and Period, so I can validate the existence (or not) of a row before attempting to add a duplicate from my front end, but I'm not sure how to do that as the AddOnAmountStatic class has a subclass whereas the table has just an Id.
So far I've written:
public AddOnAmountStatic FindByAddOnTypeAndPeriod(long addOnType, string period)
{
return FindOne(CreateCriteria()
.Add(Restrictions.Eq("AddOnTypeId", addOnType))
.Add(Restrictions.Eq("Period", period))
.SetCacheable(true));
}
which does not work, as AddOnTypeId isn't a property of AddOnAmountStatic. Not sure how to access the property of the subclass in this context.
My mapping works, as I've been using it so far with no problems.
Solved my problem - it was simple but thought I'd add the solution here in case it helps anyone else.
I'd been thinking of constructing the query from the table's perspective (i.e., with the AddOnTypeID), whereas what I should have done is look at it from the entity's perspective. In other words, I just needed to pass in an AddOnTypeStatic object.
What I did was take my AddOnTypeID parameter, check it exists through NHibernate (returning either an AddOnTypeStatic object or null) then passed that through to the original query. Final query is simply
return FindOne(CreateCriteria()
.Add(Restrictions.Eq("AddOnType", addOnType))
.(Restrictions.Eq("Period", period))
.SetCacheable(true));
Hope this helps another newbie!

"Invalid Index n for this SqlParameterCollection with Count=n" OR "foreign key cannot be null"

I have been successfully using NHibernate for quite some time now and
have been able to solve a lot of pitfalls with an application that I
developed with it and that is running in production. The recent hurdle
really has me scratching my head, though.
Recently I had to expand the class library with some new classes that
are nested as children to some already existing classes. I just copied
the same model for aggregate mapping that I already was successfully
using, but this time it does not work.
Now when I use the following in the parent mapping file:
<bag name="SeaInfoItems" table="EDIImport_SeaInfo" lazy="false" cascade="save-update">
<key column="EDI_FK_OWNERID"/>
<one-to-many class="FargoGate.AppLib.EdiImportSeaInfo, FargoGate.AppLib"/>
</bag>
I can choose to, in the child class, either use:
<property name="EDI_FK_OWNERID" column="EDI_FK_OWNERID" />
...which gives me the infamous "Invalid Index n for this
SqlParameterCollection with Count=n" error.
OR I try with this solution I found after some Googling:
<property name="EDI_FK_OWNERID" column="EDI_FK_OWNERID" insert="false" update="false" />
...which gives me a "Cannot insert the value NULL into column
'EDI_FK_OWNERID'... column does not allow nulls." error.
So basically I have to choose between pest and cholera.
What I don't get is that it works flawlessly for the already existing
aggregate classes, and I really cannot spot the difference. The only
thing is that this foreign key (EDI_FK_OWNERID) could refer to two
different parent tables. Bad database design, I know, but I didn't
design it, and it is my task to develop up to it for better or worse. I cannot change the database design.
The other difference is that I totally removed the foreign key reference from the already existing child classes (the mappings as well as the class members). I tried to emulate that of course, but of no avail.
Also I discovered that one of the new classes (which is quite small) also works fine. But I cannot see what the difference is here either. I am stumped!
Anyone has a clue?
Aaargh! I was put so much on a wrong leg with this infamous “Invalid Index n for this SqlParameterCollection with Count=n” error that I overlooked the obvious: A duplicate mapping of a field for ONE of the classes.
In that particular mapping I left this error, where the primary key is also defined as a property:
<id name="ID" column="ID">
<generator class="guid" />
</id>
<property name="ID" column="ID" />
Now that was a waste of time trying to debug that!

NHibernate - Select query in Formula attribute of Property element is not working

I am new to NHibernate.
I am using following property elements in my hbm file...
<property name="CountryId" length="4" />
<property name="CountryForCustomer"
formula="(SELECT *
FROM SystemCountry
WHERE SystemCountry.CountryId = CountryId)" />
Here I am trying to get Country details from the CountryId that I am having in an other table.
Property "CountryForCustomer" is of custom type "SystemCountry".
But this query in formula is not working.. So someone please help me solving this issue.
Thanks in Advance....
Should it not be
SELECT SystemCountry.Country FROM SystemCountry WHERE...
as the * would return multiple columns from the query
edit If you want to return the whole object back then the property element is not your friend here. What you want to do is look at the many-to-one element, note that this is just one way to do this.
<many-to-one name="CmsTemplate" column="TemplateId" ..
e.g. here or here
the Formula mapping does not map its value from the database ,it maps its value from the dataset which is loaded in the session

Map a property to the latest entry in NHibernate

Let's say my domain looks like this:
I have an object, Vehicle, that has an OdometerReading property.
An OdometerReading has the Miles & Date (when it was read).
I need to keep a history of all OdometerReadings for the Vehicle in the database, but don't want the entire odometer history to belong to the Vehicle object. What I would like is for the OdometerReading property map to the most recent OdometerReading entry out of the database.
I thought about mapping the whole collection of OdometerReadings to the Vehicle, and having a dynamic property called CurrentOdometerReading that would order them and return the latest one, but I don't need the whole collection under the Vehicle in my domain, and it seems like I would be getting more data out of the database than I need.
Is that possible with NHibernate? How would I map such a thing?
There are a few ways of doing this depending on what you want your domain model to look like. My preferred choice is to use a custom collection type, for example IOdometerReadingCollection, which you can add extra methods to. In this case it might be something like:
public interface IOdometerReadingCollection : IList<OdometerReading>
{
OdometerReading Latest { get; }
}
This way you can do:
OdometerReading reading = vehicle.OdometerReadings.Latest;
which I prefer to:
OdometerReading reading = vehicle.LatestOdometerReading;
There's lots of documentation about custom collections, which you can find with a simple google search.
If this approach isn't for you there are other options. You may be able to use a property with a formula (I'm not sure if that works with complex types?), or a regular NHibernate association where you'd have the key of the latest OdometerReading on your Vehicle mapping. As you also mentioned you could just load all the OdometerReadings, which depending on your use case might actually be fine.
I hope this helps, or at least points you in the right direction.
There is a "where" clause that you can put in your collection mapping. Check the reference documentation.
I would map the OdometerReading property as a component, then use a named query to ensure it's populated with the latest reading out of the database. (In this example, you'd have a sql-query with a name of "vehicle" that does the SQL to load the Vehicle columns along with the latest Odometer reading)
<class name="Vehicle">
<property name="Type" not-null="true"/>
<component name="OdometerReading">
<property name="Miles" />
<property name="Date" />
</component>
<loader query-ref="vehicle"/>
</class>