I'm new to Hibernate and I encountered a query today:
select new SomeClassDTO(r.id, r.name, r.description, u.id) from ClassA as u
inner join u.data as r where u.email !=?1 and r.name not like '%Blah%
Can you please explain how this query works?
This query takes several fields from a ClassA entity with it's associated data Entity(s) and passes those field values into the constructor for class SomeClassDTO.
As the name of the created object implies, this is a way to take data from multiple associated database-mapped Entities, and construct a Data Transfer Object (DTO) to pass to your presentation layer.
You are essentially creating a 'view' of your database Entities and constructing new objects to hold the records of the result set of that view.
Related
I don't know whether I should be drawing parallels, but unfortunately, that's the only way I can express my issue.
In SQL, suppose we have two tables:
Employee with columns Employee ID, Employee Name, Dept. ID
Deptartment with columns Dept. ID, Dept Name
The Dept ID. in the Employee table is a foreign key with that in the Department table.
Now suppose I want to fetch the following columns:
Employee ID, Employee Name, Department Name
using a SQL such as:
SELECT A.EMPLOYEE_ID, A.EMPLOYEE_NAME, B.DEPT_NAME
FROM EMPLOYEE A, DEPARTMENT B
WHERE A.DEPT_ID = B.DEPT_ID
How would one do this using Core Data in Swift? I guess I'm getting confused by only seeing references to
NSFetchRequest(entityName: entityName)
where the entityName refers to a single entity (table in relational DB lingo)
I'd really appreciate any pointers or examples that can help me clear my doubts.
Thanks
It is certainly possible to create a fetch request that is equivalent to your SQL query. More complex queries can be difficult if not impossible to achieve with a single fetch request. But I recommend trying NOT to draw parallels between CoreData and SQL, at least until you have got to grips with how it works.
To take your example, in the CoreData view of the world, Employee would be an entity with a relationship to another entity, Department. A fetch request based on the Employee entity will return an array of Employee objects, and (assuming you create subclasses of NSManagedObject for each entity) you can access the attributes with simple dot notation:
let employeeName = myEmployeeObject.employeeName
But you can use the same notation to traverse relationships equally easily:
let departmentName = myEmployeeObject.department.departmentName
You don't need to worry about joins, etc; CoreData handles that for you.
Now, suppose you try to do it "the SQL way". You can construct a fetch request based on the Employee entity, but specify "properties to fetch" which likewise traverse the relationship:
let fetch = NSFetchRequest(entity:"Employee")
fetch.propertiesToFetch = ["employeeID", "employeeName", "department.departmentName"]
For this to work, you would need to specify the "resultType" for the fetch request to be DictionaryResultType:
fetch.resultType = .DictionaryResultType
The results from this query would be an array of dictionaries containing the relevant keys and values. But the link with the underlying objects is lost. If you subsequently want to access any details from the relevant Department (or even the Employee), you would have to run a new fetch to get the object itself.
Ok, lets say you have two tables: Order and OrderLine and for some reason they do not have a foreign key relationship in the database (it's an example, live with it). Now, you want to join these two tables using Entity Framework and you cook up something like this:
using (var model = new Model())
{
var orders = from order in model.Order
join orderline in model.OrderLine on order.Id equals orderline.OrderId into orderlines
from ol in orderlines.DefaultIfEmpty()
select new {order = order, orderlines = orderlines};
}
Now, the above will produce orders and orderlines, left-joined and all, but it has numerous issues:
It's plain ugly
It returns an anonymous type
It returns multiple instances of the same order and I you have to do Distinct() on the client side because orders.Distinct() fails.
What I am looking for is a solution which is:
Pretty
Returns a statically well-known type instead of the anonymous type (I tried to project the query result, but I got into problems with the OrderLines)
Runs Distinct on the server side
Anyone?
Even if the database tables do not have a foreign key relationship setup, you can configure Entity Framework as if they do.
Add an OrderDetails navigation property to your Order class and then just query Orders.
so the story is very simple.
I have one table called Products and another Called categories. In addition, i have another table called ProductCategories that hold the relationship of catetories to their corresponding products (i.e, the table has two columns, ProductId, ColumnId).
For some reason, after adding all those table to my entity model, i don't have "Access" to it, hence i can do myentityModel.ProductCategories, so i could relational items between those two tables.
And yes, the ProductCategores table is added as "Association" to the entity model. i don't really understand that.
EDIT:
I do see that as part of creating new "Product" i can pass EntityCollection of "Category". So i do query from my entity model for a list of the matching categories that the user selected (on the webpage). so for example, i get (after query the model), an Objectset of "Category". However, i encountered two issues:
the 'AddObject' accept only EntityCollection, hence i need to re-create a set and then add all the objects from the ObjectSet to the entityCollection, in this process i need to detach it from the previous model and add it to the new collection. if not, i get an exception.
when i do the SaveChanges, i see that i get an exception that it was actually trying to Create new Category rather than adding new ProductCategory. again, am i missing something here?
Thanks.
This sounds like a Many-to-Many relationship. In your entity model, you don't need to declare the join table as a separate entity. Instead, you configure the relationship between the Products and the Categories as a Many-to-Many and add metadata about the join table. In Hibernate, you would have:
#ManyToMany(targetEntity=Categories.class, cascade={CascadeType.ALL}, fetch = FetchType.LAZY)
#JoinTable(name="tb_products_categories",
joinColumns=#JoinColumn(name="category_id"),
inverseJoinColumns=#JoinColumn(name="product_id")
)
#IndexColumn(name="join_id")
public List<Categories> getCategories() {
return categories;
}
When you query, the ORM layer takes care of determining SQL and traversing table joins.
I have an entity that has a relationship with another entity. I am able to search on columns that are in the main entity, and include columns from the relationship entity. But I need to be able to filter the list (search) on columns that are not in the relationship entity.
for example
the Invoice Entity contains a customerId property, and is related to the Customer Entity which contains the customerName property
I need to be able to search / filter the grid by customerName.
I am new to entity framework, please help.
thanks
Carl
Your relation is 1->1. In these cases I usually return a custom class to the grid that has all the columns I need, including joins with other tables.
So basically what you need is to create a custom linq query with your resultset.
The mais query should follow this example:
var q = from i in ctx.Invoices
join c in ctx.Customers on i.CustomerID equals c.CustomerID
select new{InvoiceID=i.InvoiceID, InvoiceDate=i.Date, CustomerName=c.Name};
Now, assuming we receive a CustomerName variable with the string to filter by c.Name we could do:
if(!string.IsNullOrEmpty(CustomerName))
{
q = q.where(c => c.Name.ToLower().Contains(CustomerName.ToLower()));
}
Notice that I'm performing a ToLower() operation and a Contains, this will beahave as a LIKE ingnoring case sensitivity and searching for the string anywhere in the Customer Name.
At the end you'll return the q.ToList() serialized for the jqGrid...
I am trying to execute a namedquery
#NamedQuery(name="getEmployeeDetails",query="select e.username,e.email,e.image,e.firstname,e.lastname from Employee e where e.empid=?1")
Now when I execute this query in a EJB 3.0 Session Bean what is the object I should return.I tried returning Listits returning a Vector which creates a classcast exception.The employee table contains fields like password and other confidential details which I don't want to fetch.So I am not using select e from Employee e.
I am learning JPA can anyone help.
Below is the sample query which fetches only the required fields, but have to make such constructor for it.
Query : SELECT NEW package_name.Employee(e.username,e.email,e.image,e.firstname,e.lastname) FROM Employee e where e.empid=?1;
It will return Employee entity with selected fields & remaining will have default values.
Inspect the returned type by calling .getClass() on a returned object. I'd guess it's an array.
But this is not really a good way to use JPA. Select the whole entity and then just don't use what you don't need. It's not such a performance hit.