The below data is stored in MongoDB. I am using Spring-Data and storing the data into mongoDB.
If I want to retrieve the fields ("id" or "Name") I can able to do, but if I want to retrieve the sub fields ("firstName" or "lastName")I can't.
(eg.)If I want to retrieve sub field "lastName" from the below data I can't.Can anyone help me in this regards.
Thanks in advance.
Data Stored in MongoDB:
{
"id":101,
"name": {"firstName":"Mark",
"lastName":"Antony"
}
}
The Code I am using is:
PersonService.java
public List<Audit> searchPerson(Audit audit)
{
List<NameDetails> name=audit.getName();
return mongoTemplate.find(new Query(Criteria.where("name.lastName").is(name.get(0))), Audit.class,COLLECTION_NAME);
}
PersonController.java
#RequestMapping(value = "/person/search", method = RequestMethod.GET)
public String search(#ModelAttribute Audit audit, ModelMap model) {
model.addAttribute("personList", personService.searchPerson(audit));
return "output";
}
Audit.java
#Document
public class Audit {
#Id
private String id;
private List<NameDetails> name;
public String getId() {
System.out.println("Person: getId");
return id;
}
public void setId(String id) {
System.out.println("Person: setId");
this.id = id;
}
public List<NameDetails> getName() {
System.out.println("Audit: getName");
return name;
}
public void setName(List<NameDetails> name) {
System.out.println("Audit: setName");
this.name = name;
}
}
NameDetails.java
package com.register.mongo.model;
public class NameDetails {
private String firstName;
private String lastName;
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
System.out.println("NameDetails: setFirstName");
this.firstName = firstName;
}
public String getLastName() {
System.out.println("NameDetails: getLastName");
return lastName;
}
public void setLastName(String lastName) {
System.out.println("NameDetails: setLastName");
this.lastName = lastName;
}
}
(output.jsp)UI Page
<table border="2">
<c:forEach var="person" items="${personList}">
<tr>
<td>${person.id}</td>
</tr>
<tr>
<td>${person.lastName}</td>
</tr>
</c:forEach>
</table>
If i understand well, you should make an extra class and use it in the Audit class
public class NameDetails{
private String FirstName;
private String LastName;
public String getFirstName() {
return id;
}
public void seFirstName(String fisrtName) {
this.FirstName= fisrtName;
}
public String getLastName() {
return LastName;
}
public void setLastName(String LastName) {
this.LastName = LastName;
}
}
and use this class in the Audit.class
#Document
public class Audit {
#Id
private String id;
private List name<NameDetails>;
and then the setters and getters
Related
I converted UUID to string (String id) and put the conversion inside a method.
I also declared other String variables such as FirstName etc and put in on an ArrayList:
Code
The code does work. But I'm confused why the string email was showing second on the list.
public class StudentController {
#Autowired
StudentService studentService = new StudentService();
#GetMapping
public List<Student> displayStudent(){
return studentService.getStudent();
}
}
public class StudentService {
Student student = new Student();
private List<Student> studentList = Arrays.asList(
new Student(student.genID(),"Elvis" , "Presley" ,"Elvis#gmail.com")
);
public List<Student> getStudent(){
return studentList;
}
}
public class Student {
UUID uuid = UUID.randomUUID();
private String id;
private String FirstName;
private String LastName;
private String email;
public Student() {}
//Method Converting UUID into string
public String genID(){
id = uuid.toString();
return id;
}
public Student(String id) {
this.id = id;
}
public Student(String id, String firstName, String lastName, String email) {
this.id = id;
FirstName = firstName;
LastName = lastName;
this.email = email;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getFirstName() {
return FirstName;
}
public void setFirstName(String firstName) {
FirstName = firstName;
}
public String getLastName() {
return LastName;
}
public void setLastName(String lastName) {
LastName = lastName;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
}
Expected
I expected data to be in this order
ID , FirstName , LastName , email
Actual Output JSON
JSON is an unordered collection, as specified on https://www.json.org/json-en.html , so you don't have to worry about it. It might depend on library though.
Specify the serialized order of properties
The order of properties during serialization can be defined in Jackson.
Either at class-level specifically using annotation #JsonPropertyOrder.
Or globally for your ObjectMapper using a feature:
objectMapper.configure(MapperFeature.SORT_PROPERTIES_ALPHABETICALLY, true)
Example
In your case you can achieve expected order using the annotation on your class:
#JsonPropertyOrder({'id', 'firstName', 'lastName', 'email'})
public class Student {
// body of your class
}
Or separately with an index on your fields:
public class Student {
#JsonProperty(index=10)
private String id;
// not ordered specifically
private String firstName;
private String lastName;
#JsonProperty(index=20)
private String email;
// remainder of your class
}
See also
Jackson ObjectMapper - specify serialization order of object properties
Order of JSON objects using Jackson's ObjectMapper
Jackson JSON - Using #JsonPropertyOrder annotation to define serialized properties ordering
I am trying to find a specific object. I'm using the following code, but it seem like get only sends back a Boolean that verifies that there is a key with this name, but not an array of Boolean values that I need to use in my program:
private Map<User, ArrayList<Boolean>> userDayOfVacationMap;
public ArrayList<Boolean> getUserVacationList(User key){
return this.userDayOfVacationMap.get(key);
}
Is there a method for this?
Here is the User object:
#Entity
public class User {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
private String firstName;
private String lastName;
#OneToMany(mappedBy="user", cascade = CascadeType.ALL)
public Set<Vacation> vacations;
public User(String firstName, String lastName) {
this.firstName=firstName;
this.lastName=lastName;
}
public User(){}
public Set<Vacation> getVacations() {
return vacations;
}
public void setId(int id){
this.id = id;
}
public Integer getId(){
return this.id;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
}
However, I can't add a variable in this function, because it would add non-useful information into my database.
I am trying to learn spring data elasticsearch, and created a sample project. Right now, I am trying to get familiar with the mechanics of sorting.
Simply put, I have a Person class, that has a firstName and lastName field. I am trying to sort on the lastNameField.
Here is my Person class:
#Document(indexName = "entities", type = "person", shards=1, replicas=0)
public class Person {
#Id
private String id;
#Field(type=FieldType.String, index=FieldIndex.not_analyzed)
private String firstName;
#Field(type=FieldType.String, index=FieldIndex.not_analyzed)
private String lastName;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
}
Here is my DAO logic:
#Override
public Page<Person> getPeople(int pageNumber, int pageSize, Direction direction, String...sortFields) {
return personRepository.findAll(new PageRequest(pageNumber, pageSize, direction, sortFields));
}
The personRepository is an empty interface that extends PagingAndSortingRepository
And the actual call:
int pageSize = 1;
int currentPageNumber = -1;
boolean morePages = true;
while(morePages){
Page<Person> results = personDataHandler.getPeople(currentPageNumber+1, pageSize, Direction.DESC, "firstName");
List<Person> people = results.getContent();
if(!CollectionUtils.isEmpty(people)){
for(Person currentPerson: people){
System.out.println("[firstName: "+currentPerson.getFirstName()+", lastName: "+currentPerson.getLastName()+"]");
}
}
currentPageNumber++;
morePages = results.hasNext();
}
Could having a page size of 1 be the issue?
I am using Spring boot and trying to implement many to many relationship between User and Skill. I have a table users_skills with columns user_id and skill_id. I keep getting "JoinColumn cannot be resolved to a type" error in #JoinColumn annotations in STS when trying to implement the relationship. Below is my User class
#Entity
#Table(name = "users")
public class User {
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
private long id;
private String email;
private String firstName;
private String lastName;
private List<Skill> skills = new ArrayList<Skill>();
protected User() {}
public User(String email,String firstName, String lastName) {
this.email = email;
this.firstName = firstName;
this.lastName = lastName;
}
public Long getId() {
return this.id;
}
public void setId(Long id) {
this.id = id ;
}
public String getEmail() {
return this.email;
}
public void setEmail(String email) {
this.email = email ;
}
public String getFirstName() {
return this.firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName ;
}
public String getLastName() {
return this.lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName ;
}
#ManyToMany
#JoinTable(name="users_skills",
joinColumns={#JoinColumn(name="user_id")},
inverseJoinColumns={#JoinColumn(name="skill_id")})
public List<Skill> getSkills(){
return skills;
}
public void setSkills(List<Skill> skills) {
this.skills = skills ;
}
}
Just write this at the head of your class
import javax.persistence.JoinColumn;
Sometime eclipse doesn't show the link to import it in context menu, but it's there. Hope it will help someone.
I can't seem to get my form to bind to the checkboxes control. I read many posts on here and tried a few techniques but no luck. Maybe a fresh set of eyes will help.
my controller:
public String editAccount(#RequestParam("id") String id, Model model) {
model.addAttribute("account", accountService.getAccount(id));
model.addAttribute("allRoles", roleService.getRoles());
return EDIT_ACCOUNT;
}
my jsp:
<form:form action="" modelAttribute="account">
<form:checkboxes items="${allRoles}" path="roles" itemLabel="name" itemValue="id" delimiter="<br/>"/>
</form>
the generated html:
<span><input id="roles1" name="roles" type="checkbox" value="1"/><label for="roles1">User</label></span><span><br/><input id="roles2" name="roles" type="checkbox" value="2"/><label for="roles2">Admin</label></span><span><br/><input id="roles3" name="roles" type="checkbox" value="3"/><label for="roles3">SuperAdmin</label></span<input type="hidden" name="_roles" value="on"/>
I used a second for each loop (not shown) to make sure that the model object contained the roles. It does, yet none of the checkboxes are checked and when I submit the roles object is always empty. Can someone please tell me what I'm missing?
Thanks
EDIT
Sorry just realized it might be helpful to see the account and role objects:
public class Account {
private String username, firstName, lastName, email;
private List<Role> roles;
#NotNull
#Size(min = 1, max = 50)
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
#NotNull
#Size(min = 1, max = 50)
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
#NotNull
#Size(min = 1, max = 50)
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
#NotNull
#Size(min = 6, max = 50)
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public List<Role> getRoles() {
return roles;
}
public void setRoles(List<Role> roles) {
this.roles = roles;
}
public String toString() {
return ReflectionToStringBuilder.toString(this);
}
}
public class Role {
private int id;
private String name;
public Role() {}
public Role(int id, String name) {
this.id = id;
this.name = name;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
#NotNull
#Size(min = 1, max = 50)
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
EDIT #2
Controller Post Method
#RequestMapping(value = "edit", method = RequestMethod.POST)
public String updateAccount(#RequestParam("id") String id, #ModelAttribute("account") #Valid AccountEditForm form, BindingResult result) {
System.out.println("FORM VALUES AFTER: " + form);
return (result.hasErrors() ? EDIT_ACCOUNT : ACCOUNT_REDIRECT);
}
AccountEditForm is the form backing object. When I do a GET I grab an Account object and pass the values into an AccountEditForm before displaying the screen. I will attach the AccountEditForm just for clarity. It is very similiar to the account object. I just happened to seperate my form objects from my model objects.
public class AccountEditForm {
private String username, firstName, lastName, email;
private List<Role> roles = new ArrayList<Role>();
#NotNull
#Size(min = 1, max = 50)
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
#NotNull
#Size(min = 1, max = 50)
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
#NotNull
#Size(min = 1, max = 50)
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
#NotNull
#Size(min = 6, max = 50)
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public List<Role> getRoles() {
return roles;
}
public void setRoles(List<Role> roles) {
this.roles = roles;
}
public String toString() {
return ReflectionToStringBuilder.toString(this);
}
}
EDIT #3 Role Property Editor
public class RolePropertyEditor extends PropertyEditorSupport {
private Map<Integer, Role> roleMap = new HashMap<Integer, Role>();
public RolePropertyEditor(List<Role> roleList) {
for (Role r : roleList) roleMap.put(r.getId(), r);
}
public void setAsText(String incomingId) {
Role role = roleMap.get(incomingId);
System.out.println("PROPERTY EDITOR ROLE " + role);
setValue(role);
}
public String getAsText() {
System.out.println("PROPERTY EDITOR ID " + ((Role)getValue()).getId());
return String.valueOf(((Role)getValue()).getId());
}
}
Defined in my controller like:
#InitBinder
public void initBinder(WebDataBinder binder) {
binder.setAllowedFields(new String[] {
"username", "password", "confirmPassword", "firstName", "lastName", "email", "acceptTerms", "currentPassword"
});
binder.registerCustomEditor(Role.class, new RolePropertyEditor(roleService.getRoles()));
}
EDIT #4 NEW ProeprtyEditor
public class SecurityRolePropertyEditor extends PropertyEditorSupport {
private RoleService roleService;
public SecurityRolePropertyEditor(RoleService roleService) {
this.roleService = roleService;
}
public void setAsText(final String name) {
Role role = roleService.getRoleByName(name);
setValue(role);
}
}
Add an equals method to your Roles entity.
see this answer (Spring MVC Pre Populate Checkboxes): of a similar question for more details.
It seems you are missing implementation equals and hashCode method on your entities.