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

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

Related

Sitefinity - Safely delete orphaned dynamic content records

I've been adding records to a dynamic module via the API and in the process during my experimentation I added a bunch of records that weren't associated correctly with any valid parent record.
I've checked and so far I can see that Sitefinity stores data about these records in a number of tables:
mydynamiccontenttype_table
sf_dynamic_content
sf_dynmc_cntnt_sf_lnguage_data
sf_dynmc_cntent_sf_permissions
I would like to clean up the database by deleting these records but I want to make sure I don't create more problems in the process.
Anyone know if there are more references to these dynamic content type records or a process to safely delete them?
There are probably other tables, so your safest option would be to delete the items using the Sitefinity API.
Just get the masterId of the item and use a code like this:
public static void DeleteDataItemOfType(this DynamicModuleManager manager, string type, Guid Id)
{
Type resolvedType = TypeResolutionService.ResolveType(type);
using (var region = new ElevatedModeRegion(manager))
{
manager.DeleteDataItem(resolvedType, Id);
manager.SaveChanges();
}
}

Linq where a record contains 2 matched fields

I’m working with an existing database with a design I’m not in control of, I’m using EF4, and querying using LINQ. I work in VB.Net but would be quite happy to translate a c# solution.
I would like to pull records from a table where two of the fields match a pair of items from a list.
So i have a list of
Public Class RequestInfo
Public Property INSP_ROUTINE_NM As String
Public Property FEATURE_ID As String
End Class
And I would like to query a table and pull any records where both INSP_ROUTINE_NM and FEATURE_ID match one of the Request Info items.
I can use contains easy enough on either of the fields
Dim Features = (From F In MLDb.TBL_FeatureInfoSet _
Where (C_Request.Select(Function(x) x.INSP_ROUTINE_NM)).Contains(F.INSP_ROUTINE_NM) Select F.FEATURE_ID, F.FEATURE_RUN_NO, F.INSP_ROUTINE_NM).ToList
I could use two contains calls but that would pull any record where both records match somewhere in the list not necessarily any one pair from the request.
You can try this:
C#
var Features= (from f in MLDb.TBL_FeatureInfoSet
let q = C_Request.Select(x=>x.INSP_ROUTINE_NM)
where q.Contains(f.INSP_ROUTINE_NM) || q.Contains(f.INSP_ROUTINE_NM)
// where q.Contains(f.INSP_ROUTINE_NM) && q.Contains(f.INSP_ROUTINE_NM)
select new {f.FEATURE_ID, f.FEATURE_RUN_NO}).ToList();

How to map a myBatis result to multiple objects?

Is it possible in myBatis 3 to map a single result to multiple objects, ensuring that the objects all reference the same instance? Is there an example of this I could reference?
Updated to add more detail:
For instance, let's say I store information regarding Contacts for my application in my DB. I want to know if it's possible to use myBatis to map the same instance of a contact to, say, a Listing class, which holds a Contact:
public class Listing {
private Contact myContact;
//getters & setters...
}
as well as to a ContactsHolder class, which also holds a Contact:
public class ContactsHolder {
private Contact aContact
//getters & setters...
}
I need the object that is mapped by myBatis to both the Listing and ContactsHolder classes to be the same instance. Is this possible?
No, MyBatis isn't able to do that with standard result mapping. (at least to my knowledge). You could select the "Contact" object, then build a Listing and ContactsHolder manually with both of them referencing the Contact.
Or implement a custom ResultSetHandler.
It's kind of a peculiar request, I'm not sure why you want the same instances shared across two objects like that. That's probably why no feature like this exists in MyBatis 3.
This can be done with standard result mapping if you use select to fetch the associated contact and both objects are fetched in the same session.
Modify result maps for Listing and ContactsHolder:
<resultMap type="Listing" id="listingMap">
<association property="myContact" column="contact_id" javaType="Contact" select="selectContact"/>
</resultMap>
<resultMap type="ContactsHolder" id="contactsHolderMap">
<association property="aContact" column="contact_id" javaType="Contact" select="selectContact"/>
</resultMap>
Now create a query selectContact:
<select id='selectContact' resultType='Contact'>
SELECT * from contact where id = #{id}
</select>
Now if you create some select that uses both listingMap and contactsHolderMap to map Listing and ContactsHolder records that reference the same contact they will both query for the contact using the same id.
Mybatis uses local cache for all objects read in a session so during fetching of the second associated contact the cache will be hit and the same object will be reused.
Even if you do two queries manually to get Listing and ContactsHolder in the same transaction the same Contact will be used in both returned objects.

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 Criteria against an <ANY> Mapping

I have a Project model that has a property of type IProjectWorker, this could either be a single User or a Team. In Castle ActiveRecord it's defined like this:
[Any(typeof(int), MetaType = typeof(string), TypeColumn = "WorkerType", IdColumn = "WorkerID", Cascade = CascadeEnum.None)]
[Any.MetaValue("USER", typeof(User))]
[Any.MetaValue("TEAM", typeof(Team))]
public IProjectWorker Worker { get; set; }
Now I need to be able to search for projects where the worker's name contains some text. My initial reaction was something like this:
query
.CreateAlias("Worker", "Worker")
.Add(Restrictions.InsensitiveLike("Worker.WorkerName", SearchText, MatchMode.Anywhere));
But this gives me an error-- "any types do not have a unique referenced persister". This makes sense, it doesn't know how to handle joining to the two different tables for the search.
Can I make two different aliases for each table and do a Restrictions.Or() across them? I tried it, but couldn't quite get it right. Or is there some other way to do this using criteria that I'm missing? Or am I going to have to use HQL instead?