jpql left join condition - eclipselink

I don´t get that simple query working and i don´t now why. i have three entities (just semantics code):
Profile {
#OneToMany
Set<ProfileClubMapping> clubs
String username
...
}
ProfileClubMapping {
#ManyToOne
Profile profile
#ManyToOne
Club club
...
}
Club {
#OneToMany
Set<ProfileClubMapping> profiles
...
}
now i want to select every profile which contains a string in the username and the ProfileClubMapping with a certain Club id. If no ProfileClubMapping exists just return null for the ProfileClubMapping.
I tried something like that:
SELECT p,pcm FROM Profile p LEFT JOIN p.clubs pcm ON pcm.club.id = :clubId WHERE UPPER(p.username) = UPPER(:str)
but this query only returns me the profiles which have an ProfileClubMapping.
Anyone an idea?
EDIT: maybe the sql query helps:
SELECT p.USERNAME, pcm.CLUB_ID FROM PROFILE AS p LEFT JOIN PROFILECLUBMAPPING AS pcm ON pcm.PROFILE_ID = p.ID AND pcm.CLUB_ID = :clubId WHERE p.USERNAME LIKE '%:username%';

Us LEFT OUTER JOIN instead. The behaviour of join is the same as with normal SQL. See for example -> http://www.w3schools.com/sql/sql_join_left.asp

Related

LINQ to Entities returns empty list but it's SQL equivalent returns results

I'm sure this is something fairly common... I'm joining two entities with a mapping table and attempting to load back all relationships.
public IEnumerable<Clinic> ClientClinics(Guid clientId)
{
var clinics =
from c in _appDbContext.Clinics
join ccm in _appDbContext.ClientClinicMappings on c.ClinicId equals ccm.ClinicId
join cli in _appDbContext.Clients on ccm.ClientId equals cli.ClientId
where cli.ClientId == clientId && !c.DeletedAt.HasValue
select c;
return clinics.ToList();
}
I'm getting no results when I should be... I turned on the db logging and here's the generated SQL:
SELECT [c].[ClinicId], [c].[Address], [c].[City], [c].[CreatedAt], [c].[CreatedBy], [c].[DeletedAt], [c].[DeletedBy], [c].[ModifiedAt], [c].[ModifiedBy], [c].[Name], [c].[Phone], [c].[State], [c].[Zip]
FROM [Clinic] AS [c]
INNER JOIN [ClientClinicMapping] AS [ccm] ON [c].[ClinicId] = [ccm].[ClinicId]
INNER JOIN [Client] AS [cli] ON [ccm].[ClientId] = [cli].[ClientId]
WHERE ([cli].[ClientId] = #__clientId_0) AND [c].[DeletedAt] IS NULL
When I paste in my GUID that I'm searching with, I'm able to get results from SQL.
Anyone have any suggestions to where I should be looking or what to be trying?

Eclipselink Inheritance policy causing malformed query

There are three entities namely Employee, Person and Address. There is a parent-child relationship between Person and Employee (Employee IS-A Person).
There is a 1:1 relationship from Person to Address. (A Person is assumed to have one permanent address).
The key properties of Employee class are: 1. employeeId(pk) 2. personId(fk)
The key properties of Person class are: 1. pId(pk) 2. pCode
The key properties of Address class are: 1. addressId(pk) 2. employeeId(fk)
The following are the descriptor code snippets for Person, Employee and Address classes:
public RelationalDescriptor buildPersonDescriptor() {
RelationalDescriptor descriptor = new RelationalDescriptor();
descriptor.setJavaClass(Person.class);
descriptor.addTableName("PERSON");
descriptor.addPrimaryKeyFieldName("PERSON.PID");
// Inheritance properties.
descriptor.getInheritancePolicy().setClassIndicatorFieldName("PERSON.PCODE");
descriptor.getInheritancePolicy().addClassIndicator(Employee.class, "EMP");
// RelationalDescriptor properties.
descriptor.useSoftCacheWeakIdentityMap();
descriptor.setIdentityMapSize(100);
descriptor.useRemoteSoftCacheWeakIdentityMap();
descriptor.setRemoteIdentityMapSize(100);
descriptor.setSequenceNumberFieldName("PERSON.PID");
descriptor.setSequenceNumberName("PERSON_SEQ");
descriptor.setAlias("Person");
// Query manager.
descriptor.getDescriptorQueryManager().checkCacheForDoesExist();
//Named Queries
DirectToFieldMapping productIDMapping = new DirectToFieldMapping();
productIDMapping.setAttributeName("pId");
productIDMapping.setFieldName("PERSON.PID");
descriptor.addMapping(productIDMapping);
DirectToFieldMapping productIDMapping = new DirectToFieldMapping();
productIDMapping.setAttributeName("pCode");
productIDMapping.setFieldName("PERSON.PCODE");
descriptor.addMapping(productIDMapping);
return descriptor;
}
public RelationalDescriptor buildEmployeeDescriptor() {
RelationalDescriptor descriptor = new RelationalDescriptor();
descriptor.setJavaClass(Employee.class);
descriptor.addTableName("EMPLOYEE");
// Inheritance properties.
descriptor.getInheritancePolicy().setParentClass(Person.class);
// RelationalDescriptor properties.
descriptor.setAlias("Employee");
// Query manager.
descriptor.getDescriptorQueryManager().checkCacheForDoesExist();
//Named Queries
// Event manager.
// Mappings.
DirectToFieldMapping employeeIdMapping = new DirectToFieldMapping();
employeeIdMapping.setAttributeName("employeeId");
employeeIdMapping.setFieldName("EMPLOYEE.EID");
descriptor.addMapping(employeeIdMapping);
DirectToFieldMapping personIdMapping = new DirectToFieldMapping();
personIdMapping.setAttributeName("personId");
personIdMapping.setFieldName("EMPLOYEE.PID");
descriptor.addMapping(personIdMapping);
OneToOneMapping addressMapping = new OneToOneMapping();
addressMapping.setAttributeName("address");
addressMapping.setReferenceClass(Address.class);
addressMapping.dontUseIndirection();
addressMapping.addTargetForeignKeyFieldName("ADDRESS.EID", "EMPLOYEE.EID");
descriptor.addMapping(addressMapping);
return descriptor;
}
public RelationalDescriptor buildAddressDescriptor() {
RelationalDescriptor descriptor = new RelationalDescriptor();
descriptor.setJavaClass(com.tropics.application.products.domain.costingandpricing.SellingPriceAddOn.class);
descriptor.addTableName("ADDRESS");
descriptor.addPrimaryKeyFieldName("ADDRESS.AID");
// Descriptor properties.
descriptor.useSoftCacheWeakIdentityMap();
descriptor.setIdentityMapSize(100);
descriptor.useRemoteSoftCacheWeakIdentityMap();
descriptor.setRemoteIdentityMapSize(100);
descriptor.setSequenceNumberFieldName("ADDRESS.AID");
descriptor.setSequenceNumberName("ADDRESS_SEQ");
descriptor.setAlias("address");
// Query manager.
descriptor.getDescriptorQueryManager().checkCacheForDoesExist();
//Mappings
DirectToFieldMapping personIDMapping = new DirectToFieldMapping();
personIDMapping.setAttributeName("employeeId");
personIDMapping.setFieldName("ADDRESS.EID");
descriptor.addMapping(personIDMapping);
DirectToFieldMapping addressIDMapping = new DirectToFieldMapping();
addressIDMapping.setAttributeName("addressId");
addressIDMapping.setFieldName("ADDRESS.AID");
descriptor.addMapping(addressIDMapping);
}
Following is the code snippet for generating the dynamic query:
ExpressionBuilder employee = new ExpressionBuilder();
ReportQuery query = new ReportQuery(Employee.class,employee);
Expression address = employee.getAllowingNull("address");
query.addAttribute("pId");
query.addAttribute("pCode");
query.addAttribute("employeeId");
query.addAttribute("addressId",address.get("addressId"));
query.addNonFetchJoin(employee.leftJoin(address,
address.get("employeeId")));
resultCollection = (Vector) clientSessionHolder.eclipselinkClientSession().executeQuery(query);
On running this program, the query which is generated as per logs:
SELECT t0.PID, t0.PCODE, t1.EID, t2.AID FROM PERSON t0 LEFT OUTER JOIN ADDRESS t2 ON ((t2.EID = t1.EID),EMPLOYEE t1 WHERE ((t1.PID = t0.PID) AND (t0.PCODE = 'EMP'));
The expected query is:
SELECT t0.PID, t0.PCODE, t1.EID, t2.AID FROM PERSON t0,EMPLOYEE t1 LEFT OUTER JOIN ADDRESS t2 ON ((t2.EID = t1.EID) WHERE ((t1.PID = t0.PID) AND (t0.PCODE = 'EMP')));
The table t1 is not correctly applied in the join clause.
Could anyone help me with what's wrong with the expression?
Waiting for a positive reply.
I ran into the same problem. Left join between two not linked entities (person left join address in your case) through another entities (employee).
I used JPQL. These entities could be linked directly by IDs, but eclipselink (2.6.2) added implicit join after the left join. And referred (in left join) to ID from implicit join. It broke the query. I got the exception "ORA-00904: "T3"."ID": invalid identifier".
I solved my problem by removing left join and adding exists and subquery. I did not need to receive entity from left join.
You can try add explicit join on employee before the left join on address. It did not help me. My eclipselink changing join on implicit join. But maybe you are lucky.
Or you can add left join on employee before the left join on address. It helps. But maybe this is not what you need.

Explication Models and queries in django

I have question and problem at the same time, I have two models in deferents, projects like this
PROJECT: TransactionMaster.models => TransactionMaster
class TransactionMaster(models.Model):
user = models.ForeignKey(User, on_delete=CASCADE)
trans_status = models.BooleanField()
trans_name = models.CharField()
PROJECT: TransactionDetails.models => TransactionDetail
from app.transactionMaster.models import TransactionMaster
class TransactionDetail(models.Model):
transaction = models.ForeignKey(TransactionMaster, on_delete=CASCADE)
current_status = models.IntegerField()
transdetail_name = models.CharField()
how Can I do the next sql query
SELECT * FROM User as u inner join TransactionMaster as tm in u.id=tm.user_id inner join TransactionDetail as td in tm=td.transaction_id where tm.trans_status=td.current_status
and
SELECT * FROM TransactionMaster as tm inner join TransactionDetail as td in tm.id=td.transaction_id where tm.trans_status=td.current_status
I try the second query like this:
TransactionDetail.object.filter(TransactionMaster__id=transaction_id, trans_status=TransactionMaster__current_status)
Please help me with this queries, and could you answer me what can I do in models in the different project, please.
thanks for your attention
Angel Rojas
For both queries, it seems that you want to get the TransactionMaster records that have at least one TransactionDetail record with a curent_status that is equal to the trans_status of the TransactionMaster.
In Django, that may translate to:
from django.db.models import F
transaction_masters = TransactionMaster.objects.filter(transactiondetail__current_status=F('trans_status'))
For the first query it looks as though you are interested in the users of the TransactionMaster records? To get the users, just extract them from the filtered transaction_masters.
users = [tm.user for tm in transaction_masters]

spring mvc hibernate performance issues

We are working on a spring mvc project with hibernate.
When we execute the following code:
try {
HibernateTemplate ht = new HibernateTemplate(sf);
List<Route> r = ht.findByNamedParam("select r from Route r inner join r.carPoolers as carPooler where (( r.owner.id = :userid ) or ( carPooler.user.id = :userid )) AND r.id =:routeID", new String[]{"userid", "routeID"} , new Object[]{ u.getId() , id});
if (r.size() == 1) {
return r.get(0);
} else {
return null;
}
} catch (DataAccessException ex) {
LogFactory.getLog(RouteRepository.class).fatal(ex);
return null;
}
this is the result:
SELECT ROUTE0_.ID AS ID4_, ROUTE0_.ARRIVALTIME AS ARRIVALT2_4_,
ROUTE0_.CAR_ID AS CAR13_4_, ROUTE0_.DATE AS DATE4_,
ROUTE0_.DAYOFWEEK AS DAYOFWEEK4_, ROUTE0_.DEPARTURETIME AS
DEPARTUR5_4_, ROUTE0_.ENDDATE AS ENDDATE4_, ROUTE0_.MESSAGEID
AS MESSAGEID4_, ROUTE0_.OPENSEATS AS OPENSEATS4_,
ROUTE0_.OWNER_ID AS OWNER14_4_, ROUTE0_.ROUTECACHE_ID AS
ROUTECACHE11_4_, ROUTE0_.ROUTEOPTIMIZED AS ROUTEOPT9_4_,
ROUTE0_.START_ID AS START12_4_, ROUTE0_.STOP_ID AS STOP10_4_
FROM ROUTE ROUTE0_ INNER JOIN CARPOOLER CARPOOLERS1_ ON
ROUTE0_.ID=CARPOOLERS1_.ROUTEID
WHERE (route0_.owner_id=? or carpoolers1_.user_id=?) and route0_.id=?
SELECT CAR0_.ID AS ID5_3_, CAR0_.BRAND_ID AS BRAND8_5_3_, CAR0_.CARNAME
AS CARNAME5_3_, CAR0_.CARTYPE AS CARTYPE5_3_, CAR0_.IMAGEURL AS
IMAGEURL5_3_, CAR0_.PRICEKM AS PRICEKM5_3_, CAR0_.SEATS AS
SEATS5_3_, CAR0_.USER_ID AS USER7_5_3_, BRAND1_.ID AS ID6_0_,
BRAND1_.BRANDNAME AS BRANDNAME6_0_, USER2_.ID AS ID0_1_,
USER2_.EMAIL AS EMAIL0_1_, USER2_.FACEBOOKID AS FACEBOOKID0_1_,
USER2_.FIRSTNAME AS FIRSTNAME0_1_, USER2_.GENDER AS GENDER0_1_,
USER2_.IMAGEURL AS IMAGEURL0_1_, USER2_.LANGUAGE_ID AS
LANGUAGE12_0_1_, USER2_.LASTNAME AS LASTNAME0_1_,
USER2_.MOBILEPHONE AS MOBILEPH8_0_1_, USER2_.PASSWORD AS
PASSWORD0_1_, USER2_.SMOKER AS SMOKER0_1_, USER2_.TELEPHONE AS
TELEPHONE0_1_, LANGUAGE3_.ID AS ID9_2_, LANGUAGE3_.LANGUAGE AS
LANGUAGE9_2_, LANGUAGE3_.LANGUAGECODE AS LANGUAGE3_9_2_
FROM CAR CAR0_ LEFT OUTER JOIN BRAND BRAND1_ ON
CAR0_.BRAND_ID=BRAND1_.ID LEFT OUTER JOIN USER USER2_ ON
CAR0_.USER_ID=USER2_.ID LEFT OUTER JOIN LANGUAGE LANGUAGE3_ ON
USER2_.LANGUAGE_ID=LANGUAGE3_.ID
WHERE car0_.id=?
SELECT USER0_.ID AS ID0_1_, USER0_.EMAIL AS EMAIL0_1_,
USER0_.FACEBOOKID AS FACEBOOKID0_1_, USER0_.FIRSTNAME AS
FIRSTNAME0_1_, USER0_.GENDER AS GENDER0_1_, USER0_.IMAGEURL AS
IMAGEURL0_1_, USER0_.LANGUAGE_ID AS LANGUAGE12_0_1_,
USER0_.LASTNAME AS LASTNAME0_1_, USER0_.MOBILEPHONE AS
MOBILEPH8_0_1_, USER0_.PASSWORD AS PASSWORD0_1_, USER0_.SMOKER
AS SMOKER0_1_, USER0_.TELEPHONE AS TELEPHONE0_1_, LANGUAGE1_.ID
AS ID9_0_, LANGUAGE1_.LANGUAGE AS LANGUAGE9_0_,
LANGUAGE1_.LANGUAGECODE AS LANGUAGE3_9_0_
FROM USER USER0_ LEFT OUTER JOIN LANGUAGE LANGUAGE1_ ON
USER0_.LANGUAGE_ID=LANGUAGE1_.ID
WHERE user0_.id=?
SELECT ROUTECACHE0_.ID AS ID7_2_, ROUTECACHE0_.AANTALM AS AANTALM7_2_,
ROUTECACHE0_.AANTALMIN AS AANTALMIN7_2_, ROUTECACHE0_.ACTIVE AS
ACTIVE7_2_, ROUTECACHE0_.JSON AS JSON7_2_,
ROUTECACHE0_.LOCATIONS AS LOCATIONS7_2_,
ROUTECACHE0_.LOCATIONSOPTIMIZED AS LOCATION7_7_2_,
ROUTECACHE0_.ROUTEOPTIMIZED AS ROUTEOPT8_7_2_,
ROUTECACHE0_.START_ID AS START10_7_2_, ROUTECACHE0_.STOP_ID AS
STOP9_7_2_, LOCATION1_.ID AS ID2_0_, LOCATION1_.LANG AS
LANG2_0_, LOCATION1_.LAT AS LAT2_0_, LOCATION1_.NUMBER AS
NUMBER2_0_, LOCATION1_.STREET AS STREET2_0_, LOCATION1_.ZIPCODE
AS ZIPCODE2_0_, LOCATION2_.ID AS ID2_1_, LOCATION2_.LANG AS
LANG2_1_, LOCATION2_.LAT AS LAT2_1_, LOCATION2_.NUMBER AS
NUMBER2_1_, LOCATION2_.STREET AS STREET2_1_, LOCATION2_.ZIPCODE
AS ZIPCODE2_1_
FROM ROUTECACHE ROUTECACHE0_ LEFT OUTER JOIN LOCATION LOCATION1_ ON
ROUTECACHE0_.START_ID=LOCATION1_.ID LEFT OUTER JOIN LOCATION
LOCATION2_ ON ROUTECACHE0_.STOP_ID=LOCATION2_.ID
WHERE routecache0_.id=?
SELECT ROUTECACHE0_.ROUTECACHESPUNTENTUSSEN_ID AS ROUTECAC1_1_,
ROUTECACHE0_.ROUTECACHETUSSENPUNTEN_ID AS ROUTECAC2_1_,
LOCATION1_.ID AS ID2_0_, LOCATION1_.LANG AS LANG2_0_,
LOCATION1_.LAT AS LAT2_0_, LOCATION1_.NUMBER AS NUMBER2_0_,
LOCATION1_.STREET AS STREET2_0_, LOCATION1_.ZIPCODE AS
ZIPCODE2_0_
FROM ROUTECACHE_LOCATION_PUNTEN ROUTECACHE0_ LEFT OUTER JOIN LOCATION
LOCATION1_ ON
ROUTECACHE0_.ROUTECACHETUSSENPUNTEN_ID=LOCATION1_.ID
WHERE routecache0_.routecachesPuntenTussen_id=?
SELECT CARPOOLERS0_.ROUTEID AS ROUTEID5_, CARPOOLERS0_.ID AS ID5_,
CARPOOLERS0_.ID AS ID3_4_, CARPOOLERS0_.APPROVED AS
APPROVED3_4_, CARPOOLERS0_.ONETIME AS ONETIME3_4_,
CARPOOLERS0_.ROUTEID AS ROUTEID3_4_, CARPOOLERS0_.START_ID AS
START5_3_4_, CARPOOLERS0_.STOP_ID AS STOP7_3_4_,
CARPOOLERS0_.USER_ID AS USER6_3_4_, LOCATION1_.ID AS ID2_0_,
LOCATION1_.LANG AS LANG2_0_, LOCATION1_.LAT AS LAT2_0_,
LOCATION1_.NUMBER AS NUMBER2_0_, LOCATION1_.STREET AS
STREET2_0_, LOCATION1_.ZIPCODE AS ZIPCODE2_0_, LOCATION2_.ID AS
ID2_1_, LOCATION2_.LANG AS LANG2_1_, LOCATION2_.LAT AS LAT2_1_,
LOCATION2_.NUMBER AS NUMBER2_1_, LOCATION2_.STREET AS
STREET2_1_, LOCATION2_.ZIPCODE AS ZIPCODE2_1_, USER3_.ID AS
ID0_2_, USER3_.EMAIL AS EMAIL0_2_, USER3_.FACEBOOKID AS
FACEBOOKID0_2_, USER3_.FIRSTNAME AS FIRSTNAME0_2_,
USER3_.GENDER AS GENDER0_2_, USER3_.IMAGEURL AS IMAGEURL0_2_,
USER3_.LANGUAGE_ID AS LANGUAGE12_0_2_, USER3_.LASTNAME AS
LASTNAME0_2_, USER3_.MOBILEPHONE AS MOBILEPH8_0_2_,
USER3_.PASSWORD AS PASSWORD0_2_, USER3_.SMOKER AS SMOKER0_2_,
USER3_.TELEPHONE AS TELEPHONE0_2_, LANGUAGE4_.ID AS ID9_3_,
LANGUAGE4_.LANGUAGE AS LANGUAGE9_3_, LANGUAGE4_.LANGUAGECODE AS
LANGUAGE3_9_3_
FROM CARPOOLER CARPOOLERS0_ LEFT OUTER JOIN LOCATION LOCATION1_ ON
CARPOOLERS0_.START_ID=LOCATION1_.ID LEFT OUTER JOIN LOCATION
LOCATION2_ ON CARPOOLERS0_.STOP_ID=LOCATION2_.ID LEFT OUTER
JOIN USER USER3_ ON CARPOOLERS0_.USER_ID=USER3_.ID LEFT OUTER
JOIN LANGUAGE LANGUAGE4_ ON USER3_.LANGUAGE_ID=LANGUAGE4_.ID
WHERE carpoolers0_.RouteId=?
Problem:
This takes minimum 460ms.
We only need the first query for our results.
,
ty in advance
You probably have so many queries because some relationships are eager loaded. Note that by default all OneToOne and ManyToOne relationships are eager loaded. This means that if a route has a car, which has a user, which has a language, etc., Hibernate will load all these referenced entities each time it loads a route.
Make them lazy loaded instead, and tune your queries to fetch only the entities you need.
I guess returned object is passed to some automatic serializer (you use #ResponseBody, yes?) that tries to serialize the whole graph of accessible objects and therefore triggers lazy loading of related objects which you don't need.
If so, you can create a DTO that contains only necessary fields, populate it from the loaded entity and return that DTO instead of entity.
Alternative approach would be to configure serializer to make it serialize only necessary fields, but it can be more complex.
See this for how to get only 1 result: How do you do a limit query in HQL?.
Have you configured indexes on your tables?

NHibernate Left Outer Join Unrelated Entities

I have 2 entities Role & Translation.
Role -> Role_ID, Code
Translation -> Code, Language, Name
The idea is to say for a certain role, that it has English name, French name and so on.
For example:
A Role(1, 'Rol_001') can have the relations: Translation('Rol_001', 'English', '') & Translation('Rol_001', 'French', '').
I would like to express the following SQL query in HQL:
select r.Role_ID, t.Name
from Role r left outer join Translation t
on r.Code = t.Code and t.Language = #lang;
In my mapping files I don't have any relation between the 2 entities but the following HQL query works as if it is inner join
IQuery query = session.CreateQuery("select new Lookup(r.Role, t.Name) from Role r, Translation t where r.Code = r.Code and t.Language = :language");
If I change the HQL to left outer join, I get the Path expected for join exception.
Can you help me with the following:
1- Do I need to change my mapping files?
2- If I can keep the mapping files as is, how write such a query in HQL?
3- How does HQL really works? Why such a simple outer join query is not working? I must be missing something here!
Edit:
Now I am using the following code based on the suggetion to use CreateSQL:
ISQLQuery query = session.CreateSQLQuery("select m.MedicineTypeID, t.Name, m.IsDeleted from MedicineType m left outer join Translation t on m.Code = t.Code and t.Language = :language");
query.SetString("language", language);
IList rawLookup = query.List();
IList medicineTypesLookup = new List(rawLookup.Count);
foreach (object[] lookup in rawLookup)
{
medicineTypesLookup.Add(new Lookup((int)lookup[0], (string)lookup[1], (bool)lookup[2]));
}
return medicineTypesLookup;
This is working however I want to use query.List() to get the result directly instead of converting it myself.
I tried to use query.AddEntity(typeof(Lookup)); but I get the exception NHibernate.MappingException: No persister for: DAL.Domain.Lookup.
The Lookup is just a POCO and doesn't map to any database table. Its mapping file is simply <import class="Lookup" />
Finally I found the answer:ISession session = NHibernateHelper.Session;
ISQLQuery query = session.CreateSQLQuery("select m.MedicineTypeID as ID, t.Name, m.IsDeleted from MedicineType m left outer join Translation t on m.Code = t.Code and t.Language = :language");
query.setString("language", language);
IList lookup = query.SetResultTransformer(Transformers.AliasToBean()).List();
return lookup;
And the lookup is a POCO class with a parameterless constructor and 3 properties ID, Name and IsDeleted.
I would like to thank Kelly and Diego Mijelshon for their hints. Although they don't provide the full answer the but using Session.CreateSqlQuery() was a very useful hint.
So the complete solution is Session.CreateSQLQuery and query.SetResultTransformer
Note: Transformers.AliasToBean() is so java.
Edit: http://docs.jboss.org/hibernate/orm/3.2/api/org/hibernate/impl/SQLQueryImpl.html for correct method of setString()
You must to define the relationship in the mappings or do a subquery