I want to have a depper look into java reflection and hibernate.
To pass values to a known setter works, but I want to do the same with an unknown setter of a hibernate pojo.
I get the mapped class with
PersistentClass mappedClass = session.configuration.getClassMapping(classFromPath.getName());
Table myTable = mappedClass.getTable();
iter = myTable.getColumnIterator();
while(iter.hasNext()) {
Column myColumn = (Column) iter.next();
Property myProperty = mappedClass.getProperty(myColumn.getName());
System.out.println(myProperty.getName());
}
This is my way, to get a specific property. Now, I want to get the propertys getter and setter methods.
One way is to get the name, to concate the words get/set with the property names. I don't like that way and want a better solution.
I know, there is a function like myProperty.getSetter, but I'm not sure, how to deal with it.
I'm totally wrong? Are there any ways to get the getter/setter methods?
You can use Introspector and PropertyDescriptor for this.
For details, please refer here
Related
Due to the fact that I'm using an abstract class, I get such error:
org.springframework.data.mapping.MappingException: Ambiguous field mapping detected!
Both private final com.life.book.domain.event.EventType com.life.book.domain.command.ObjectCommand.eventType
and private final com.life.book.domain.event.EventType com.life.book.domain.command.UpdateObjectCommand.eventType
map to the same field name eventType! Disambiguate using #Field annotation!
My classes:
abstract class ObjectCommand(
open var eventType: EventType?
)
#Document(collection = "COMMAND")
data class UpdateObjectCommand(
val description: String?,
override var eventType: EventType?
) : ObjectCommand(eventType)
enum class EventType {
CREATED, UPDATED
}
The solution might be to use a different name instead of the eventType name in the UpdateObjectCommand class. But then the database will have two fields with the same purpose. Maybe there is another way?
There is Disambiguate using #Field annotation in the description of the error, but I don't understand how to use it.
It's been a sec since I have delt with what looks like Mongo DB and Spring Boot (I could be off base here). The #Field annotation is applied to fields in your class that have the #Document annotation.
You can add information to the #Field annotation like the serialized name of the field, or if its written when null. #Field in most cases does not need to be applied to a field unless you are dealing with enums. Mongo does not know how to store an enum, so you must add the #Field annotation to specify that it needs to be stored as a string.
https://blog.tericcabrel.com/using-mongodb-with-spring-boot-project-part-1/
From tericcabrel.com:
#Field is used to enhance the property by changing the type; like our case, MongoDB doesn't support Enum, so we need to tell Mongo to store this property's value as a string. When retrieving the data from the collection, the value will be returned back as an Enum. You can also provide a different name for the property in MongoDB.
How can I access this value, the max value and message from the controller
I try to access the information schema table, do it via sql and access this variable without writing it directly in the code,
I was trying to access the schema Information table, to get the maximum value from the column but it generates an error that is not mapped
thank you very much and sorry, I'm new to this
There are 2 options to do this.
Since the value is constant, you can declare a static final variable and use it as the class variable.
eg:
static final int MAX_RANGE = 100;
In this case, just use "class_name".MAX_RANGE
You could also specify the value in a property file and use the property file as and when needed.
You can use reflection (which is not the best case)
Class<?> cls = Class.forName(name);
cls.getDeclaredAnnotations(); // get all annotation
(cls.getDeclaredMethods()[0]).getAnnotations(); //get annotation of a method
Annotation ety = cls.getAnnotation(Annotation.class); // get annotation of particular annotation class
I have an entity which looks something like this: (I'm coding to the web page so I apologize for any mistakes)
#Entity
public class Entity {
#Id
private Long id;
private String field;
// Insert getters and setters here...
}
I try to manipulate it using reflection:
Long id = 1;
Entity entity = myDao.getEntity(id);
entity.setField("set directly");
Field[] fields = entity.getClass().getDeclaredFields();
for (Field f : fields) {
if (f.getName().equals("field")) {
f.setAccessible(true);
f.set(entity, "set using reflection");
f.setAccessible(false);
}
}
System.out.println(entity.getField());
This program prints "set using reflection". However, in the database the value set using reflection does not get updated:
SELECT * FROM ENTITY WHERE ID = 1
ID FIELD
1 set directly
This is strange. I could swear that this used to work - but now it isn't. Is it really so that you cannot manipulate entities using reflection?
I'm using EclipseLink 1.1.1 if that matters.
Changing values of an entity class by reflection is going to fraught with issues. This is because you're dealing with a class which is persistent and thus the persistence API needs to know about changes to the fields.
If you make changes via reflection, chances are the persistence API will not know about those changes.
A better solution would be to call the setters via reflection.
I'm pretty sure the Entity you are given by your persistence framework is actually wrapped in another class (possibly the same with stuff tacked on through reflection). Changing the field directly through reflection seems unlikely to work. You might want to check if there's a (generated) setter that you can use. Although if you're going that route one might ask why you don't allow callers to call the setter directly?
Your class might be instrumented and the setters responsible for recording changes. I'm not familiar with EclipseLink to check if the class returned by myDao.getEntity(id); is your actual class of a sub-class generated by EclipseLink.
I'm trying to use spring PagingAndSortingRepository with a find MyEntity where field in fieldValues query as follows:
#Repository
public interface MyEntity extends PagingAndSortingRepository<MyEntity, String> {
List<MyEntity> findByMyField(Set<String> myField);
}
But of no success.
I expected the above function to return all entities whose field matches one of the field values but it only returns empty results.
Even though it seems like a pretty straight forward ability i could not find any reference to it in the docs.
Is / How that could be achieved?
Thanks.
This should indeed be possible if you are searching on a specific field within your entity and you want to return a list of all that field matches at least one entry in some collection. The documentation here says this can be achieved using the keyword In example: findByAgeIn(Collection<Age> ages) and is equivalent to … where x.age in ?1
From your post i'm not 100% sure if this is the use case you are after but give this a try. You will need to search on a specific field, so replace 'field' with whatever field you are searching on. If you are searching on multiple fields it may be possible to concatenate the results with the Or keyword and specify multiple fields that way.
#Repository
public interface MyEntity extends PagingAndSortingRepository<MyEntity, String> {
List<MyEntity> findByFieldIn(Set<String> myField);
}
http://docs.spring.io/spring-data/jpa/docs/current/reference/html/
Your method name has to be findByMyFieldIn so you got to add an In at the end to get a where ... in (..) query.
Code:
class MyClass {
private String field1;
private Long field2;
//getters and setters also here
}
List<MyClass> myClassList = new ArrayList<>();
//getting my list filled
Now I need to set e.g. field1 for all objects in list to some value. I can do it with:
forEach(myClassList).setField1("some value");
But how can I set some field dynamically, passing field name as string "field1" or "field2" etc.?
What you're asking is countrary to the main principle on which lambdaj is based. I designed it to allow to invoke the methods of your Beans in a strongly typed way. In this way you have all the help that your favorite IDE can give you like autocompletion. Moreover if you'll decide to rename that method your IDE will be able to automatically change the name for you or at least you'll a compilation error instead of finding the problem only at runtime.