Building my first api, running into a saveall error for type of 'something' and could not create query

111 Views Asked by At

I'm programming an API and when I run the program it runs but doesn't work. In the logs it says

No property 'saveAll' found for type 'UserModel'

and I'm also getting:

Could not create query for public abstract java.util.List org.springframework.data.jpa.repository.JpaRepository.saveAllAndFlush(java.lang.Iterable); Reason: No property 'saveAll' found for type 'UserModel'

So these errors have me stumped, I don't think I need to make a saveall in my repo, I thought that function came with the crud operations.

Here's my code, I'm going to keep looking online but if someone has seen this error before, I'd appreciate any and all help.

Here is my controller:

package com.vault.safe.MyController;

import com.vault.safe.CustomExceptions.UserNotFoundException;
import com.vault.safe.MyModel.UserModel;
import com.vault.safe.MyService.UserService;


import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;



import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.SQLException;

@RestController
@RequestMapping("/users")
public class UserController {

    private static final Logger logger = LoggerFactory.getLogger(UserController.class);


    private final UserService userService;

//*************************************************************************************
//Constructors, Getters, and Setters

    @Autowired
    public UserController(UserService userService){
        super();
        this.userService = userService;
    }

    public UserService getUserService(){
        return userService;
    }

//*************************************************************************************

    @GetMapping("/isConnected")
    public ResponseEntity<String> is_connected() {
        try {
            // Attempt to connect to the MySQL database
            DataSource dataSource = DataSourceBuilder.create()
                    .url("jdbc:mysql://127.0.0.1:3306/user_info")
                    .username("root")
                    .password("JunesDragon12")
                    .driverClassName("com.mysql.cj.jdbc.Driver")
                    .build();

            Connection connection = dataSource.getConnection();
            connection.close();

            return ResponseEntity.ok("Connected to the MySQL database.");
        } catch (SQLException e) {
            return ResponseEntity.ok("Not connected to the MySQL database.");
        }
    }





    @PostMapping("/add")
    public UserModel addUser(@RequestBody UserModel userModel){
        logger.info("Adding user: {}", userModel);
        UserModel addedUser = userService.addUser(userModel);
        logger.info("User added: {}", addedUser);
        return addedUser;
    }

    @GetMapping("/findById/{id}")
    public ResponseEntity<UserModel> getUserById(@PathVariable Long id){
        try{
            logger.info("Fetching user by ID: {}", id);
            UserModel user = userService.findById(id);
            logger.info("User found: {}", user);
            return ResponseEntity.ok(user);
        }catch(UserNotFoundException ex){
            logger.error("User not found with ID: {}", id);
            return ResponseEntity.notFound().build();
        }
    }
//    public UserModel findById(@PathVariable Long userId){
//        return userService.findById(userId);
//    }

    @PutMapping("/update/{userId}")
    public UserModel updateUser(@PathVariable Long userId, @RequestBody UserModel updatedUser) {
        logger.info("Updating user with ID: {}", userId);
        UserModel updatedUserModel = userService.updateUserInfo(userId, updatedUser);
        logger.info("User updated: {}", updatedUserModel);
        return updatedUserModel;
    }

    @DeleteMapping("/delete/{userId}")
    public void deleteUser(@PathVariable Long userId) {
        logger.info("Deleting user with ID: {}", userId);
        userService.deleteById(userId);
        logger.info("User deleted: {}", userId);
    }
}

Here is my repo:

package com.vault.safe.Repositories;

import java.util.Optional;
import com.vault.safe.MyModel.UserModel;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

@Repository
public interface UserRepository extends JpaRepository<UserModel, Long> {
    Optional<UserModel> findById(Long id);

    //Iterable<s> saveAll(Iterable<S> UserModel);
}

Here's my service:

package com.vault.safe.MyService;

import com.vault.safe.CustomExceptions.UserNotFoundException;
import com.vault.safe.MyModel.UserModel;
import com.vault.safe.Repositories.UserRepository;
import org.springframework.stereotype.Service;
import org.springframework.beans.factory.annotation.Autowired;


import java.util.Optional;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

@Service
public class UserService {

    private static final Logger logger = LoggerFactory.getLogger(UserService.class);

    private final UserRepository userRepository;

    @Autowired
    public UserService(UserRepository userRepository) {
        super();
        this.userRepository = userRepository;
    }

    public UserRepository getUserRepository(){
        return userRepository;
    }

//***********************************************************************************************************
    public UserModel addUser(UserModel user){
        logger.info("Adding user: {}", user);
        UserModel addedUser = userRepository.save(user);
        logger.info("User added: {}", addedUser);
        return addedUser;
    }


    public UserModel findById(Long id) {
        logger.info("Fetching user by ID: {}", id);
        Optional<UserModel> userOptional = userRepository.findById(id);
        if (userOptional.isPresent()) {
            UserModel user = userOptional.get();
            logger.info("User found: {}", user);
            return user;
        } else {
            logger.error("User not found with ID: {}", id);
            throw new UserNotFoundException("User not found with ID: " + id);
        }
    }

    public void deleteById(long userId){
        logger.info("Deleting user with ID: {}", userId);
        userRepository.deleteById(userId);
        logger.info("User deleted: {}", userId);
    }

    public UserModel updateUserInfo(Long userId, UserModel userModel){
        //Retrieve the user from the repository
        logger.info("Updating user with ID: {}", userId);
        Optional<UserModel> optionalUser = userRepository.findById(userId);

        // check if the user exists
        if(optionalUser.isPresent()){
            UserModel user = optionalUser.get();

            user.setUsername(userModel.getUsername());
            user.setEmail(userModel.getEmail());
            user.setFirstName(userModel.getFirstName());
            user.setLastName(userModel.getLastName());
            user.setAge(userModel.getAge());
            user.setStreet1(userModel.getStreet1());
            user.setStreet2(userModel.getStreet2());
            user.setCity(userModel.getCity());
            user.setState(userModel.getState());
            user.setCountry(userModel.getCountry());
            user.setZipcode(userModel.getZipcode());
            user.setPhone(userModel.getPhone());

            //Save the updates user
            UserModel updatedUser = userRepository.save(user);
            logger.info("User updated: {}", updatedUser);
            return updatedUser;

        } else {
            //Handle the case when the user does not exist
            logger.error("User not found with ID: {}", userId);
            throw new UserNotFoundException("User not found with ID: " + userId);
        }
    }
}

Here is my model:

package com.vault.safe.MyModel;


import javax.persistence.*;
import org.springframework.data.relational.core.mapping.Table;
import javax.persistence.Id;
@Entity
@Table(name = "users")
public class UserModel {

    @Id
    @Column(name = "id")
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private long id;

    @Column(name = "username", length = 50, nullable = false)
    private String username;

    @Column(name = "email", length = 100, nullable = false)
    private String email;

    @Column(name = "password", length = 255, nullable = false)
    private String password;

    @Column(name = "password2", length = 255, nullable = false)
    private String password2;

    @Column(name = "first_name", length = 50, nullable = false)
    private String firstName;

    @Column(name = "last_name", length = 50, nullable = false)
    private String lastName;

    @Column(name = "age")
    private Integer age;

    @Column(name = "street1", length = 100, nullable = false)
    private String street1;

    @Column(name = "street2", length = 100)
    private String street2;

    @Column(name = "city", length = 50, nullable = false)
    private String city;

    @Column(name = "state", length = 50, nullable = false)
    private String state;

    @Column(name = "country", length = 50, nullable = false)
    private String country;

    @Column(name = "zipcode", length = 10, nullable = false)
    private String zipcode;

    @Column(name = "phone", length = 10, nullable = false)
    private String phone;

    public UserModel() {
        // Default constructor
    }

    public UserModel(long id, String username, String email, String password, String password2, String firstName, String lastName, Integer age, String street1, String street2, String city, String state, String country, String zipcode, String phone) {
        this.id = id;
        this.username = username;
        this.email = email;
        this.password = password;
        this.password2 = password2;
        this.firstName = firstName;
        this.lastName = lastName;
        this.age = age;
        this.street1 = street1;
        this.street2 = street2;
        this.city = city;
        this.state = state;
        this.country = country;
        this.zipcode = zipcode;
        this.phone = phone;
    }

    public long getId() {
        return id;
    }

    public void setId(long id) {
        this.id = id;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public String getPassword2() {
        return password2;
    }

    public void setPassword2(String password2) {
        this.password2 = password2;
    }

    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;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    public String getStreet1() {
        return street1;
    }

    public void setStreet1(String street1) {
        this.street1 = street1;
    }

    public String getStreet2() {
        return street2;
    }

    public void setStreet2(String street2) {
        this.street2 = street2;
    }

    public String getCity() {
        return city;
    }

    public void setCity(String city) {
        this.city = city;
    }

    public String getState() {
        return state;
    }

    public void setState(String state) {
        this.state = state;
    }

    public String getCountry() {
        return country;
    }

    public void setCountry(String country) {
        this.country = country;
    }

    public String getZipcode() {
        return zipcode;
    }

    public void setZipcode(String zipcode) {
        this.zipcode = zipcode;
    }

    public String getPhone() {
        return phone;
    }

    public void setPhone(String phone) {
        this.phone = phone;
    }
}

Here is my build.gradle:

plugins {
    id 'java'
    id 'org.springframework.boot' version '3.2.0'
    id 'io.spring.dependency-management' version '1.1.0'
    id 'application'
}

group = 'com.vault'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '19'

application {
    mainClassName = 'com.vault.safe.DigitalVaultApplication'
}

repositories {
    mavenCentral()
}

ext {
    set('springCloudVersion', "2022.0.3")
}

dependencies {
    implementation 'org.springframework.boot:spring-boot-starter-data-jdbc'
    implementation 'org.springframework.boot:spring-boot-starter-jdbc'
    implementation 'org.springframework.boot:spring-boot-starter-web' // Added Web Starter
    implementation 'org.springframework.cloud:spring-cloud-starter-config'
    implementation 'org.springframework.cloud:spring-cloud-starter-gateway'
    implementation('org.springframework.boot:spring-boot-starter-data-jpa') {
        exclude group: 'org.springframework.boot', module: 'spring-boot-starter-web'
    }
    implementation 'mysql:mysql-connector-java:8.0.33'
    implementation 'javax.persistence:javax.persistence-api:2.2'
    implementation 'org.springframework.boot:spring-boot-starter-data-jpa'

    runtimeOnly 'com.mysql:mysql-connector-j'
    testImplementation 'org.springframework.boot:spring-boot-starter-test'
    developmentOnly 'org.springframework.boot:spring-boot-devtools'
}

dependencyManagement {
    imports {
        mavenBom "org.springframework.cloud:spring-cloud-dependencies:${springCloudVersion}"
    }
}
2

There are 2 best solutions below

2
Ruslan Zinovyev On

You don't need to provide any saveAll() implementation in your code if you are using JpaRepository

Say you have an Entity Car:

@Entity
public class Car {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private long id;

    private String model;

    // constructors, standard getters and setters
}

Here is your repository:

public interface CarRepository extends JpaRepository<Car, Long> {
}

Here is your usage:

List<Car> carList = new ArrayList<>();
for (int i = 0; i < carCount; i++) {
    carList.add(new Car ("model"));
}

carRepository.saveAll(carList);

What happens when you make this invocation?

userRepository.saveAll(Your list of Users);
0
AlefMemTav On

I'll help you improve your first API a little:

  1. Remove these methods from your repository: Optional<UserModel> findById(Long id) and Iterable<s> saveAll(Iterable<S> UserModel).

Your repository should look like this:

@Repository
public interface UserRepository extends JpaRepository<UserModel, Long> {
}

JpaRepository already has these methods.

(https://docs.spring.io/spring-data/jpa/docs/current/api/org/springframework/data/jpa/repository/JpaRepository.html)

  1. It is a safer and more manageable practice to configure database connection properties in the application.properties or application.yml file. This allows you to change database settings without modifying the source code:

application.properties:

# MySQL database configuration
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/user_info
spring.datasource.username=root
spring.datasource.password=JunesDragon12
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver

Now in your Controller:

method isConnected in the Controller:

@GetMapping("/isConnected")
public ResponseEntity<String> isConnected() {
      try {
            Connection connection = dataSource.getConnection();
             connection.close();
          return ResponseEntity.ok("Connected to the MySQL database.");
      } catch (SQLException e) {
        return ResponseEntity.ok("Not connected to the MySQL database.");
      }
 }
        
  1. You can simplify your code using functional programming. Their simplified methods look like this:

method findById in the Service:

public UserModel findById(Long id) {
    return userRepository.findById(id)
            .map(user -> {
                logger.info("User found: {}", user);
                return user;
            })
            .orElseThrow(() -> {
                logger.error("User not found with ID: {}", id);
                return new UserNotFoundException("User not found with ID: " + id);
            });
}

method getUserById in your Controller:

@GetMapping("/findById/{id}")
public ResponseEntity<UserModel> getUserById(@PathVariable Long id){
    logger.info("Fetching user by ID: {}", id);
    UserModel user = userService.findById(id);
    logger.info("User found: {}", user);
    return ResponseEntity.ok(user);
}

It works perfectly well because the exception is already caught and handled in your service method.