Could not find a setter for property in class - nhibernate

I'm trying to create Criteria as follow:
var criteria - session.CreateSQLQuery("select * from myTable where ID in (select id from tableB) AND ANOTHERID IN(select id from tableC)");
criteria.SetResultTransformer(Transformers.AliasToBean(typeof(myClass))).List<MyClass>().ToList()
And got the following exception:
Could not find a setter for property 'NAME' in class 'MYCLASS'
hbm property:
<property name="Name" type="string" column="NAME" not-null="true" update="true" insert="true"/>
.cs:
private string name;
public virtual string Name
{
get {return this.name;}
set { this.name=value;}
}
What I'm missing here?

Versions of NHibernate prior 5.0 had a bug where properties were matched case sensitively. In the 5.0+ this query would work.
AliasToBeanResultTransformer (Transformer.AliasToBean(...)) is intended to be used with "projections" and therefore does not use mappings to do the binding from columns to the class.
If you want to return an entity and want to leverage the mapping, you'll need to call AddEntity(...) on your query, like this:
var query = session.CreateSQLQuery("select * from myTable where ID in (select id from tableB) AND ANOTHERID IN(select id from tableC)");
query.AddEntity(typeof(myClass)).List<MyClass>();

Related

hibernate bug: How to keep Hibernate sql where condition order obey the declared order?

I have a class Student:
#Entity
#Table(name="student")
public class Student{
#EmbeddedId
private Id id;
//other property omit
#Embeddable
public static class Id implements Serializable{
#Column(name="last_name")
private String lastName;
#Column(name="first_name")
private String firstName;
}
}
I used hibernate to find a student by id, but I found that the generated sql where clause is what I don't expect. I want to generate the sql like select * from student where last_name = ? and first_name = ?, but the generated sql looks like select * from student where first_name = ? last_name = ?.
I want the generated sql where clause expression order to obey the proper order. Does anyone know how to generate such sql when I query a entity by composite id?

Eclipelink #ElementCollection remove all on merge

I have this mapping:
#Entity
#Table(name="CUSTOMER")
class Customer {
#Id
#Column(name="CUSTOMER_ID")
Long id;
...
#ElementCollection
#CollectionTable(name="CUSTOMER_ADDRESS", joinColumns=#JoinColumn(name="CUSTOMER_ID"))
List<CustomerAddress> addresses;
}
#Embeddable
class CustomerAddress {
String street;
String zip;
String ...
String ...
...
}
I have two saved addresses for customer ID : 1. If i update this customer, having a single address on, Eclipselink tries deletes the missing address row using all CustomerAddress fields on DELETE where statement:
DELETE FROM CUSTOMER_ADDRESS WHERE STREET = ?, ..., ZIP = ?, ..., CUSTOMER_ID = ?
The issue is i may have accents and other data that prevents the WHERE statement to match the row using all fields. Is there anyway to force Eclipselink to delete all user addresses and insert again?
DELETE FROM CUSTOMER_ADDRES WHERE CUSTOMER_ID = ?
INSERT ALL FROM COLLECTION
I could not find a way to accomplish what i wanted. It seems Hibernate has the behavior i expect.
Changed ElementCollection to OneToMany and changed the model to have an ID under CustomerAddress.

Insert records into embedded field of OrientDB class from select

I am evaluating OrientDB database.
I have two document classes imported from a relational database.
class Order with properties (ID: integer, OrderItems: EmbeddedList of OrderItem)
and
class OrderItem with properties (ID: integer, OrderID: integer, PropA: string)
Both classes are filled with data from the database (except field Order.OrderItems).
Now I would like to insert data from class OrderItem into class Order based on OrderID.
I have tried SQL like
update Order set OrderItems = (select from OrderItem where OrderID = Order.ID)
without success, with error like
The field 'Order.OrderItems' has been declared as EMBEDDEDLIST but the value is document with the valid RecordId ...
I do understand that embedded record should not have RecordId so I have tried
update Order set OrderItems = (select PropA from OrderItem where OrderID = Order.ID)
without success, with error like
The field 'Order.OrderItems' has been declared as EMBEDDEDLIST with linked class 'OrderItem' but the record has no class ...
I have also tried
update Order
set OrderItems = (select #class, PropA from OrderItem where OrderID = Order.ID)
without success.
Is there any other way (OrientDB 2.1.4) ...
Ales
I have found the solution
update Order
set OrderItems = (select $current.exclude('#rid') from OrderItem where $parent.$current.ID = OrderID)

NHibernate How to convert a SQL Query pulling from multiple tables to QueryOver

Hello any NHibernate genius,
Some help/guidance would really be appreciated, I'm a bit stuck!
I have the following SQL query, which I'd like to convert to QueryOver and I'm not sure weather it can be done? Any help would be greatly appreciated.
SQL:
Insert Into #categoryAndItems
Select GlobalRateCategoryId,null,[Description],null, null,null, GlobalRateCategoryId, 2 From [GlobalRateCategory]
Insert Into #categoryAndItems
Select Id,Name, gr.[Description],un.[Description],null,gr.Formula,gr.GlobalRateCategoryId, 1 From dbo.[GlobalRateCategoryVariable] gr JOIN
dbo.UnitOfMeasure un on gr.UnitOfMeasureId = un.UnitOfMeasureId
JOIN [GlobalRateCategory] grc on grc.GlobalRateCategoryId = gr.GlobalRateCategoryId
Insert Into #categoryAndItems
Select gr.GlobalResourceId,null, gr.[Description], um.[Description], gr.Rate,grr.Formula, c.id, 0 From #categoryAndItems c JOIN
GlobalRateResource grr on c.id = grr.GlobalRateCategoryId JOIN
GlobalResource gr on grr.GlobalResourceId = gr.GlobalResourceId JOIN
UnitOfMeasure um on gr.UnitOfMeasureId = um.UnitOfMeasureId
Select * From #categoryAndItems
order by groupid,id
drop table #categoryAndItems
This cannot be converted to QueryOver, however why not use a Named Query and an XML embedded resource and then project into a DTO?
var results = Session
.GetNamedQuery("GetCategoriesAndItems")
.SetResultTransformer(
new AliasToBeanResultTransformer(typeof(CategoryAndItemsDto)));
return results.List<CategoryAndItemsDto>();
and your DTO:-
public class CategoryAndItemsDto{
public virtual int Id { get; set; }
public virtual string Description{ get; set; }
...
}
This is the embedded XML file....
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2">
<sql-query name="GetCategoriesAndItems">
Insert Into #categoryAndItems
Select ...
Insert Into #categoryAndItems
Select ...
Insert Into #categoryAndItems
Select ...
Select * From #categoryAndItems
order by groupid,id
drop table #categoryAndItems
</sql-query>
</hibernate-mapping>
Make sure the ALL column names returned by your select * match exactly the columns in the DTO (remember it is case sensitive)
And the final bit of the jigsaw to tell fluent you have an XML file:-
sessionFactory = Fluently.Configure()
.Mappings(m =>
{
...
m.HbmMappings.AddFromAssemblyOf<SomeEntityMap>();
})
.BuildSessionFactory();
note: SomeEntityMap is a class in the assembly that contains the XML embedded resource.

NHibernate, how to map a property to a subselect

I currently have a legacy system that uses SPs exclusively for access to the DB. My domain object looks something like this:
public class User : EntityBase
{
public virtual string Name {get;set;}
public virtual string CreatedBy {get;set;}
public virtual DateTime CreatedDate {get;set;}
}
The SP I have that mapped this looked like this:
CREATE PROCEDURE getUser
{
#ID int
}
select
Name
,(SELECT TOP 1 UserName FROM AuditTrail WHERE EntityID = [User].[ID] AND EntityName = 'User' AND AuditActionID = 1 ORDER BY DateStamp) AS CreatedBy
,(SELECT TOP 1 DateStamp FROM AuditTrail WHERE EntityID = [User].[ID] AND EntityName = 'User' AND AuditActionID = 1 ORDER BY DateStamp) AS CreatedDate
FROM [User]
WHERE [User].ID = #ID
So, as you can see, the audit information is separated from the entity itself on the database and the CreatedBy/CreatedOn (and ModifiedBy/ModifiedOn) are stored in a separate table called AuditTrail. the AuditActionID field on the table specifies if it was a create/update.
How can I setup this mapping with NHibernate? I looked into JOIN but it doesn't give me the option to restrict by the additional values (and a join isn't what I want).
Also, if this is possible in Fluent NHibernate, that's a bonus but I'm fine with trying just standard NHibernate mapping config if it gets me there.
UPDATE:
I have found one way to do this, but I'm not a fan. I have setup a SQLQuery that reads the data and maps it back to an object. It works, but I'd love to do this via mapping. Is it even possible since the "values" from the database I'm mapping to is a subselect and not editable?
Solution:
Thanks to the tip from Diego, this was the final solution I found (using Fluent NHibernate, in my ClassMap file):
Map(x => x.CreatedBy).Formula("(SELECT TOP 1 AuditTrail.UserName FROM AuditTrail WHERE AuditTrail.EntityID = [ID] AND AuditTrail.EntityName = 'User' AND AuditTrail.AuditActionID = 1 ORDER BY AuditTrail.DateStamp)");
Map(x => x.CreatedDate).Formula("(SELECT TOP 1 AuditTrail.DateStamp FROM AuditTrail WHERE AuditTrail.EntityID = [ID] AND AuditTrail.EntityName = 'User' AND AuditTrail.AuditActionID = 1 ORDER BY AuditTrail.DateStamp)");
Thanks,
M
You can specify the select clause as the formula for your property.