2

I have a problem when I want save repository by foreach loop . By Foreach loop user come and save it to another entity

User.class

public class Attendance {

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

private String status;

@ManyToOne(cascade = {CascadeType.MERGE,CascadeType.PERSIST,CascadeType.REFRESH,CascadeType.DETACH})
@JoinColumn(name="user_id", nullable=false)
private User user;

}

User.class This is user class of User Entity

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

private String username;

@OneToMany(mappedBy = "user",cascade = CascadeType.ALL)
@JsonIgnore
private List<Attendance> attendances;

Error show :: java.lang.StackOverflowError: null

@Scheduled(initialDelay = 10000,fixedDelay = 30000)
public void insertHolidaysAttendance() throws Exception {

    Calendar c1 = Calendar.getInstance();

    if ((c1.get(Calendar.DAY_OF_WEEK) == Calendar.SATURDAY)  || (c1.get(Calendar.DAY_OF_WEEK) == Calendar.MONDAY)) {

        List<User> userList = userService.fetchUserList();

        List<Attendance> attendanceList = new ArrayList<>();

        for (User user: userList){
            Attendance attendance = new Attendance();

            System.out.println("Curent user "+user);
            attendance.setStatus("WEEKEND");
            attendance.setUser(user);
            attendanceList.add(attendance);
        }

        System.out.println("Attendance List "+attendanceList+"\n");

         attendanceRepository.saveAll(attendanceList);
         userList.clear();
         attendanceList.clear();

    } else {
        System.out.println("Today is working Day");

    }

}
Bulbul Ahmed
  • 84
  • 1
  • 11
  • Can you please post the stacktrace and tell us on which line you get the StackOverflowError? – Simon Martinelli Jun 14 '21 at 06:24
  • @SimonMartinelli First Time save the data in database Attendance table perfectly, As it is scheduler when it run second time its shows the error stackoverflow null> its not show the specific line – Bulbul Ahmed Jun 14 '21 at 06:26
  • 1
    Is this a reproducible error? What's the user list size like? a million? – Rahul SK Jun 14 '21 at 06:30
  • @RahulSK userlist size only 10 – Bulbul Ahmed Jun 14 '21 at 06:36
  • What is the implementation ```userService.fetchUserList``` doing. Can you provide some details to it? – KnockingHeads Jun 14 '21 at 06:49
  • share the content of your object attendance/user plz. Maybe the devil is inside the toString implementation – CodeScale Jun 14 '21 at 07:53
  • You can also try increasing the value of -Xss parameter as -Xss128m or something larger to be sure if there is actually something in your code that is causing stackoverflow error, which definitely is there. But, with that you might get more than one scheduled execution of your code, or, maybe this may solve your pupose completely considering that these are scheduled executions and the next execution is running only after the first is finished, which leaves only one choice to try increasing your stack size while running it. – KnockingHeads Jun 14 '21 at 07:56
  • @Ashish@Override public List fetchUserList() { return userRepository.findAll(); } – Bulbul Ahmed Jun 14 '21 at 07:58
  • @CodeScale Entity Data NoArgsConstructor AllArgsConstructor Builder Table(name = "users") public class User implements UserDetails { Id GeneratedValue(strategy = GenerationType.AUTO) private Long id; private String username; OneToMany(mappedBy = "user",cascade = CascadeType.ALL) JsonIgnore private List attendances; – Bulbul Ahmed Jun 14 '21 at 08:04
  • @CodeScale ManyToOne(cascade = {CascadeType.MERGE,CascadeType.PERSIST,CascadeType.REFRESH,CascadeType.DETACH}) JoinColumn(name="user_id", nullable=false) private User user; – Bulbul Ahmed Jun 14 '21 at 08:04
  • @BdBulbul please move these definitions into the question part. It is not readable – CodeScale Jun 14 '21 at 08:06
  • do you have @data annotation on user class ? if yes does user has a relation to attendance type ? – CodeScale Jun 14 '21 at 08:22
  • @CodeScale adding Yes I use Lombok Data – Bulbul Ahmed Jun 14 '21 at 08:26
  • do you have @data on both types ? code is uncomplete – CodeScale Jun 14 '21 at 08:27
  • @CodeScale yes I use – Bulbul Ahmed Jun 14 '21 at 08:27

1 Answers1

6

Mixing what I saw in your code and what you said in comments I found the guilty.

  • the trigger line : System.out.println("Attendance List "+attendanceList+"\n");
  • the cause : @Data

This annotation will add a toString implementation on your objects and by default it prints all the non static fields... causing infinite cyclic calls because attendance tries to print user then user tries to print attendance and again attendance tries to print user... you're looping forever.

Either add the annotation @ToString.Exclude on one of the 2 relationships or re-write toString implementation by yourself.

Always take care on code generation frameworks like Lombok. It could give you some nasty surprises ;-)

CodeScale
  • 3,046
  • 1
  • 12
  • 20
  • I would go a step further and say: You shouldn't use @Data with JPA because it may lead to StackOverFlow errors and more important the generated equals() and hashCode() do not meet Hibernate's requirements https://vladmihalcea.com/how-to-implement-equals-and-hashcode-using-the-jpa-entity-identifier/ – Simon Martinelli Jun 14 '21 at 08:34
  • You saved me a lot of time; thank you! – Vinod Liyanage Mar 26 '23 at 15:33