I want to post like this :
[{
"employeeid": "1111",
"employeename": "YOA"
},
{
"employeeid": "2222",
"employeename": "OYA"
}]
My controller like this :
#PostMapping("/api/employee/save")
public Employee createEmployee(#Valid #RequestBody List<Employee> employee) {
return employeeService.save(employee);
}
Model :
#Entity
#Table(name="EMPLOYEE")
public class Employee implements Serializable{
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "ID")
int id;
#Column(name = "EMP_ID")
int employeeid;
#Column(name = "EMPLOYEE_NAME")
String employeename;
//GETTER AND SETTER
}
When i post data, The error I get is the following:
{
"timestamp": "2018-07-13T03:36:25.898+0000",
"status": 500,
"error": "Internal Server Error",
"message": "Invalid property 'id' of bean class [java.util.ArrayList]: Could not find field for property during fallback access!",
"path": "/api/employee/save"
}
Service :
public interface employeeService{
Employee save(List<Employee> employee);
}
Service Imp :
#Service("employeeService")
public class EmployeeServiceImpl implements EmployeeService {
#Autowired
EmployeeRepository employeeRepository;
#Override
public Employee save(List<Employee> employee) {
return employeeRepository.save(employee);
}
}
Repository:
public interface EmployeeRepository extends Repository <Employee, Long>
Employee save(List<Employee> employee);
}
The error description is this:
Invalid property 'id' of bean class [java.util.ArrayList]: Could not find field for property during fallback access!
when using saveAll(), I Get Error message : No property saveAll found for type Employee
is there anyone who can help me ?
I have modified my question.
Regards,
Me
Problem is in this line
public Employee createEmployee(#Valid #RequestBody List<Employee> employee) {
return employeeService.save(employee); // Problem
}
employeeService.save can take only one Object of Entity in your case Employee
There are 2 ways
1.
public Boolean createEmployee(#Valid #RequestBody List<Employee> lstEmployee) {
try{
for(Employee emp : lstEmployee){
employeeService.save(employee);
}
return true;
}catch(Exception e){}
return false;
}
2.
Use saveAll instead
public Employee createEmployee(#Valid #RequestBody List<Employee> employee) {
return employeeService.saveAll(employee);
}
Edit 1:
After adding service class it looks like you are manually implementing so
Option 1:
I would suggest you directly use EmployeeRepository in your controller class.
As by manually overriding there methods you are not actually
enjoying benefit of using Repository
#Autowired
EmployeeRepository employeeRepository;
#PostMapping("/api/employee/save")
public Employee createEmployee(#Valid #RequestBody List<Employee> lstEmployee) {
return employeeRepository.saveAll(lstEmployee);
}
Option 2:
Longer way, change your implementation like this. There might be some error for Object but it should give you an idea
public interface employeeService{
Employee save(Employee employee);
public <S extends User> List<S> saveAll(Iterable<S> entites);
}
#Service("employeeService")
public class EmployeeServiceImpl implements EmployeeService {
#Autowired
EmployeeRepository employeeRepository;
#Override
public Employee save(Employee employee) {
return employeeRepository.save(employee);
}
#Override
public List<Employee> saveAll(List<Employee> employee) {
return employeeRepository.saveAll(employee);
}
}
I assume you're using spring-data-jpa repository. Let know if it is otherwise. You're trying to use the save api which only saves one entity. What you need is saveAll() which saves all the given entity. Please read the documentation.
https://docs.spring.io/spring-data/commons/docs/current/api/org/springframework/data/repository/CrudRepository.html#saveAll-java.lang.Iterable-
Edit: Updated answer to save all records
The save method will return all the employees so change the type to List<Employees>
public interface EmployeeRepository extends Repository <Employee, Long>
List<Employee> saveAll(List<Employee> employee);
}
Even better use one of the pre-supplied interfaces for simple CRUD operations for example CrudRepository. It reduces the boilerplate code that you may have write.
https://docs.spring.io/spring-data/jpa/docs/current/reference/html/#repositories
public interface EmployeeRepository extends CrudRepository <Employee, Long>
}
Related
I'm running into a failure, but I can't figure out why. For a simple test, I want to quickly create a RESTful API to accept a JSON and convert it to an object (POJO).
Restcontroller:
#RestController
public class RESTController {
#Autowired
AuthorService authorService;
#RequestMapping(value = "/setsAuthor", headers = "Accept=application/json", method=RequestMethod.POST)
public void addAuthor(#RequestBody Author author){
authorService.addAuthor(author);
}
}
Data object:
#AllArgsConstructor
#Entity
#NoArgsConstructor
public class Author {
#Id
private Integer id;
private String authorName;
}
Service:
#Service
public class AuthorService {
#Autowired
AuthorRepository authorRepository;
public void addAuthor(Author author) {
try {
authorRepository.save(author);
} catch (IllegalAccessError e) {
System.out.println("cant save Author: " + author + " to Respository");
}
}
Repository interface:
public interface AuthorRepository extends CrudRepository<Author, Integer> {
}
Post Request at
http://localhost:8080/setsAuthor
With JSON:
{
"id": 1,
"authorName": "SomeAuthor"
}
I also tried to wrap the Items in the JSON in a "Author" :{}
The RestController won't map my JSON to the object. It always says id = null, authorName = null when I debug the program.
What am I doing wrong? I remember it always worked this way.
Add #Getter and #Setter to entity
#AllArgsConstructor
#Entity
#NoArgsConstructor
#Getter
#Setter
public class Author {
You can also use
#AllArgsConstructor(onConstructor = #__(#JsonCreator))
instead of #Setter
I'm using Neo4j to create graphs. The below codes is an example for spring data Neo4j. I can save a node entity when no id property value is provided.
But how to save a node entiry with a specific id property value?
Model Class:
#Data
#NodeEntity
public class Person {
#Id
#GeneratedValue
private Long id;
private String name;
private String title;
#Relationship(type = "ACTED_IN")
private List<Movie> movies = new ArrayList<>();
}
Repository Class
public interface PersonRepository extends Neo4jRepository<Person, Long> {
#Query("MATCH (n:Person {name:{name}}) RETURN n")
List<Person> findByName(#Param("name") String name);
}
Controller Class
#RestController
#RequestMapping("/person")
public class PersonController {
#Autowired
private PersonRepository personRepository;
#PostMapping("/save")
public Map save(#RequestBody Person person) {
Map resultMap = new HashMap();
String code = "200";
String msg = "success";
// It can save success when no id property value is provided
Person savedPerson = personRepository.save(person);
resultMap.put("code", code);
resultMap.put("msg", msg);
resultMap.put("data", savedPerson);
return resultMap;
}
}
I have tried it successfully and can be easily done provide the "id" should be
String not Long
Domain/DAO class:
#Id
#GeneratedValue(strategy = Neo4JCustomIdStrategy.class)
String id;
Repository Class:
#Repository
public interface PersonRepository extends Neo4jRepository<Person, String>{
}
And lastly, custom implementation of Strategy:
public class Neo4JCustomIdStrategy implements IdStrategy {
#Override
public Object generateId(Object entity) {
return String.valueOf(entity.hashCode());
}
}
The library I am using is spring-data-neo4j
I want to return a JSON Object with information from two different Classes.
Like I want the username from the class User and the rolename from the Class Role together in one JSON Object.
My current code:
#Entity
#DynamicUpdate
public class User {
private String username;
private String phone;
private String email;
private Set<Role> role;
}
#Entity
public class Role {
private int idRole;
private String name;
}
#Projection(name = "CustomUser", types = {User.class})
public interface CustomUser {
String getUsername();
RoleTest getRole();
interface RoleTest {
String getName();
}
}
#Repository
public interface UserRepository extends JpaRepository<User, Integer> {
List<CustomUser> findAllBy();
}
#Controller
#RequestMapping
public class UserController {
#Autowired
private UserRepository userRepository;
#GetMapping
#ResponseStatus(HttpStatus.ACCEPTED)
public #ResponseBody List<CustomUser> getAllUsers() {
return userRepository.findAllBy();
}
}
What I currently get:
{
"role": {
"name": "ADMIN"
},
"username": "test"
}
However, my goal is it to get something like this:
{
"role": "ADMIN",
"username": "test"
}
If you are using the Jackson library, please check #JsonUnwrapped. The documentation is here
The problem here is that #JsonUnwrapped doesn't work with the Collections. As you indicated in one of your comments if the Role need not be a set, this will solve your problem.
If you have questions on why the #JsonUnwrapped doesn't work with the Collcetions, this will help to understand further.
I think you could simply do the following.
#Projection(name = "CustomUser", types = {User.class})
public interface CustomUser {
String getUsername();
#Value("#{target.getRoles(0).getName()}")
String getRole();
}
You're getting the role -> name structure because RoleTest is an interface and it might have multiple values.
i have problem with saving data in DB.I'm new in Spring Boot. When i run my program the result of writen data is: packagename#randomcode example:com.abc.patient.Patient#6e3e681e
This is my Entity class - Patient.java
#Entity
public class Patient {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
private String name;
// getter, setter, constructor, etc
}
This is my CrudRepo PatientRepository.java
public interface PatientRepository extends CrudRepository<Patient,Integer> {
}
This is my Service class PatientService.java
#Service
public class PatientService {
#Autowired
private PatientRepository patientRepository;
public void savePatient (String name) {
Patient patient = new Patient(name);
patientRepository.save(patient);
}
public Optional<Patient> showPatient(int id) {
return patientRepository.findById(id);
}
public List<Patient> showAllPatients() {
List<Patient> patients = new ArrayList<>();
patientRepository.findAll().forEach(patients::add);
return patients;
}
}
I think that problem in in the savePatient method in this line:
Patient patients = new Patient(name);
I checked the "name" parameter and it's in 100% correct String. I'm using Derby DB.
The only problem you have is how you are printing out your Patient class. Define a proper toString() or just debug yourself to see the resulting fields. There is no problem in your JPA implementation.
See this question for the details of default toString
Try:
public void savePatient(Patient patient) {
patientRepository.save(patient);
}
In Spring, CrudRepository findAll() operation working good for fetching data from the database but with the same configuration in case of saving, update & delete it's not working.
EmployeeService.java
#Service
public class EmployeeService {
#Autowired
private EmployeeRepo employeeRepoI;
#Transactional
public List<Employee> getAllEmployee() {
return (List<Employee>) employeeRepoI.findAll();
}
#Transactional
public Employee getEmployee(int id) {
return (Employee) employeeRepoI.findOne(id);
}
#Transactional
public Employee addEmployee(Employee employee) {
return (Employee) employeeRepoI.save(employee);
}
#Transactional
public Employee updateEmployee(Employee employee) {
return (Employee) employeeRepoI.save(employee);
}
#Transactional
public void deleteEmployee(int id) {
employeeRepoI.delete(id);
}
}
EmployeeRapo.java
#Repository
public interface EmployeeRepo<T, ID extends Serializable> extends CrudRepository<Employee, Long> {
List<Employee> findAll();
}
As pointed out by #Sergey Your EmployeeRepo has a wrong definition there
Try this
#Repository
public interface EmployeeRepo extends CrudRepository<Employee, Long> {
List<Employee> findAll();
}
Also your deleteEmployee() method takes an int while it should take Long as a parameter.
#Transactional
public void deleteEmployee(Long id) {
employeeRepoI.delete(id);
}
You have CrudRepository with Long type and deleteEmployee with primitive int. This values should match.