JPA findBy multiple items optionally - spring-data-jpa

I'm looking for a simple solution to an ugly problem. I am using Spring Data JPA and have 7 entities that are all related. I have a need to do a findByEntity1_NameAndEntity2_NameAndEntity3_NameAndEntity4_NameAndEntity5_NameAndEntity6_NameAndEntity7_Name
I need every permutation including and excluding each other those entities. I could build all 128 methods and use a big case statement to select which one to use, but that's horridly ugly. I feel like I'm missing the easy button on this one.

Query By Example method
I think the best option for you is to use the (imo, somewhat infrequently used) QueryByExample feature of Spring Data JPA. On researching this answer, I posted an answer somewhere else that needed the same response. I'd take a look at that to get an idea of how this solves your problem.
You'll first need to the QueryByExampleExecutor to your Repository.
Secondly you'll just need to create your query like so (and hopefully you're using fluent builders for your entities!):
ExampleMatcher matcher = ExampleMatcher.matching().withIgnoreNullValues();
Example<MyObject> exampleQuery = Example.of(new MyObject()
.withEntity1(new Entity1().withName("foo"), matcher);
repository.findAll(exampleQuery);
Would select all of the MyObject elements with Entity1 having name of foo.
ExampleMatcher matcher = ExampleMatcher.matching().withIgnoreNullValues();
Example<MyObject> exampleQuery = Example.of(new MyObject()
.withEntity1(new Entity1().withName("foo"),
.withEntity2(new Entity2().withName("bar"),
.withEntity3(new Entity3().withName("baz"),
.withEntity4(new Entity4().withName("foo"),
.withEntity5(new Entity5().withName("bar"),
.withEntity6(new Entity6().withName("baz"),
.withEntity7(new Entity7().withName("foo")
), matcher);
repository.findAll(exampleQuery);
Would select all of the MyObject elements for Entity1 with name of foo, Entity2, with name of bar, etc.

Related

How to write an extension for the Entity Framework Core

The actual thing that I need is an effective Delete method for the entities. In other words I would like to be able to write
cntx.Orders.Where(item => item.Category == "Custom1").Delete();
and that is supposed to delete all the records from the table Orders where the Category column value is equal to "Custom1". I don't really care if it will do it right away or after calling cntx.SaveChanges(). And, yes, the query is supposed to be efficient, something like
DELETE FROM Orders WHERE Category = "Custom1"
I know about at least 3 extension libraries for the Entity Framework Core which advertise such abilities but non of them work for Android. Now, I'm thinking how difficult it actually is to write a Delete extension method myself. Can anybody help me with an example? Apparently I should be able to add something to the expression tree which will be called by the framework and in my turn I would generate "DELETE FROM Orders" and then "Where(item => item.Category == "Custom1")" would be replaced by the "WHERE Category = "Custom1""
So, apparently everything should start from
public static class QueryExtension {
public static void Delete<T>(IQueryable<T> objThis) {
// The big mystery is what to call here to ensure that "DELETE FROM [TableName]"
// is entered to the right place of the expression tree and then
// we somehow need to execute the complete statement here or delegate it to SaveChanges
}
}
I sort of realize that translation of the expression tree into a SQL statement happens somewhere in the expression visitor. That is most likely wrapped into some kind of statement compiler of the Entity Framework. I have no idea where all those entry points to write an extension like I need.

What and when can "Target" be instead of an Entity and should I check its logical name when working on a single entity type?

I'm a newbie in developing in CRM, so I want to get some things clear. And you first you need to know the reason why you have to do something in order to fully understand it. So lets get to the question.
I know you have to do this when making a plugin:
var context = (IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext));
if (context.InputParameters.Contains("Target") && context.InputParameters.["Target"] is Entity)
{
var entity = (Entity)context.InputParameters["Target"];
if(entity.LogicalName == "myEntity")
{
//Do something with your entity
}
}
Now, in the PluginRegistration Tool, you can set up that your plugin will be fired on the defined Message and which entities (and specific attributes from them) will be affected by it, besides other stuff.
I can see the validations are very useful when manipulating several entities with a single plugin.
Now, let's suppose you only are updating a single entity with your plugin. Why should I check if the entity that's on "Target" is the entity I want to work on, if I already know because I set it up for that entity in particular? What can an Entity be otherwise in that scenario?
Also, in what cases "Target" is NOT an Entity (in the current context)?
Thanks in advance, and sorry if this is a silly question.
See this answer: Is Target always an Entity or can it be EntityReference?
Per the SDK (https://msdn.microsoft.com/en-us/library/gg309673.aspx):
Note that not all requests contain a Target property that is of type
Entity, so you have to look at each request or response. For example,
DeleteRequest has a Target property, but its type is
EntityReference.
The bottom line is that you need to look at the request (all plugin's fire on an OrganizationRequest) of which there are many derived types (https://msdn.microsoft.com/en-us/library/microsoft.xrm.sdk.organizationrequest.aspx) to determine the type for the Target property.
As Nicknow said, the Input Parameters will change depending on the Message being executed.
You can get that information from the MSDN (every request will list the Input Parameters under the Properties section, for instance the CreateRequest) or using the ParameterBrowser.
There's also a really nice alternative to deal with this in a type-safe approach (intellisense included) described in the following blog article: mktange's blog.

JPA EntityManager.detach() still load lazy relations

I got a problem that goes against my understanding of how it supposed to work. I have a Arquillian-test that tests a repository-method with a JPA query.
The test persists an object, and then persists an another object with the first persisted object in a field. Then it calls the repository-method. Next the test detaches (and clear the entitymanager, checks that the object is not contained in the em etc etc). Last the test checks if the related object is there or not (it shouldn't since the query is not supposed to read the relation).
As expected, when looking in the debugger, the related object is null, but when the assert actually uses the getRelatedObject-method, is loads the related object.
Pseudocode to clarify (i hope):
FirstObject f = new FirstObject();
em.persist(f);
SecondObject s = new SecondObject();
s.setFirstObject(f);
em.persist(f);
MyRepo r = new MyRepo();
SecondObject result = r.runQuery(f.getId());
em.detach(result); //result.getFirstObject is null
em.clear();
assertIsNull(result.getFirstObject()); //loads first object and test fails
Is it my understanding that is wrong, should the related object still load? I expected a LazyInit-exception.
If i'm my understanding is wrong, how to verify that a query doesn't populate related object I don't won't?
(yes, using dto-objects instead of the entity is better, I know... we have had that discussion and I was overruled)
The book Pro JPA 2 (Apress, p160) notes
"The behavior of accessing an unloaded attribute when the entity is
detached is not defined. Some vendors might attempt to resolve the
relationship, while others might simply throw an exception or leave
the attribute uninitialized."
I do not have experience of EclipseLink personally and can find anything definitive in the documentation in this area however the following links all suggest that EclipseLink will try and resolve the relationship when you access a lazy association on a detached collection.
Eclipselink Lazy Loading
http://issues.apache.org/jira/browse/OPENJPA-2483
http://blog.ringerc.id.au/2012/06/jpa2-is-very-inflexible-with-eagerlazy.html

EntityFramework 4, DbSet and ObjectContext

few days ago i read tutorial about GenericRepository and Unit Of Work patterns http://www.asp.net/mvc/tutorials/getting-started-with-ef-using-mvc/implementing-the-repository-and-unit-of-work-patterns-in-an-asp-net-mvc-application. I use web forms and i have EntityFramework CTP4 package installed. (I can't using EF 5).
I want to code generic repository for my project but i was stuck at this line:
this.dbSet = context.Set<TEntity>();
I know that this line doesn't work because a use ObjectContext in my project and database first approach. How can i deal with it? Can I code generic repository without migration to code first (which is not an option in my case) ?
This is the equivalent for ObjectContext:
this.dbSet = context.CreateObjectSet<TEntity>();
Now this creates an ObjectSet<TEntity> rather than a DbSet<TEntity>, but for your pattern you can use it in the same way.
UPDATE
The ObjectSet class does not have a utility method like that matches the Find() method of the DbSet. In order to "Get by key" you would need to construct an EntityKey and use the ObjectContext.GetEntityByKey(), unfortunately that's not a really simple thing to do.
There really isn't a simple way to tackle this, that I've found. In my case what I've done is to base all of my entities from a common class (using custom T4 templates to generate the classes from the model). And then I can add a generic constraint to my repositories, like:
public class MyRepository<TEntity> where TEntity : MyEntityBaseClass
And then my common base class has an Id field which is inherited by all the entities so I can can simply do:
return myObjectSet.SingleOrDefault(x => x.Id == myId);
I'm sure there are other approaches, that might be a good topic for another question.
1. You want to add the DbContextGenerator template to your visual studio templates:
2. After this make sure you clear out the default generation tool on your .edmx file.
3. Now you can implement the GenericRepository pattern as you wish.

Linq-to-entities: How to create objects (new Xyz() vs CreateXyz())?

What is the best way of adding a new object in the entity framework. The designer adds all these create methods, but to me it makes more sense to call new on an object. The generated CreateCustomer method e.g. could be called like this:
Customer c = context.CreateCustomer(System.Guid.NewGuid(), "Name"));
context.AddToCustomer(c);
where to me it would make more sense to do:
Customer c = new Customer {
Id = System.Guid.NewGuid(),
Name = "Name"
};
context.AddToCustomer(c);
The latter is much more explicit since the properties that are being set at construction are named. I assume that the designer adds the create methods on purpose. Why should I use those?
As Andrew says (up-voted), it's quite acceptable to use regular constructors. As for why the "Create" methods exist, I believe the intention is to make explicit which properties are required. If you use such methods, you can be assured that you have not forgotten to set any property which will throw an exception when you SaveChanges. However, the code generator for the Entity Framework doesn't quite get this right; it includes server-generated auto increment properties, as well. These are technically "required", but you don't need to specify them.
You can absolutely use the second, more natural way. I'm not even sure of why the first way exists at all.
I guess it has to do with many things. It looks like factory method to me, therefore allowing one point of extension. 2ndly having all this in your constructor is not really best practice, especially when doing a lot of stuff at initialisation. Yes, your question seems reasonable, i even agree with it, however, in terms of object design, it is more practical as they did it.
Regards,
Marius C. (c_marius#msn.com)