When is the implementation for repositories generated by Spring Data? At compile time or runtime? Can I see the implementation repository implementation generated by Spring Data?
tl;dr
No, for a very simple reason: there's no code generation going on. The implementation is based on proxies and a method interceptor delegating the call executions to the right places.
Details
Effectively, a method execution can be backed by 3 types of code:
The store specific implementation of CrudRepository. Have a look for types named Simple(Jpa|Mongo|Neo4|…)Repository (see the JPA specific one here). They have "real" implementations for all of the methods in CrudRepository and PagingAndSortingRepository.
Query methods are effectively executed by QueryExecutorMethodInterceptor.doInvoke(…) (see here). It's basically a 3-step-process to find the delegation target and invoke it. The actual execution is done in classes named (Jpa|Mongo|Neo4j…)QueryExecution (see this one for example).
Custom implementation code is called directly, also from QueryExecutorMethodInterceptor.
The only thing left is the query derivation, which consists of two major parts: method name parsing and query creation. For the former, have a look at PartTree. It takes a method name and a base type and will return you a parsed AST-like structure or throw an exception if it fails to resolve properties or the like.
The latter is implemented in classes named PartTree(Jpa|Mongo|Neo4j|…)Query and delegates to additional components for actually creating the store specific query. E.g. for JPA the interesting bits are probably in JpaQueryCreator.PredicateBuilder.build() (see here).
Related
What is the difference between JPAQuery and JPAQueryFactory?
And, When to use which?
According to the querydsl reference documentation:
Both JPAQuery and HibernateQuery implement the JPQLQuery interface.
For the examples of this chapter the queries are created via a JPAQueryFactory instance. JPAQueryFactory should be the preferred
option to obtain JPAQuery instances.
But, I could not understand clearly.
Can anyone explain it briefly?
What matters is that Hibernates query language (HQL) is a superset of JPA's query language (JPQL). Hibernate also has a special method for result set transformation and being able to iterate over scrollable result sets without the need to keep a reference to all records in memory. In order to take advantage of this extra functionality, the HQLTemplates and the HibernateHandler have to be used. The first is responsible for serializing the additional types of expressions, the second for the integration with Hibernates Query implementation. The HibernateHandler is actually obtained from the HQLTemplates as well, so all that remains is specifying HQLTemplates.
And in fact: a JPAQuery instantiated with HQLTemplates.INSTANCE for the Templates variable, behaves the same as a HibernateQuery. FWIW, if you provide an EntityManager instance with the construction of your JPAQuery, then the appropriate implementation for Templates is deduced for your ORM vendor automatically.
All JPAQueryFactory really is, is a factory method that binds the EntityManager and Templates variables for newly instantiated JPAQueries. This eliminates the need to pass these as a variable individually for each instantiation of a JPAQuery.
There is no need to use the JPAQueryFactory, but it could make your code easier to read. Furthermore, a lot of code examples on the QueryDSL website utilize the query factory, so it might make it easier to use these examples as snippets in your own code.
Spring Data allows you to declare methods like findByLastname() in your repository interface and it generates the queries from the method name automatically for you.
Is it possible to somehow have these automatically-generated queries also accept a Specification, so that additional restrictions can be made on the data before it's returned?
That way, I could for example call findByLastname("Ted", isGovernmentWorker()), which would find all users that have the last name Ted AND who satisfy the isGovernmentWorker() specification.
I need this because I'd like the automated query creation provided by Spring Data and because I still need to be able to apply arbitrary specifications at runtime.
There is no such feature. Specifications can only be applied on JpaSpecificationExecutor operations.
Update
The data access operations are generated by a proxy. Thus if we want to group the operations (as in findByName + Criteria) in a single SELECT call, the proxy must understand and support this kind of usage; which it does not.
The intended usage, when employing Specification API would look like this for your case:
findAll(Specifications.where(hasLastName("Ted")).and(isGovernmentWorker())
Spring data allows you to implement custom repository and use Specifications or QueryDSL.
Please see this article.
So at the end you will have one YourCustomerRepository and appropriate YourRepositoryImpl implementation, where you will put your findByLastname("Ted", isGovernmentWorker()) method.
And then YourRepository should extend YourCustomerRepository interface.
I am working on a Web Application using ASP.Net MVC 4 3-Tier Architecture and I am stuck at certain points. I know here exist similar threads but none were clear enough. I have already created the needed layers which are UI(MVC4 project), BLL- Business Logic Layer(library class), BOL- Business Object Layer(library class that contains ADO.net) and DAL- Data Access Layer (library class).
Layer dependencies are as follows:
UI depends on BOL and BLL
BLL depends on BOL and DAL
DAL depends on BOL
I want you to correct me if I am wrong in the following. The BOL is the master reference layer which exchanges raw dB records with DAL then sends them to BLL which is responsible for any logical computations then gets the updated records and sends them to the controller in the UI.
Knowing the above,
Where should we place the CRUD functions?
Where and why should we create a class for declaring (plus set and get) the useful database fields?
What exactly should we put in the ViewModel folder; in other words since we have already defined the variables in the previous step and in the Entity then does it add any value to keep the Model folder?
Thank you in advance.
Can't be unambiguously correct answers on these issues, so any answer should be evaluated simply as an opinion. Here are my answers:
Where should we place the CRUD functions? CRUD is a frequent pattern at different levels. Hi-level Repository provides similar methods, as a low-level Table Gateway.
Where and why should we create a class for declaring (plus set and get) the useful database fields? These classes are usually simple Data Transfer Objects (DTO) or slightly more complicated Active Records. In accordance with the Dependency Inversion Principle the interface for these classes should provide the Business Logic Layer, and implementation should provide the Data Access Layer. Since DTO is very simple classes, they can be provided "as is" without interface/implementation separation.
What exactly should we put in the ViewModel folder; in other words since we have already defined the variables in the previous step and in the Entity then does it add any value to keep the Model folder? In theory entities should be our models; but in practice it's often not the case. F.e. in ASP.NET MVC models should provide not only the value of drop-down field, but also all possible values; so it requires the separate model class.
The result may be that you have three or four very similar classes at different levels of the application. Of course, it's not very good, so Aspect Programming may be applied in this case.
I'm writing my first GWT-Application and need your advice. I have no problems implementing a locator for database entities where I can reuse the version-column used for optimistic locking by hibernate, but one of my entities represents a ldap-Object. Can you tell me what the method getVersion() of the Locator is used for and how I can implement this method for my ldap-Object? I will do read and write ldap objects.
From GWT documentation, getVersion method is
Used by RequestFactory to infer if an entity has changed. The backing store (JDO, JPA, etc.) is responsible for updating the version each time the object is persisted, and RequestFactory calls getVersion() to learn of changes. This information is used in two places. First, the RequestFactoryServlet sends an UPDATE event to the client if an entity changes as a result of the method invocation on the server, for example, when a call to persist an editable entity results in an updated version on the server. Second, the client maintains a version cache of recently seen entities. Whenever it sees an entity whose version has changed, it fires UPDATE events on the event bus so that listeners can update the view.
Since many persistence frameworks offer generic find/get/query methods, it's also possible to create a generic Locator class and specify it in the #ProxyFor annotation for each entity type. To do this, all your entities can extend a base class that provides getId() and getVersion(). Alternatively, the generic Locator can use reflection to call getId() and getVersion() when needed.
Not sure if you're looking for anything else in addition to this.
I have the same problem. My first thought was to use the Attribute modifyTimestamp and createTimestamp. But there is still a functional gap:
The smallest unit of These timestamps is seconds so a Change in the same second can not be detected. Another solution would be to use a kind of checksum over all attributes of the ldap object. Not very nice..
When using an IPC library, it is important that it provides the possibility that both client and server can communicate even when their version of the API differs. As I'm considering using SOAP for our client/server application, I wonder whether a SOAP/WSDL solution can deal with API changes well.
For example:
Adding parameters to existing functions
Adding variables to existing structs that are used in existing functions
Removing functions
Removing parameters from existing functions
Removing variables from existing structs that are used in existing functions
Changing the type of a parameter used in an existing function
Changing the order of parameters in an existing function
Changing the order of composite parts in an existing struct
Renaming existing functions
Renaming parameters
Note: by "struct" I mean a composite type
As far as I know there is not such stuff as per the SOAP/WSDL standard. But tools exists to cope with such issues. For instance, in Glassfish you can specify XSL stylesheet to transform the request/response of a web service. Other solution such as Oracle SOA suite offer much more elaborated tools to manage versioning of web service and integration of component together. Message can be routed automatically to different version of a web service and/or transformed. You will need to check what your target infrastructure offers.
EDIT:
XML and XSD is more flexible regarding evolution of the schema than types and serialization in object-oriented languages. Some stuff can be made backward compatible by simply declaring them as optional, e.g.
Adding parameters to existing functions - if a parameter is optional, you get a null value if the client doesn't send it
Adding variables to existing structure that are used in existing functions - if the value is optional, you get null if the client doesn't provide it
Removing functions - no magic here
Removing parameters from existing functions - parameters sent by the client will be superfluous according to the new definition and will be omitted
Removing variables from existing structure that are used in existing functions - I don't know in this case
Changing the type of a parameter used in an existing function - that depends on the change. For a simple type the serialization/deserialization may still work, e.g. String to int.
Note that I'm not 100% sure of the list. But a few tests can show you what works and what doesn't. The point is that XML is sent over the wire, so it gives some flexibility.
It doesn't. You'll have to manage that manually somehow. Typically by creating a new interface as you introduce major/breaking changes.
More generally speaking, this is an architectural problem, rather than a technical one. Once an interface is published, you really need to think about how to handle changes.