I have this repository:
public interface AccountsRepository extends CrudRepository<Account, Long> {
}
Then I have this service class:
public class AccountService {
private AccountsRepository accountsRepository;
public AccountService(AccountsRepository accountsRepository) {
this.accountsRepository = accountsRepository;
}
public Account createNewAccount() {
Account account = new Account();
account = tryStoreAccountElseRepeatWithDifferentIdentifier(account);
return account;
}
private Account tryStoreAccountElseRepeatWithDifferentIdentifier(Account account) {
account.setIdentifier(IdentifierGenerator.generateString(6));
try {
return accountsRepository.save(account);
} catch (DataIntegrityViolationException e) {
return tryStoreAccountElseRepeatWithDifferentIdentifier(account);
}
}
}
Unit test:
public class AccountServiceUnitTests {
AccountService fixture;
AccountsRepository mockAccountRespository;
@Before
public void setup() {
mockAccountRespository = mock(AccountsRepository.class);
fixture = new AccountService(mockAccountRespository);
}
@Test
public void repeatCreateAccountWhenIdentifierIsDuplicateValue() {
Account account = new Account();
account.setId(123L);
account.setIdentifier("ABCDEF");
when(mockAccountRespository.save(any(Account.class)))
.thenThrow(DataIntegrityViolationException.class)
.thenThrow(DataIntegrityViolationException.class)
.thenThrow(DataIntegrityViolationException.class)
.thenReturn(account);
Account newAccount = fixture.createNewAccount();
assertEquals(account, newAccount);
}
}
Entity:
@Entity
@Table(name = "accounts")
public class Account {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "id")
private Long id;
@Column(name = "identifier", unique = true)
private String identifier;
@Column(name = "username", unique = true)
private String username;
// getter, setter shortened
}
Thing is, I want to store a new Account into the database. Some columns have index UNIQUE. So when you try to insert data MySQL throws an exception if there is a DUPLICATE value.
Since the save(Entitiy)
method does not throw a documented exception I tried what would happen and saw that a DataIntegrityViolationException
is thrown in case I try to add duplicate value.
So my idea was basically try recursively to insert a new row till no exception is thrown. See: tryStoreAccountElseRepeatWithDifferentIdentifier
Is this way of checking for duplicate value good practise? Or is there a "built-in" solution I don't know?