I am using MapStruct to provide bean mapping between different systems, and I have reached a point where the only way to map a specific property is to add it as a Map entry to the target object with the field name as key.
I can do this using a very long expression where I set the entire map using guava ImmutableMap builder, but is there a more elegant and safe way of providing this mapping? Setter method would expect two parameters in this case.
This is currently not support in MapStruct. There is already an open feature request #1075 for support like this.
Related
I am trying to implement REST query param "fields" with Mapstruct. The REST "fields" query param by convention lets you specify as its value a comma separated list of the fields of the entity you want in the response when you are preforming a GET request on an entity. This is opposed to returning all the fields of entity, which is what happens when "fields" query parameter is omitted.
Example:
GET locahost/blah/1
Response {"a":"1", "b":"2", c:"3"}
GET local/blah/1?fields=a,c
Response {"a":"1", "c":"3"}
So what I want Mapstruct to do is only map the bean's fields who's fields' names I specify. Note I need to be able to specify the bean's fields' names I want to map at runtime. Why? The fields I wish to map change from call to call of the GET method.
From what I read in the MapStruct documentation, you can specify what fields to map or not map with annotations. Unfortunately you can't change the annotation value at runtime (It maybe possible through reflection, but it feels should be a better way).
Given what I want to do, does anyone know how I can specify at runtime what fields are mapped?
Or alternately does anyone know a better way of implementing the REST "fields" query param?
I Look forward to reading the responses. If you have any questions or need clarifications just ask 🙂.
Regards,
Ben.
Thinking about this, I think that it doesn't make sense. As MapStruct generates the mapper classes at build time and therefore can't changing the mapping process at runtime. Is this right?
I am developing an SAPUI5 app using Smart Table and Smart Filter. I have added local annotations for LineItem and SelectionFields for this purpose in my Web IDE project. The table is being rendered as expected, but not the Smart Filter. I am not able to get suggestions and value help for my input filter since there are no OData annotations for this.
Is it possible to add ValueList annotation in the Local Annotations file in the Web IDE project to map the main entity set and the value help entity set? The required entity set that I want for the value help is already a part of the OData service. But, I was unable to find ValueList annotation under Common Vocabulary in the annotation modeler. Please help.
Yeah, create second entity with dictionary and add in local annotation file valuelist annotation.
So, I have an object that is embedded via the #Embedded annotation in several entities. I would like to exclude a property/attribute from being persisted in one instance where it is embedded but not the other. Is there a concise way to do this? Should I do this? If not, why not? I'm using spring-data-jpa 1.7.1, eclipselink 2.5.1. Thanks in advance!
Ken
Firstly you cannot use annotations if you want to persist a field of a class (whether embedded or otherwise) differently in one place than another (since an annotation is specified in one place only), or at least I can't see how it would be possible.
Secondly, with XML you could specify an "embedded" element and under that "attributes" and for each attribute you could put "transient". Never tried it mind, but that would be the way I'd go
I read this in the EJB/JPA Book:
"Even if you mark the property as LAZY for a #Basic type, the persistence provider is still allowed to load the property eagerly. This is due to the fact that this feature requires class-level instrumentation. It should also be noted that lazy loading is neither really useful nor a significant performance optimization. It is best practice to eagerly load basic properties."
QUESTION 1)
If I set property as an LAZY, why e persistence provider is still allowed to load the property eagerly? when this happens? and why? is this for primitives only?
QUESTION 2)
"The #Basic annotation is the simplest form of mapping for a persistent property. This is the default mapping type for properties which are primitives, primitive wrapper types"
If I use does not use primitive or wrapper (for instance I use my class object), will he persistence provider is still allowed to load the property eagerly?
QUESTION 3)
"You do not need to tell your persistence manager explicitly that you're mapping a basic property because it can usually figure out how to map it to JDBC using the property's type."
As I understand this happens when I use primitives or wrappers, don't I? And how does it figure out how to map? Is there any obvious rule?
QUESTION 1)If I set property as an LAZY, why e persistence provider is
still allowed to load the property eagerly? when this happens? and
why? is this for primitives only?
Because of performance issues: the JPA provider has the right (according to the JPA spec) to decide that it is better to fetch the field eagerly. This is valid also for wrapper fields & Strings. It is not specified when this happens, which means that can happen when the JPA provider considers it needed.
QUESTION 2)"The #Basic annotation is the simplest form of mapping for
a persistent property. This is the default mapping type for properties
which are primitives, primitive wrapper types"
If I use does not use primitive or wrapper (for instance I use my
class object), will he persistence provider is still allowed to load
the property eagerly?
Actually yes, also for relationships you have the same rule, although almost always the JPA provider will consider your hint. Of course: when you have a field of type YouClass, you are not allowed to annotate it with #Basic and must use #ManyToOne-like annotations. You will read further about them.
QUESTION 3) "You do not need to tell your persistence manager
explicitly that you're mapping a basic property because it can usually
figure out how to map it to JDBC using the property's type."
As I understand this happens when I use primitives or wrappers, don't
I? And how does it figure out how to map? Is there any obvious rule?
That happens will all types listed in the documentation of the #Basic annotation, not only those that you enumerated. The rule is pretty simple: String types are mapped as VARCHAR/CHAR like columns, number-fields like NUMBER (or DECIMAL) and so further.
How do I use the 'exists' keyword in Spring Data in a query method?
I would like to have a method like this:
public interface ProfileRepository extends JpaRepository<Profile, Long> {
boolean existsByAttribute(String attribute);
}
where Attribute is a field of the Profile.
A workaround would be to use a custom-implementation. But the appendix defines exists as keyword. Could someone give me an example how to use this keyword?
Documented keywords are intended to be used in combination with a property reference. Thus, the semantics of EXISTS in this case are that it checks whether the property exists. Note, that the part of the documentation is pulled it from Spring Data Commons and the keyword being listed there doesn't mean it's supported in Spring Data JPA (indicated in the first paragraph of the section you linked). Exists is not supported by Spring Data JPA as it only makes sense in MongoDB for example as there's a difference between a field not present entirely and the field available with a logically null value.
So what you're looking for seems to be around the (Is)Null keyword with the current limitation that it would return objects and you'd have to check the returned list for content. There's a ticket to add support for projections for derived query methods which you might wanna follow for further progress.