Multiple instances of generic class - java

I'm trying to create a generic DAO in order to avoid having more or less the same code in many separate DAOs.
My problem is that in the following lines of code:
private BaseDAOImpl<Artist> baseDAOArtist = new BaseDAOImpl<>(Artist.class);
private BaseDAOImpl<ArtistRelation> baseDAOArtistRelation = new BaseDAOImpl<>(ArtistRelation.class);
The first one seems to be skipped.
An excerpt of the BaseDAOImpl:
public class BaseDAOImpl<T> implements BaseDAO<T> {
private Class<T> entity;
private DAOFactory daoFactory = Config.getInstance().getDAOFactory();
private static String SQL_FIND_BY_ID;
public BaseDAOImpl(Class entity) {
this.entity = entity;
SQL_FIND_BY_ID = "SELECT * FROM VIEW_" + entity.getSimpleName() + " WHERE id = ?";
}
}
Is it not possible to instantiate multiple objects this way?

Yes. It's not clear what you mean by "The first one seems to be skipped." but it could be that your using a static value for "SQL_FIND_BY_ID"? As at the moment:
private BaseDAOImpl<Artist> baseDAOArtist = new BaseDAOImpl<>(Artist.class);
Creates two instance variables and sets the value of SQL_FIND_BY_ID then:
private BaseDAOImpl<ArtistRelation> baseDAOArtistRelation = new BaseDAOImpl<>(ArtistRelation.class);
Creates two new instance variables and will change the value "SQL_FIND_BY_ID" for both instances.

Without a more detailed description of the error I am more or less guessing now, but judging from variable names and the code snippet I would suspect the static field SQL_FIND_BY_ID to be the cause.
When you instantiate the two DAOs, the second execution of the constructor BaseDAOImpl will overwrite the value of the static field. If the DAO relies on the SQL query stored there, it will always query for the entity of the last instantiated DAO.
Static fields and methods are shared among all instances of a class even if they differ on their generic parameters. In contrast to e.g. C++'s templates, there are no separate classes generated for each generic parameter.
To achieve the desired behavior of separate queries for each entity you may change the static field to a non-static member.

Related

ModelMapper DTO-->Entity. How to skip unconditionally all fields not mapped

I have two classes (entity and DTO)
public class Deliver {
private Long id;
private String uri;
private Instant moment;
private DeliverStatus status; // enum PENDING,ACCEPTED,REJECTED
private String feedback; // feedback about received task
private Integer correctCount; // nr of correct questions
private Enrollment enrollment;
private Lesson lesson;
// constructors, getters and setters..
public class DeliverRevisionDto {
private DeliverStatus status;
private String feedback;
private Integer correctCount;
// constructors, getters and setters..
The goal is pretty simple, update the entity fields conveyed by Dto class I have the following code at Service layer (Spring Boot version 2.4.4):
#Service
public class DeliverService {
#Autowired
private DeliverRepository deliverRepository;
#Autowired
private ModelMapper modelMapper;
#Transactional
public void saveRevision(Long id, DeliverRevisionDto dto) {
Deliver deliver = deliverRepository.getOne(id);
System.out.println("BEFORE MAPPING: " + deliver.toString()); // # debug purpose
deliver = modelMapper.map(dto, Deliver.class);
// # debug purpose
TypeMap<DeliverRevisionDto, Deliver> tm = modelMapper.getTypeMap(DeliverRevisionDto.class, Deliver.class);
List<Mapping> list = tm.getMappings();
for (Mapping m : list)
{
System.out.println(m);
}
System.out.println("AFTER MAPPING: " + deliver.toString()); // # debug purpose
deliverRepository.save(deliver);
}
}
The console output is:
BEFORE MAPPING: Deliver [id=1, uri=``https://github/someone.com``, moment=2020-12-10T10:00:00Z, status=PENDING, feedback=null, correctCount=null, enrollment=com.devsuperior.dslearnbds.entities.Enrollment#7e0, lesson=com.devsuperior.dslearnbds.entities.Task#23]`
`PropertyMapping[DeliverRevisionDto.correctCount -> Deliver.correctCount]`
`PropertyMapping[DeliverRevisionDto.feedback -> Deliver.feedback]`
`PropertyMapping[DeliverRevisionDto.status -> Deliver.status]`
`AFTER MAPPING: Deliver [id=null, uri=null, moment=null, status=ACCEPTED, feedback=Muito bem cabra, tarefa aceita., correctCount=5, enrollment=null, lesson=null]
The mapping of the 3 fields in DTO is done correctly, BUT all the other fields of my entity are set to null. I know that I can skip fields according http://modelmapper.org/user-manual/property-mapping/
The problem is that I don´t want to couple the code with specific field names/getters/setters, that´s the reason I´m using ModelMapper. I wonder if there is any configuration that, upon mapping the modelmapper object says "Hey, the TARGET class have way more fields than the SOURCE class, I will left them untouched unconditionally (meaning I don´t need to say what fields are).
I'm trying to map fields between 2 classes with different set of fields (some are the same), and when I map the class with smaller set of fields to the one with bigger set of fields, the mapper set fields that don´t match with "null", I want these fields untouched (with original values) without I telling which one they are, after all, the mapper knows which ones match.
ModelMapper documentation is not the best part of that framework. Let us see what happens in your code.
Here you fetch the entity to be updated from the repo:
Deliver deliver = deliverRepository.getOne(id);
and log it having all the fields as should be. However this line:
deliver = modelMapper.map(dto, Deliver.class);
does a re-assignment to your variable deliver. This method creates a new instance of Deliver class and assigns it to variable deliver so discarding the entity fetched from repo.
This new instance will have all the fields that are not existing or not set in DTO null.
This is the API doc that my IDE provides, fotr these two different methods:
String org.modelmapper.ModelMapper.map(Object source, Class destinationType)
Maps source to an instance of destinationType. Mapping is performed according to the corresponding TypeMap. If no TypeMap exists for source.getClass() and destinationType then one is created.
Versus
void org.modelmapper.ModelMapper.map(Object source, Object destination)
Maps source to destination. Mapping is performed according to the corresponding TypeMap. If no TypeMap exists for source.getClass() and destination.getClass() then one is created.
It might not be clearly stated that the first method actually creates a new instance based on the type (Class) passed but it should be clear that ModelMapper cannot alter some arbitrary variable just by knowing the type. You need to pass the variable to alter as method parameter.

Grails Domain Class String List Not Persisting

This is in grails 2.5.6 code. I have a domain class that uses inheritance. One of the subclasses contains a list of strings stored in the variable values. When calling .save(), the domain class itself saves correctly with the right inheritance behavior, but the values do not get saved. Here is my domain classes:
abstract class Condition implements ICondition, IMarshaler {
String field;
static mapping = {
tablePerHierarchy false;
}
...
}
class ListCondition extends Condition {
static hasMany = [values: String];
List<String> values;
...
}
Attempting to save a new list condition and the getting it again from the database shows that there is no values.
ListCondition condition = new ListCondition(field: 'someField', values: ['test', 'otherTest'])
condition.save()
println ListCondition.getAll()[0].values.size() // Prints 0
Stumbled upon a similar issue. Try condition.save(flush: true) or even better try running your persistence-logic inside a transaction. This seems to make the difference and is considered best-practice anyways.

Java: creating several instances of object in class itself or how to restructure

I'm a java beginner and have a question concerning how to best structure a cooking program.
I have a class called Ingredient, this class currently looks like this:
public class Ingredient {
private String identifier;
private double ingredientFactor;
private String titleInterface;
public Ingredient(String identifier, double ingredientFactor,String titleInterface) {
this.identifier = identifier;
this.ingredientFactor = ingredientFactor;
this.titleInterface = titleInterface;
}
I want to initialize several objects (about 40) with certain values as instance variables and save them in a Map, for example
Map<String, Ingredient> allIngredients = new HashMap<String, Ingredient>();
allIngredients.put("Almonds (ground)", new Ingredient("Almonds (ground)", 0.7185, "Almonds (ground)");
Later on I want to retrieve all these objects in the form of a Map/HashMap in a different class.
I'm not sure how to proceed best, initialize all these objects in the Ingredient class itself or provide a method that initializes it or would it be better to create an super class (AllIngredients or something like that?) that has a Map with Ingredients as instance variables?
Happy for any suggestions, thanks in advance :)
Please do not initialize all these objects in the Ingredient class itself. That would be a bad practice for oops.
Just think your class is a template from which you create copies(objects) with different values for attributes. In real world if your class represent model for a toy plane which you would use to create multiple toy planes but each bearing different name and color then think how such a system would be designed. You will have a model(class). Then a system(another class) for getting required color and name from different selection of colors and names present(like in database,files,property file ) etc.
Regarding your situation .
If predetermined values store the values in a text file,properties file,database,constants in class etc depending on the sensitivity of the data.
Create Ingredient class with constructors
Create a class which will have methods to initialize Ingredient class using predetermined values,update the values if required,save the values to text file -database etc and in your case return as map .
Also check the links below
http://www.tutorialspoint.com/design_pattern/data_access_object_pattern.htm
http://www.oracle.com/technetwork/java/dataaccessobject-138824.html
Sounds to me like you are looking for a static Map.
public class Ingredient {
private String identifier;
private double ingredientFactor;
private String titleInterface;
public Ingredient(String identifier, double ingredientFactor, String titleInterface) {
this.identifier = identifier;
this.ingredientFactor = ingredientFactor;
this.titleInterface = titleInterface;
}
static Map<String, Ingredient> allIngredients = new HashMap<String, Ingredient>();
static {
// Build my main set.
allIngredients.put("Almonds (ground)", new Ingredient("Almonds (ground)", 0.7185, "Almonds (ground)"));
}
}

Create an arbitary table like object for jOOQ unit testing

I have an issue using jOOQ's MockDataProvider to mock a SQL JOIN in a unit test.
The JOIN implemented with jOOQ selects a single column containing UUIDs. Thus the result type is Result<Record1<UUID>>. In the associated unit test I would like to mock this result using the MockDataProvider, but I can't find a proper way to initialize the Result, as I can't find a way to create a table like object I could pass to the newResult method. I know that there are some table methods in DSL, but the signatures just seem to be wrong for my use case.
Also as the unit test is not runnable at this point, I'm not sure that the way I create the UUID field is correct.
This is my code:
private class MyProvider implements MockDataProvider {
#Override
public MockResult[] execute(final MockExecuteContext ctx) throws SQLException {
final MockResult[] mockResults = new MockResult[1];
final DSLContext db = DSL.using(SQLDialect.POSTGRES);
final Result<Record1<UUID>> result = db.newResult(<some table object here>);
final Field<UUID> uuidField = DSL.fieldByName(UUID.class, "uuid");
final Record1<UUID> record = db.newRecord(uuidField);
record.setValue(uuidField, ID);
result.add(record);
mockResults[0] = new MockResult(1, result);
return mockResults;
}
}
I suspect that this is essentially the same question as the one on the jOOQ User Group here:
https://groups.google.com/forum/#!topic/jooq-user/h4pfIHjmBpo
In summary, there is a method that is going to be added to jOOQ 3.4 (with issue #3139), to help you create such Result objects for arbitrary Record types. In the mean time (before jOOQ 3.4 is released), you will have to resort to creating a new org.jooq.impl.ResultImpl via reflection.

how find fields of all member variables contained in java bean

I want to make a GUI using Java in which a user can select a bean, edit its fields, and then add an instance of the created bean to a queue. My question though is about accessing the fields. I have a class MyCompositeObject that inherits from MyParentObject. The MyParentObject is composed of multiple beans, each being composed of more beans. The class MyCompositeObject is also composed of beans. I want to find all accessible fields from MyCompositeObject.
Class MyParentObject
{
MyObjectOne fieldOne;
MyObjectTwo fieldTwo;
String name;
...
}
Class MyCompositeObject extends MyParentObject
{
MyObjectThree fieldThree;
Integer number;
...
}
Class MyObjectThree
{
boolean aBoolean;
MyObjectFour fieldFour;
...
}
I have been trying to use the BeanUtils api, but I'm getting stuck trying to get the fields of all the member beans. What I am imagining is a depth first search of all fields that could be accessed from an instance of MyCompositeObject. For example, this would include, but not be limited to, the fields: MyCompositeObject.fieldOne, MyCompositeObject.number, MyCompositeObject.fieldThree.aBoolean.
I realized when I tried:
Fields[] allFields = BeanUtils.getFields(myCompositeObject);
that I was in over my head. My research has so far not turned up any prebuilt methods that could do what I describe. Please let me know of any API methods that can do this or tell me how I can go about building my own. Thanks.
It's kind of a pain but you have to go in two dimensions
yourBeanClass.getSuperclass(); (and recursively get all superclasses until Object)
and then you can get the fields of each one
eachClass.getDeclaredFields() NOT getFields so you can get all the private fields
Once you have each field
field.getType() which returns the Class of that field
then of course, you need to go up that dudes superclass chain again to make sure you get ALL the fields of the class including the ones in the superclass
Once you have that chain of classes for that field, you can then get it's fields by repeating the above....yes, the jdk made this fun!!!! I wish to god they had a getAllDeclaredFields method so I didn't have to go up the superclass heirarchy.
IMPORTANT: you need to call field.setAccessible(true) so you can read and write to it when it is a private field by the way!!!
Here is code that gets all the fields for a Class including the superclasses..
private static List<Field> findAllFields(Class<?> metaClass) {
List<Field[]> fields = new ArrayList<Field[]>();
findFields(metaClass, fields);
List<Field> allFields = new ArrayList<Field>();
for(Field[] f : fields) {
List<Field> asList = Arrays.asList(f);
allFields.addAll(asList);
}
return allFields;
}
private static void findFields(Class metaClass2, List<Field[]> fields) {
Class next = metaClass2;
while(true) {
Field[] f = next.getDeclaredFields();
fields.add(f);
next = next.getSuperclass();
if(next.equals(Object.class))
return;
}
}
later,
Dean

Categories

Resources