How to get child's primary key id when saving data using @OneToMany relationship in spring boot

Viewed 38

User

public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id", nullable = false)
    private Long id;

    @Column(name = "email", nullable = false, unique = true)
    private String email;

    @OneToMany(mappedBy = "user", cascade = CascadeType.ALL)
    private List<Project> projects = new ArrayList<>();
}

Project

public class Project {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id", nullable = false)
    private Long id;

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

    @ManyToOne(fetch = FetchType.LAZY, optional = false)
    @JoinColumn(name = "user_id", nullable = false)
    private User user;
}

Service method while creating new project for given user:

@Override
@Transactional(rollbackFor = Exception.class)
public ProjectResponseDTO createProject(Long userId, CreateProjectRequestDTO projectRequestDTO) {
    Optional<User> userOptional = userRepository.findById(userId);
    if (userOptional.isEmpty()) {
        throw new ResourceNotFoundException(String.format("user with id %s does not exist", userId));
    }
    User user = userOptional.get();
    Project project = new Project().setName(projectRequestDTO.getName());
    user.getProjects().add(project);
    userRepository.save(user);
    return new ProjectResponseDTO()
            .setProjectId(project.getId()) // This is still null
            .setUserId(project.getUser().getId())
            .setProjectName(project.getName());
}

This is adding a new project for the given user. I want to return generated primary key id (project id) in the response. In this case it's returning null.

If I saved it using projectRepository.save(project); it would work, but that would defeat the purpose of creating parent-child relationship between User and Project.

I am using PostgreSQL.

How do I get the project id?

1 Answers

The save() method in JPA returns the object if the transaction is successful and you are not storing the results of the userRepository.save(user); at the moment. so what you can do is something like this.

User result = userRepository.save(user);
Project latestProject = result.getProjects()
  .stream()
  .filter(project -> projectRequestDTO.getName().equals(project.getName())) // filter the appropriate element
  .findAny()
  .orElse(null);

This will return the project object with the generated ID which you can then map to your response DTO.

Related