Does OpenCSV support write to CSV from bean with a map [duplicate] - spring-boot

I'm using opencsv for read/write csv files using opencsv annotations.
My bean is having fields not just primitives, but a java HashMap as well.
Now what i want to do is
public class MyBean {
#CsvBindByName(column = "ID")
private int id;
#CsvBindByName(column = "PROPERTIES")
private Map<String, String> sampleMap = new HashMap<String, String>();
TO
ID, property1, property2...
1, value1, value2.....
I'd like to get this working in both read/write.
as i understand, the default MappingStrategy doesn't work in this case. Also Creating Custom MappingStrategy doesn't makes sense for HashMap field. because we don't know the complete field list until we iterate all the map.
Another way to get column names is that just read one bean from the list of beans. And get access to HashMap then create the header.(Hashmap keys are fixed across beans in my case)
MappingStrategy only concerned about Class level meta data. Like fields etc.
public static Field[] getAllFields(Class<?> cls) {
List allFieldsList = getAllFieldsList(cls);
return (Field[])allFieldsList.toArray(new Field[allFieldsList.size()]);
}
getting access to the real data for creating csv header doesn't look like a natural way to do.
Any advice on how to solve this?
Please point me out to any other libraries out there that can do read/write into beans having Map field.
Cheers!

Sadly openCSV does not support this. A quick google showed me that SuperCSV comes close but it puts everything in a map whereas you want to control what goes in the map and what does not. There may be others out there but most require a one to one between the fields in the object and the columns in the csv file.
This was something that I wanted to develop for years and contribute because the company I currently work for has need for that but they do not want to pay me to develop it and I have higher priorities for openCSV when free time is available.
A possible but limited workaround would be to create what I would call a Data Transfer Object. Have a custom object that has all the values you would have and have it return the object of the type you want (or a translator that will convert the DTO that has all fields to the object you want with the map and some fields). The problem with this solution is that it forces you to know in advance what are all possible entries you have in the map.

Related

Can MongoTemplate provide automatic translation?

I have a simple persistent pojo like:
public class Peristent {
private String unsafe;
}
I use Spring Data mongoTemplate to persist and fetch the above object. I also need to encrypt the Persistent.unsafe variable and store a complex representation of that in backend, everytime I try to save Persistent object.
Can I annotate Persistent, or provide some sort of hooks where I can make the aforementioned translations without me having to do that in the Pojo code manually. This has to happen automatically during mongoTemplate.insert.
Spring Data currently only support Type based conversions. There is an issue for supporting property based conversion, which you might want to track.
Therefore annotating won't work. What you could do is, create use a separate class for the property, which just wraps the String and register a custom converter for that type. See http://docs.spring.io/spring-data/data-mongo/docs/1.10.4.RELEASE/reference/html/#mongo.custom-converters for details, how to do that.

How to make flexible database for Spring MVC project

I want to make flexible database design for a Spring-mvc application, I mean that I want for example let user delete or add some attributes on the application withou disturbing it.
For example:
User want to add "adress mail" to his costumer or he want to delete "postal code" because he don't need this information ...etc
Something like that.
Is any body has an idea how to make that?
Use schemaless database, for example MongoDB. With Spring Data MongoDB you can persist maps that will give you flexibility you need:
#Document
public class Customer{
#Id
private ObjectId id;
private Map<String, String> properties;
...
}
Even though it is doable, I am not convinced if your design is valid. You can persist custom attributes in DB, but showing them in GUI at some point, when you need to customize look and feel for particular field it can become quite frustrating issue.

Spring-Data + QueryDSL + JDBC: how to map the query results to the domain objects?

I am considering to use Spring-Data + QueryDSL + JDBC to replace (or enhance) the currently used MyBatis.
My reasons are:
Compile-time check of column names
Compile-time check of SQL tatements and auto-completion from IDE
Ability to write unit tests on Java Collections against the same code that will work against the actual DB, which is much simpler and faster than pre-populating a DB
It is more concise than MyBatis – no need for a separate XxxMapper.java and XxxMapper.xml under the DAO layer
Yet I see the following problems:
There is no infrastructure for mapping the query results to domain objects. QueryDSL's QBean and MappingProjection, Spring's BeanPropertyRowMapper and Spring-Data's OneToManyResultSetExtractor seem to be too low level, see below.
No out of the box session/transaction-level cache which comes for free in MyBatis
No out of the box SQL statement and result logging which comes for free in MyBatis
Since I am asking a single question let's concentrate on the mapping which I consider the most important problem.
So my question is:
Is there any convenient solution to map the QueryDSL's SQLQuery results to the domain object, similar to what MyBatis or JPA offer? That is, the mapping based on some simple configuration, be it XML, annotations, or simple Java?
In particular, I am interested in the following:
Mapping a column to a custom type, e.g. a String column to an EmailAddress Java object
Mapping a group of columns to an embedded object, such as e.g. grouping {first_name, last_name} into a FullName Java object
Supporting one-to-many relationship, such as being able to extract a Customer object(s) containing a list of Addresses.
To summarize, I need an easy way to obtain one or many objects of the following 'Customer' class from the following SQL query:
class Customer {
EmailAddress emailAddress;
FullName fullName;
Set<Address> addresses;
Set<Comment> selfDescription;
}
class EmailAddress {
private String address;
EmailAddress(String address) {this.address = address; }
}
class FullName {
String firstName, lastName;
}
class Address {
String street, town, country;
}
class Comment {
LocalDateTime timeStamp;
String content;
}
Query:
query.from(qCustomer).
leftJoin(qCustomer._addressCustomerRef, qAddress)).
leftJoin(qCustomer._commentCustomerRed).
getResults(
qCustomer.email_address, qCustomer.first_name, qCustomer.last_name,
qAddress.street, qAddress.town, qAddress.country,
qComment.creation_time_stamp, qComment.content);
The ideal solution for me would be to reuse the MyBatis mapping infrastructure.
Another mapping solution or a custom one is also acceptable.
Note:
I could also accept "negative" answers if you show an alternative that:
Possesses an ease of use and transparency comparable to that of MyBatis - you always know which SQL is executed by simply inspecting the code
Allows full control over the executed SQL code, in particular, allows to easily write three DAO methods for retrieving 'Customer': without 'addresses' and 'selfDescription' information, just with 'addresses', and with all the fields
Allows compile-time check of your SQL code
Does not require hand-coding of mapping of every single domain class from SQL.
The alternative should work well on the example above.
Solutions already considered:
MyBatis 'Builder' class (http://mybatis.github.io/mybatis-3/statement-builders.html): not enough, since the column and table names are still Strings, so it violates requirement (3)
Spring-data + JPA + QueryDSL: might be an option if you show how the requirements (1) and (2) can be satisfied and if no simpler solution will be provided
Lukas Eder gave an excellent answer to a similar question here: Is it possible to combine MyBatis and QueryDSL/jOOQ?
His answer to the mapping question is to use either Java 8 functional style capabilities or a dedicated solution such as modelmapper.
He also mentioned Spring JCache support as a caching solution and this solution to the logging.

Spring RedisTemplate : use same key with multiple RedisTemplate to store different values

I am new to Redis and want to implement it with my existing spring application.
My question is to use different redisTemplate with same keys to store different types of values.
For e.g.
I have redisTemplate1 and redisTemplate2 beans defined in spring, like.
<bean id="redisTemplate1" class ="org.springframework.data.redis.core.RedisTemplate" p:connection-factory-ref ="connectionFactory" />
<bean id="redisTemplate2" class ="org.springframework.data.redis.core.RedisTemplate" p:connection-factory-ref ="connectionFactory" />
In java file to my service, I have created two different data structure using these two redis templates.
#Autowired
#Qualifier(value = "redisTemplate1")
private RedisTemplate<String, Student> redisTemplate1;
#Autowired
#Qualifier(value = "redisTemplate2")
private RedisTemplate<String, Address> redisTemplate2;
And, using following pattern to store data.
redisTemplate1.opsForHash().put("KEY1", student.getId(), student);
redisTemplate2.opsForHash().put("KEY1", address.getId(), address);
The case is, I have primary keys starting with 1 for each table. So 1 is there a primary key of Student as well as of Address.
I am using line below to get Student back from data-store.
(Student) redisTemplate1.opsForHash().get("KEY1", 1);
But, unfortunately it generates an exception.
java.lang.ClassCastException: com.redis.model.Address cannot be cast to com.redis.model.Student
So, my questions are,
Is it possible to use multiple redis templates ?
If yes, can I use same key (unique for each template) to store different types of data and access the same data stored using that template and key ?
If not, what are the alternative to perform same operation ?
Thanks in advance.
Actually Redis is a key/value store and if you use the same key for the same store you just override the old value with new one. And it doesn't matter how much RedisTemplates (or even connectionFactorys) you have, if the real Redis server is the same.
Now how to help you with your task:
You should have different kyes for different domain objects: e.g. students, addresses.
Since you are going to store domain objects with their own keys it looks like Map value is for you. I mean under key students a map of Students should be stored ,and the same for Addresses.
However you, actually, do it, but you use the same key for both domains.
So, the answer for you: that's because you are using the same Redis from both RedisTemplates.

Storing session data in controller

I'm new to Spring. I'm working on a MVC application that would works as follows:
1) user fills the form with data necessary to create the connection to some service
2) controller gets the data from input, create new object serviceManager and save this object e.g in some HashMap with serviceId
3) next time user wants to use this service, controller using serviceId reads data from HashMap.
So I simply need to store this HashMap throughout the whole session in my controller for future use. What would be the best way to accomplish that? Maybe creating serviceManager object each time and reading data from database is the proper solution? In my controller I'm already using #Autowired fields which perfectly serve the purpose, but they're defined in spring xml and I have to store the data dynamically.
Seems your requirement is kind of same with mine which I should keep the main data in the session and every time get the detail data from client and combine 2 kind of data to retrieve something from database. I just put the main part data in the session and then in the whole session that I can get it. I also try to use #SessionAttribute, but after tried dozens of time, I gave it up, it has a lots of problems. So if you can, I just recomment you to store the data in session, that's the samplest way.
I'm newish to spring myself, but as far as putting this in the session:
#Controller
#SessionAttributes({"myObject"})
public class MyController() {
...
#RequestMapping(value="/foo")
// Corrected as per Costi below
// public String someMethod(#PathVariable MyObject myObject) {
public String someMethod(#ModelAttribute MyObject myObject) {
...
}
}
#SessionAttributes will put a MyObject named myObject into the session, if it's not already there, and the #PathVariable pulls it down so you can use it in the method.
The curlys in session attributes aren't necessary for just one attribute, however, you can specify more than one, comma separated, when you use the array notation (which is to say: the curlys)

Resources