andrew17
andrew17

Reputation: 925

How to use CommandLineRunner in Spring Boot?

I try to set data to database by CommandLineRunner interface.

If I remove everything about bank instance and save account with null list of banks, it saves data to database.

Bean class with CommandLineRunner:

@Override
    public void run(String... args) throws Exception {
        List<Bank> banks = new ArrayList<>();
        Bank bank = new Bank("Приват Банк", 5000.0f);
        Bank bank2 = new Bank("UkrsibBank", 3000.1f);
        banks.add(bank);
        banks.add(bank2);
        bankAccountRepository.save(bank);
        bankAccountRepository.save(bank2);
        Account account = new Account(15000.2f, 1200.5f,  banks);
        accountRepository.save(account);
    }

My entities:

@Entity
@Data
@NoArgsConstructor
public class Account {

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

    @Column(name = "total_balance")
    private float totalBalance;

    private float cash;

    @OneToMany(cascade = CascadeType.ALL)
    @JoinTable(name = "account_banks", joinColumns = @JoinColumn(name = "account_id"),
            inverseJoinColumns = @JoinColumn(name = "bank_id") )
    private List<Bank> banks;

    public Account(float totalBalance, float cash, List<Bank> banks) {
        this.totalBalance = totalBalance;
        this.cash = cash;
        this.banks = banks;
    }
}
@Entity
@Data
@NoArgsConstructor
public class Bank implements Serializable {

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

    private String name;
    @Column(name = "account_balance")
    private float balance;

    public Bank(String name, float balance) {
        this.name = name;
        this.balance = balance;
    }
}

What is my mistake? Stacktrace:

java.lang.IllegalStateException: Failed to execute CommandLineRunner
Caused by: org.springframework.dao.InvalidDataAccessApiUsageException: detached entity passed to persist: 
Caused by: org.hibernate.PersistentObjectException: detached entity passed to persist:

Upvotes: 1

Views: 871

Answers (1)

Anthony
Anthony

Reputation: 621

You set cascade type for this relation as cascade = CascadeType.ALL When you call accountRepository.save(account) Hibernate tries to persist its related entities (Banks), but before that, you manually saved them yet(after that they are in detached state). This causes an error. I think there are three possible solutions for this:

  • Remove cascade strategy at all if you want to persist your entities independently.
  • Persist Bank entities transitively with Account
Bank bank = new Bank("Приват Банк", 5000.0f);
        Bank bank2 = new Bank("UkrsibBank", 3000.1f);
        banks.add(bank);
        banks.add(bank2);
        Account account = new Account(15000.2f, 1200.5f,  banks);
        accountRepository.save(account);
  • Decorate method run with @Transactional annotation to guarantee your entities to be in persistent state

Upvotes: 1

Related Questions