Reputation: 2076
I have a Spring Batch application (https://spring.io/projects/spring-batch) that reads comma delimited data from a .csv file and then maps each column to specific Java class beans, the saves it to a database (postgres). My problem is that one of the date/time columns, called END_DT is writing to the database with an incorrect time portion of the date/time. You can see the date part is correctly read (2023-04-15) but the time is just written as 00:00:00.000000
The steps it performs a little more in-depth are:
dd-mmm-YYYY HH:mm:ss
(i.e. 29-Apr-2099 23:59:59) is parsed out using this method:private String getDateTimeString(String dateString) {
SimpleDateFormat sdfTo = new SimpleDateFormat("dd-MMM-yyyy HH:mm:ss");
SimpleDateFormat sdfFrom = new SimpleDateFormat("dd-MMM-yyyy HH:mm:ss");
String formattedDateTimeStr = null;
if (StringUtils.isNotEmpty(dateString)) {
formattedDateTimeStr = sdfTo.format(sdfFrom.parse(dateString));
}
return formattedDateTimeStr;
}
@Entity
@Table(name = "blah_blah_blah", schema = "some_schema", catalog = "some_catalog")
// code inbetween
public class MyRandomClassEntity {
private Timestamp endDt;
// more stuff
}
I know the date/time String is parsed correctly in the DaMasterRecord data class, because I can see it in the debugger. It's right after the Mapper interface method "mapper" is called in the Dozer framework that I see the wrong date/time listed in the Entity class via the debugger. So I'm not exactly sure how Dozer is doing it's mappings, but I'm guessing when Dozer goes to map the String that is "dd-mmm-YYYY HH:mm:ss" to a java.sql.Timestamp datatype, for some reason it doesn't map the "time" portion of the date/time String correctly (it just does 00:00:00.000000). Does anyone know how to fix this? There are a lot interfaces and overriden methods, so I haven't quite pinpointed where this mapping is happening.
Upvotes: 1
Views: 987
Reputation: 2076
I was able to solve this issue and will post my answer here. I would also like to state this is a legacy application (not too old actually) but its using classes like "Timestamp" and "SimpleDateFormat" (pre-Java 8 API updates), so my intent was to solve this issue/bug/question with minimal effort and not having to re-write the application. Hopefully, this can be of use to any other developers who have a similar application/business issue.
DozerConverter<String, LocalDateTime>
class to create my own custom converter for this String -> LocalDateTime object.
However, I ran into issues with Dozer throwing exceptions trying to map the LocalDateTime object -> java.sql.Timestamp data type that our database column uses. We have another repo with all the database configurations, so again, I didn't want to have to go into that dependency and edit code (which could potentially break more components as they are dependent on it), so I trashed idea for the time.When you use a custom converted like this, Dozer has an .xml (in your resources directory) file that you will have to attach this converter to the specific field you are trying to map, something like:
<field custom-converter="com.mydomainname.my.namespace.MyCustomConverter">
<a>theColumnNameIamMappingFrom</a>
<b>theColumnNameIamMappingTo</b>
</field>
I also tried keeping the format of the DateTime String as "yyyy-MM-dd HH:mm:ss", which is the format of the Timestamp. However, everytime it mapped over to my database/Entity class, it always "cut" the time portion to 00:00:00.000000 for some reason.
So last solution was a variation of the 1st, where I created a custom converter but this time had it convert to the java.sql.Timestamp
data type. I was trying to avoid using these old legacy classes but other parts of the code seems too tightly-coupled to it and I didn't want to break everything. Anyway, it worked and I was finally able to see the DB save the timestamp as a full date and time i.e.
2020-08-31 23:59:59.123456
Hopefully this helps anyone else out if they have similiar issues. Dozer is kind of weird, but you can read more about it here: https://www.baeldung.com/dozer
Upvotes: 0