Knowing child collections count without loading them in NHIbernate - nhibernate

I'm using NHibernate with FluentNH. I've a simple class called PostCategory and it contains a collection of Posts. The PostCategory class contains a property called TotalActivePosts. When I load all the PostCategories I want the no. of active posts for each category to be populated in this property. How I can do that? Any help is greatly appreciated.
Vijaya Anand

The way I did it is by using a computed property. see item no. 5- arbitrary SQL.
you could use something like:
Select Count(*) from Posts where PostCategoryId = Id And IsActive = 1
see also this question

You can either do what sJhonny recommends or use the lazy="extra" attribute on the mapping. That way you can just do Posts.Count to get just the count without loading all of the entities.
See this SO question:
NHibernate Lazy="Extra"

Related

Typo3 Extbase: findByParent

I have an aggregate root object in my extbase Extension called "article" that has several child objects "product" (1:n) assigned to it. How can i findByArticle in the productRepository (so findByParent in child repo). I cannot do it the normal way, getting the child records of my desired parent object, because i need load the product items by ajax call and need to set offset, limit, and different sorting on the request. (This is not possible if i just get the children of article)
thanks for the help
I think you will have to implement an own function in your repository.
An overview of the possibilities can be found here:
http://docs.typo3.org/typo3cms/ExtbaseFluidBook/6-Persistence/3-implement-individual-database-queries.html
If you can't use the normal findByArticleId() you have to use a custom method in your (child) repository:
Something like:
public function findByArticleId($acticleId){
$query = $this->createQuery();
$query->matching(
$query->logicalAnd(
$query->equals('articleId', $acticleId ),
$query->equals('something', 'else')
)
);
$query->setOffset(10);
$query->setLimit(20);
return $query->execute();
}
As you can see you are able to set the limit and the offset or get what ever you want from the repository.
Details can be found here: http://docs.typo3.org/typo3cms/ExtbaseFluidBook/6-Persistence/3-implement-individual-database-queries.html (thanks Max)
If you have a ProductRepository and you want can access the products through anything else than an Article object, then your Article is not an aggregate root.
I would recommend implementing this logic in the Article class. It should hold a reference to an ObjectStorage object containing the products. It should be possible to get a limited number of products with an offset from that storage. You already have the article ID apparently, so you can easily find your article and its products. For performance reasons, the reference from the Article to its products should have the annotation #lazy (TYPO3 8.7) resp. #TYPO3\CMS\Extbase\Annotation\ORM\Lazy (TYPO3 9.5).

Need a concept on fetching data with HQL while three or more tables are in use

A small briefing on what I am trying to do.
I have three tables Content(contentId, body, timeofcreation), ContentAttachmentMap(contentId, attachmentId) and Attachment(attachmentId, resourceLocation).
The reason I adopted to create the mapping table because in future application the attachment can also be shared with different content.
Now I am using HQL to get data. My objectives is as follows:
Get All contents with/without Attachments
I have seen some examples in the internet like you can create an objective specific class (not POJO) and put the attribute name from the select statement within its constructor and the List of that Class object is returned.
For e.g. the HQL will be SELECT new com.mydomain.myclass(cont.id, cont.body) ..... and so on.
In my case I am looking for the following SELECT new com.mydomain.contentClass(cont.id, cont.body, List<Attachment>) FROM ...`. Yes, I want to have the resultList contain contentid, contentbody and List of its Attachments as a single result List item. If there are no attachments then it will return (cont.id, contentbody, null).
Is this possible? Also tell me how to write the SQL statements.
Thanks in advance.
I feel you are using Hibernate in a fundamentally wrong way. You should use Hibernate to view your domain entity, not to use it as exposing the underlying table.
You don't need to have that contentClass special value object for all these. Simply selecting the Content entity serves what you need.
I think it will be easier to have actual example.
In your application, you are not seeing it as "3 tables", you should see it as 2 entities, which is something look like:
#Entity
public class Content {
#Id
Long id;
#Column(...)
String content;
#ManyToMany
#JoinTable(name="ContentAttachmentMap")
List<Attachment> attachments;
}
#Entity
public class Attachment {
#Id
Long id;
#Column(...)
String resourceLocation
}
And, the result you are looking for is simply the result of HQL of something like
from Content where attachments IS EMPTY
I believe you can join fetch too in order to save DB access:
from Content c left join fetch c.attachments where c.attachments IS EMPTY

Fluent nHibernate Selective loading for collections

I was just wondering whether when loading an entity which contains a collection e.g. a Post which may contain 0 -> n Comments if you can define how many comments to return.
At the moment I have this:
public IList<Post> GetNPostsWithNCommentsAndCreator(int numOfPosts, int numOfComments)
{
var posts = Session.Query<Post>().OrderByDescending(x => x.CreationDateTime)
.Take(numOfPosts)
.Fetch(z => z.Comments)
.Fetch(z => z.Creator).ToList();
ReleaseCurrentSession();
return posts;
}
Is there a way of adding a Skip and Take to Comments to allow a kind of paging functionality on the collection so you don't end up loading lots of things you don't need.
I'm aware of lazy loading but I don't really want to use it, I'm using the MVC pattern and want my object to return from the repositories loaded so I can then cache them. I don't really want my views causing select statements.
Is the only real way around this is to not perform a fetch on comments but to perform a separate Select on Comments to Order By Created Date Time and then Select the top 5 for example and then place the returned result into the Post object?
Any thoughts / links on this would be appreciated.
Thanks,
Jon
A fetch simple does a left-outer join on the associated table so that it can hydrate the collection entities with data. What you are looking to do will require a separate query on the specific entities. From there you can use any number of constructs to limit your result set (skip/take, setmaxresults, etc)

NHibernate - define fetching strategy dynamically

Let me explain the problem - hopefully I have defined it well in the title but I want to be sure.
I have a linq query that pulls back a bunch of objects (say Foos). Each Foo holds a reference to a User. Each User holds a reference to a Person:
public class Foo
{
//properties omitted...
public User CreatedBy {get;}
}
public class User
{
//properties omitted...
public Person Person {get;set;}
}
As the object structure would suggest, in the database, Foo relates many-to-one to User, and User relates many-to-one to Person.
When I run the query, I get a single SELECT for the Foos, then a SELECT each for all the Users and People. Clearly I would much prefer a single SELECT with a couple of joins.
I don't necessarily want to specify in my mapping config that Foos ALWAYS eager fetch the User, or that Users ALWAYS eager fetch the Person, but I would like to be able to specify that in this instance.
Is there a way to do that?
Thanks
David
All the NHibernate query methods have ways of specifying eager fetching.
For Criteria, you have SetFetchMode.
For HQL, you have [inner|left] join fetch.
For Linq yo have Expand (2.x contrib) / Fetch (3.x).
For SQL you have AddJoin.
Both Udi Dahan and Ritesh Rao offer example implementations of dynamic fetching strategies for NHibernate, this should give you a good starting point.
Additionally to Diegos nice answer: You can also use batching. This reduces the N+1 problem without much pain:
use batch-size on class level:
<class name="Person" batch-size="20">
...
</class>
use batch-size on collection level:
<map
name="SomeCollection"
batch-size="20">
...
</map>
When ever one of these references is loaded, NHibernate loads 20 at once using a query like this:
select ... from Person where user_fk in (23, 34, 6, 667, 6745, 234 ....)
So it turns N+1 to N / 20 + 1, which is pretty good.

NHibernate: How to get mapped values?

Suppose I have a class Customer that is mapped to the database and everything is a-ok.
Now suppose that I want to retrieve - in my application - the column name that NH knows Customer.FirstName maps to.
How would I do this?
You can access the database field name through NHibernate.Cfg.Configuration:
// cfg is NHibernate.Cfg.Configuration
// You will have to provide the complete namespace for Customer
var persistentClass = cfg.GetClassMapping(typeof(Customer));
var property = persistentClass.GetProperty("FirstName");
var columnIterator = property.ColumnIterator;
The ColumnIterator property returns IEnumerable<NHibernate.Mapping.ISelectable>. In almost all cases properties are mapped to a single column so the column name can be found using property.ColumnInterator.ElementAt(0).Text.
I'm not aware that that's doable.
I believe your best bet would be to use .xml files to do the mapping, package them together with the application and read the contents at runtime. I am not aware of an API which allows you to query hibernate annotations (pardon the Java lingo) at runtime, and that's what you would need.
Update:
Judging by Jamie's solution, NHibernate and Hibernate have different APIs, because the Hibernate org.hibernate.Hibernate class provides no way to access a "configuration" property.