0

I am very new to Spring boot and this is my first spring dummy project where I'm trying to learn to save an array of objects in mysql-db.

Actually, I am trying to use the saveAll method from the crudRepository in my controller. But it's giving me an error no instance(s) of type variable(s) S exist so that Iterable<S> conforms to List<User>

My JSON looks like this:

[
    {
        "first_name": "Jack",
        "last_name": "Jill",
        "email": "jacjill@gmail.com",
        "password": "passq3623"
    },
    {
        "first_name": "John",
        "last_name": "Doe",
        "email": "john@gmail.com",
        "password": "pass23"
    }
]

This is my entity class

package com.example.testbatch.Entities;

import javax.persistence.*;

@Entity
@Table(name = "user")
public class UserEntity {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    public int id;
    public String first_name;
    public String last_name;
    public String email;
    public String password;
}

Here is my User Model Class

package com.example.testbatch.Models;

public class User {
    public int id;
    public String firstName;
    public String lastName;
    public String email;
    public String password;
}

Here is my repository

package com.example.testbatch.Repositories;

import com.example.testbatch.Entities.UserEntity;
import org.springframework.data.repository.CrudRepository;

import java.util.List;

public interface UserRepository extends CrudRepository<UserEntity, Integer> {
    @Override
    List<UserEntity> findAll();

}

and here is my rest controller

package com.example.testbatch.Controllers;

import com.example.testbatch.Entities.UserEntity;
import com.example.testbatch.Models.User;
import com.example.testbatch.Repositories.UserRepository;
import org.apache.poi.ss.formula.functions.T;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import javax.transaction.Transactional;
import java.util.ArrayList;
import java.util.List;

@RestController
@RequestMapping("/api/v1/user")
public class UserController {

    @Autowired
    UserRepository userRepository;



    @PostMapping("/register")
    public void saveUsers(@RequestBody UserEntity userEntity) {
        List<User> persistedUser = userRepository.saveAll(List.of(userEntity));
    }


}

Can anyone please help me? This is ery first time I am usig spring boot

user9824674
  • 493
  • 1
  • 14
  • 28
  • `userRepository.saveAll(List.of(userEntity))` returns a list of type `UserEntity` and not `User`. You would need to map `UserEntity` to `User`, or just not care about the result. This depends on what you want to do with the data after saving – XtremeBaumer Apr 28 '22 at 08:46
  • @XtremeBaumer Actually I just want to save this list to DB and return just a string "ok" as a response. Can you please please tell me how to save this list to db? I have no idea as of now :'( – user9824674 Apr 28 '22 at 09:05
  • Remove `List persistedUser =` and you are good to go. For the response, wrap the `saveAll` call in a `try-catch`. If you catch any exception, then the save failed, otherwise it was successful – XtremeBaumer Apr 28 '22 at 09:07
  • @XtremeBaumer Hi I just tried as you suggested but it's giving me an error ```Inferred type 'S' for type parameter 'S' is not within its bound; should extend 'com.example.testbatch.Entities.UserEntity'``` Am I still missing something? – user9824674 Apr 28 '22 at 09:10
  • Are you sure it happens on the `userRepository.saveAll(List.of(userEntity));` call? I found this which has the same error as you: https://stackoverflow.com/questions/52634362/inferred-type-s-for-type-parameter-s-is-not-within-its-bound-should-extend – XtremeBaumer Apr 28 '22 at 09:20

2 Answers2

1

The user_repo is returning a List of type UserEntity while in yout controller you are asking for a List of type User

There is not mapping between UserEntity and User.

1

You have some problems about your code:

At first you have a DTO (User class), so, you should use this DTO inside your controller in saveUsers method and more importantly you pass an array of objects in your JSON, so you have to use a List not an Object as the parameter:

public void saveUsers(@RequestBody List<User> users) {...}

Another problem is you don't have any getters and setters inside you DTO (public class User) and Entity (public class UserEntity) classes and also you have to add a method inside your DTO class for mapping DTO to Entity:

public class User {
    ...
    public static UserEntity dtoToEntity(User user){
        UserEntity userEntity = new UserEntity();
        userEntity.setEmail(user.getEmail());
        userEntity.setPassword(user.getPassword());
        userEntity.setFirst_name(user.getFirstName());
        userEntity.setLast_name(user.getLastName());
        return userEntity;
    }
}

Also you must change your JSON properties to match your DTO's properties:

[
    {
        "firstName": "Jack",
        "lastName": "Jill",
        ...
    },
    ...
]

As the last one, change your controller saveUsers method as (saveAll method return Iterable not List):

@PostMapping("/register")
public void saveUsers(@RequestBody List<User> users) {

    List<UserEntity> userEntities = new ArrayList<>();

    for (User user : users) {
        userEntities.add(dtoToEntity(user));
    }

    Iterable<UserEntity> persistedUser = userRepository.saveAll(userEntities);
}

Notice: As a point remember that because you have auto-generated id inside your Entity, so you don't need id property for your DTO, obviously because it's auto-generated and you don't need to get it from input;

Mehdi Rahimi
  • 1,453
  • 5
  • 20
  • 31