Search code examples
javaspringspring-bootentityfield

How to get Field Variable on Java Spring


I has a issue on my learn project, on case "if condition value is null and then else if condition value field is null" for example my code following these code :

For Entity Users.java :

@Entity
public class Users {
    private Long id;
    private String employeeId;
    private String fullName;
    private String username;
    private String password;
    ...

    public Users() {
    }

    Some Code Setter and Getter....
}

For Entity Employee.java :

@Entity
public Class Employee {
    private Long id;
    private String employeeId;
    private String fullName;
    ...
    
    public Employee() {
    }
    
    Some Code Setter and Getter....
}

and then for my Class Service i have case for insert data Employee with Repository. On case we have validation data before insert data to table Employee, we need to check table users not null and then on field employeeId should null. with my code following this :

For Repository UserRepo.java and EmployeeRepo.java :

@Repository
public interface EmployeeRepo extends CrudRepository<Employee, Long> {

}

@Repository
public interdace UsersRepo extends CrudRepository<Users, Long> {

@Transactional
@Modifying(clearAutomatically = true, flushAutomatically = true)
@Query("UPDATE Users u SET u.employeeId = :employeeId WHERE u.id = :id")
public void updateEmployeeIdUsers(@Param("id") Long id, @Param("employeeId") String employeeId);

}

For Service UsersService.java :

@Service("usersService")
public class UsersService {
    
    @Autowired
    private UsersRepo repo;
    
    public Optional<Users> findById(Long id) {
        return repo.findById(id);
    }
    
    public void updateEmployeeIdUsers(Long id, String employeeId) {
        repo.updateEmployeeIdUsers(id, employeeId);
    }

}

For Service EmployeeService.java :

@Service("employeeService")
public class EmployeeService {
    
    @Autowired
    private EmployeeRepo employeeRepo;
    
    @Autowired
    private UsersService userService;
    
    public Employee insertEmployee(Employee employee) throws Exception {
        Optional<Users> users = userService.findById(employee.getId());
        Users userOptional = new Users(); **//on this my problem**
        userOptional.getEmployeeId(); **//on this my problem**
        if (!users.isPresent()) {
            throw new Exception("User ID : "+ employee.getId() +" Not Founded");
        }else if (!(userOptional == null)) { **//on this my problem**
            throw new Exception("User employeID : "+ employee.getEmployeeId() +" Already Exist on Users");
        }
        
        String str1 = "TEST";
        Long idUser = employee.getId();
        userService.updateEmployeeIdUsers(idUser, str1);
        return employeeRepo.save(employee);
    }

}

on this code we have problem on else if userOptional is always NULL and i try to debug to see value on employeeId just i see always Null. so any idea with my problem because i try some case alway fail with my issue. please if any idea for my issue, can reply these my question. is very thank you of all about thing to answer my question.


Solution

  • For the proposed solution, I will assume the following:

    • There is relation between Employee and Users.
    • An Employee can be related with only one Users
    • username is the natural key of Users
    • employeeId is the natural key of Employee

    So the entities:

    @Entity
    public class Users {
    
      @Id
      // This one is an example, you can use the configuration you need
      @GeneratedValue(strategy = GenerationType.SEQUENCE, generator= "users_seq")
      @SequenceGenerator(name="users_seq", initialValue=1, allocationSize=1, sequenceName = "users_id_seq")
      private Long id;
    
      @Column(name = "fullname")
      private String fullName;
    
      // Probably this column should be unique and you need to configure in that way here and in your database
      @Column
      private String username;
    
      @Column
      private String password;
    
      // Getter & setter & constructors
    }
    
    
    
    @Entity
    public class Employee {
    
      @Id
      // This one is an example, you can use the configuration you need
      @GeneratedValue(strategy = GenerationType.SEQUENCE, generator= "employee_seq")
      @SequenceGenerator(name="employee_seq", initialValue=1, allocationSize=1, sequenceName = "employee_id_seq")
      private Long id;
    
      /**
       * Assuming this is your specific identifier for an employee (not related with database PK)
       *    If the assumption is correct, this column should be unique and you need to configure in
       * that way here and in your database
       */
      @Column(name = "employeeid")
      private String employeeId;
    
      /**
       * Not sure if this relation could be nullable or not
       */
      @OneToOne
      @JoinColumn(name = "users_id")
      private Users users;
    
      // Getter & setter & constructors
    }
    

    As you can see, there are no "repeated columns" in both entities and there is an unidirectional OneToOne relation between Employee and Users. If you need a bidirectional one, this link will help you with it: Bidirectional OneToOne

    The repositories:

    @Repository
    public interface UsersRepository extends CrudRepository<Users, Long> {
      Optional<Users> findByUsername(String username);
    }
    
    
    
    @Repository
    public interface EmployeeRepository extends CrudRepository<Employee, Long> {
      Optional<Employee> findByEmployeeId(String employeeId);
    }
    

    The services:

    @Service
    public class UsersService {
    
      @Autowired
      private UsersRepository repository;
    
      public Optional<Users> findByUsername(String username) {
        return Optional.ofNullable(username)
                .flatMap(repository::findByUsername);
      }
    
      public Optional<Users> save(Users user) {
        return Optional.ofNullable(user)
                .map(repository::save);
      }
    }
    
    
    
    @Service
    public class EmployeeService {
    
      @Autowired
      private EmployeeRepository repository;
    
      @Autowired
      private UsersService usersService;
    
      public Optional<Employee> insert(Employee newEmployee) {
        /**
         * The next line don't make sense:
         *
         *   Optional<Users> users = userService.findById(employee.getId());
         *
         * I mean:
         *
         *  1. Usually, id column is configured with @GeneratedValue and manage by database. So you don't need to ask
         *     if that value exists or not in Users.
         *
         *  2. Even if you are including id's values manually in both entities what should be "asked" is:
         *
         *    2.1 Is there any Users in database with the same username than newEmployee.users.username
         *    2.2 Is there any Employee in database with the same employeeId
         *
         *    Both ones, are the natural keys of your entities (and tables in database).
         */
        return Optional.ofNullable(newEmployee)
                .filter(newEmp -> null != newEmp.getUsers())
                .map(newEmp -> {
                    isNewEmployeeValid(newEmp);
    
                    // Required because newEmp.getUsers() is a new entity (taking into account the OneToOne relation)
                    usersService.save(newEmp.getUsers());
    
                    repository.save(newEmp);
                    return newEmp;
                });
      }
    
      private void isNewEmployeeValid(Employee newEmployee) {
        if (usersService.findByUsername(newEmployee.getUsers().getUsername()).isPresent()) {
            throw new RuntimeException("Username: "+ newEmployee.getUsers().getUsername() +" exists in database");
        }
        if (repository.findByEmployeeId(newEmployee.getEmployeeId()).isPresent()) {
            throw new RuntimeException("EmployeeId: "+ newEmployee.getEmployeeId() +" exists in database");
        }
      }
    }