(Spring) When using PUT method, #CreationTimestamp fails - spring

I have this API that uses #CreationTimestamp to auto-generate the date when any information is added to the database, and it works. The problem is, when i use the PUT method in a specific information of the database, the generated Date disappears.
This is how things are structured:
...
#Temporal(TemporalType.TIMESTAMP)
#Column(name = "CreationDate", length = 29)
#CreationTimestamp
private Date CreationDate;
...
This is how my PUT method is:
#PutMapping("/SomeURL/{id}")
#ResponseBody
public User editUser(#RequestBody #Valid User T, #PathVariable Integer id) {
return userRepository.save(T);
}
When I use this, the generated Date from the #CreationTimestamp disappears, and that field becomes blank (null).
Why is this happening?
OBS: I dont think is necessary, but this is my POST method:
#PostMapping("/someURL")
public User addUser(#RequestBody #Valid User T) {
return userRepository.save(T);
}

The creation date will be updated when calling save method within your editUser method. The entity possibly does not contain this value, therefore null will be set as updated value. (you can try to debug this to check)
Change the column annotation as followed:
#Column(name = "CreationDate", length = 29, nullable = false, updatable = false)
This should prevent the once created date to be updated.
HTH

Related

Set input field attribute in Thymeleaf from database

I have a table in the database with fields like below which holds my form input's attributes:
#Column(name = "propertyname")
private String propertyname;
#Column(name = "propertyvalue")
private String propertyvalue;
#Column(name = "propertytype")
private String propertytype;
#Column(name = "propertyrequired")
private String propertyrequired;
#Column(name = "propertysize")
private String propertysize;
#Column(name = "propertymin")
private String propertymin;
Now I am getting these as bean fields in Thymeleaf template. But keep getting template parsing error (on the same line as below). I am trying to achieve below:
<input th:field="${modelAttribute.beanPropertyList[__${rowStat.index}__].propertyname}" th:errorclass="is-invalid" th:required="${modelAttribute.beanPropertyList[__${rowStat.index}__].propertyrequired}" th:min="${modelAttribute.beanPropertyList[__${rowStat.index}__].propertymin}" th:max="${modelAttribute.beanPropertyList[__${rowStat.index}__].propertymax}"/>
What am I doing wrong? or what is the correct approach for this?
th:field doesn't work like that. It requires a th:object="${foo} as a form backing bean. Then th:field="*{bar}" will set the input's name="bar" and try to reflect on the model object called foo and get its field call bar to use the input's value
Try th:name and th:value separately. That also seems more plausible given your model.

#Valid for long data type is not working for mandatory check

I have the below input class and when i trigger the api without 'interactionId' param in the input,
I expect validation error message "interactionId cannot be empty" but the validation passes through which i guess could be due to the fact that interactionId has a default value of 0.
Can someone pls. help to enforce this validation on the 'long' parameter when its not given in input?
with #NotEmpty for the customerId param, its working as expected. Using #NotEmpty for the long param "interactionId" is throwing a different error that #notempty cannot be used for long.
public class Input {
#NotEmpty(message = "customerId cannot be empty")
private String customerId;
#Valid
#NotNull(message = "interactionId cannot be empty")
private long interactionId;
// setters and getters
}
my controller class:
#RestController
public class Controller {
#PostMapping(value="/detailed-customer-transaction", produces =
MediaType.APPLICATION_JSON_VALUE)
#ResponseBody
public ResponseEntity<Object> detailTransactions(#Valid #RequestBody Input
params)
{
return new ResponseEntity<>(Dao.detailTransactions(params), HttpStatus.OK);
}
Above issues is resolved after changing to Long instead of long.
Query #2
I need another help. I have a String input param which takes date-time format in below format. Given its a string parameter, how can i validate for the pattern="yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"
long should be Long, because long is a primary type in java, not an object, so Long is an object that can be checked whether it is null

Transient and Persistent fields not being sent to JSP page

When sending an Object to a JSP page the persistent and transient fields are left out. I can see on the Java side these variables are filled in with data, but once it gets to the JSP page some of the values are missing, specifically every field that is not mapped to a column.
Group Entity
#Entity
#Table(name="groups")
#XmlRootElement
public class Groups {
#Id
#GeneratedValue(strategy=GenerationType.SEQUENCE,generator="groupsSeqGen")
//TODO: I dont think H2 is having the sequences auto generated. Need to add these manually.
#SequenceGenerator(name="groupsSeqGen",sequenceName="groups_sequence", initialValue = 10, allocationSize = 100)
private Long id;
#Column(name="name")
private String name;
#Column(name="create_date")
private Date createDate;
#Column(name="owner_user")
private String ownerUser;
#Column(name="is_public")
private Boolean isPublic;
#Column(name="description")
private String description;
#OneToMany(fetch = FetchType.EAGER, mappedBy = "ownerGroup")
private List<Books> books;
}
Request Mapping
#RequestMapping("/Mygroups")
public ModelAndView getMyGroup() {
ModelAndView mav=new ModelAndView();
mav.addObject("groups", appservice.findMyGroups()); //This returns the groups!
mav.setViewName("myGroups");
return mav;
}
My JSP page can read the groups. Just for an idea here is the console output when I print the object.
Groups [id=1, name=Club 1, createDate=2019-08-01 00:00:00.0, description=Club 1 desc, isPublic=true, ownerUser=user1]
What i've tried.
Adding #transient and #XMLTransient tags.
Joining columns differently.
Changing the Fetch type (This doesnt matter im just changing random things at this point)
The other Odd Part is when I write to the object with a form I can set these fields fine! Maybe its because Javascript is just setting the fields regardless of if it matches and when Java reads it in when it does match it works correctly?
I'm an idiot....
It didn't show up in my JavaScript console output because I skipped adding it to the ToString in my Groups class. Once I added it there. I realized I was just referencing it incorrectly in JavaScript.I think I was referencing it as "books" instead of "group.books" and didn't realize because I was printing the object and it wasn't there.

Bulk data to find exists or not : Spring Data JPA

I get an Post request that would give me a List<PersonApi> Objects
class PersonApi {
private String name;
private String age;
private String pincode ;
}
And I have an Entity Object named Person
#Entity
#Table(name = "person_master")
public class Person{
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
Long id;
#Column(name = "name")
String name;
#Column(name = "age")
String age;
#Column(name = "pincode ")
String pincode ;
}
My record from Post request would look something like this (pseudocode representation of the data below)
[
"Arun","33","09876gh"
"James","34","8765468"
]
I need to do a bulk-validation using Spring JPA.. Give the List<PersonApi> and get a True or False based on the condition that all the entries in the PersonApi objects list should be there in the database.
How to do this ?
The selected answer is not a right one. (not always right)
You are selecting the whole database to check for existence. Unless your use case is very special, i.e. table is very small, this will kill the performance.
The proper way may start from issuing repository.existsById(id) for each Person, if you never delete the persons, you can even apply some caching on top of it.
exists
Pseudo Code:
List<PersonApi> personsApiList = ...; //from request
List<Person> result = personRepository.findAll();
in your service class you can access your repository to fetch all database entities and check if your list of personapi's is completeley available.
boolean allEntriesExist = result.stream().allMatch(person -> personsApiList.contains(createPersonApiFromPerson(person)));
public PersonApi createPersonApiFromPerson(Person person){
return new PersonApi(person.getName(), person.getAge(), person.getPincode());
}

How can I include or exclude a record according to a boolean parameter using Spring Data JPA?

I am not so into Spring Data JPA and I have the following doubt about how to implement a simple query.
I have this AccomodationMedia entity class mapping the accomodation_media on my database:
#Entity
#Table(name = "accomodation_media")
public class AccomodationMedia {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id")
private Long id;
#Column(name = "id_accomodation")
private Long idAccomodation;
#Column(name = "is_master")
private boolean isMaster;
#Lob
#Column(name = "media")
private byte[] media;
private String description;
private Date time_stamp;
public AccomodationMedia() {
}
...............................................................
...............................................................
...............................................................
// GETTER AND SETTER METHODS
...............................................................
...............................................................
...............................................................
}
The instance of this class represents the photo associated to an accomodation (an hotel)
So as you can see in the prvious code snippet I have this field :
#Column(name = "id_accomodation")
private Long idAccomodation;
that contains the id of an accomodation (the id of an hotel on my database).
I also have this boolean field that specify if an image is the master image or not:
#Column(name = "is_master")
private boolean isMaster;
So, at this time, in my repository class I have this method that should return all the images associated to a specific hotel:
#Repository
public interface AccomodationMediaDAO extends JpaRepository<AccomodationMedia, Long> {
List<AccomodationMedia> findByIdAccomodation(Long accomodationId);
}
I want to modify this method passing also the boolean parameter that specify if have to be returned also the master image or only the images that are not master.
So I tryied doing in this way:
List<AccomodationMedia> findByIdAccomodationAndIsMaster(Long accomodationId, boolean isMaster);
but this is not correct because setting to true the isMaster parameter it will return only the master image (because it is first selecting all the Accomodation having a specific accomodation ID and then the one that have the isMaster field setted as true).
So, how can I correctly create this query that use the isMaster boolean parameter to include or exclude the AccomodationMedia instance that represent my master image?
I know that I can use also native SQL or HQL to do it but I prefer do it using the "query creation from method names"
I don't have how to test this, but essentially your final query should be:
id_accomodation = ?1 AND (is_master = ?2 OR is_master = false)
So I would try the following method signature:
findByIdAccomodationAndIsMasterOrIsMasterFalse(Long accomodationId, boolean isMaster);
I would go with two methods one for isMaster true, while second for false value like this:
List<AccomodationMedia> findByIdAccomodationAndIsMasterFalse(Long accomodationId);
List<AccomodationMedia> findByIdAccomodationAndIsMasterTrue(Long accomodationId);
Change your acommodation id as accomodationId instead of idAccomodation. When you write findByIdAccomodationAndIsMaster spring confusing findByIdAccomodationAndIsMaster
Try this this convention
#Column(name = "accomodation_id")
private Long accomodationId;

Resources