При создании обычного CRUD контроллера разработчик обычно делает несколько вещей.

  1. Создает Entity

  2. Пишет миграцию в БД

  3. Создает DTO для Entity

  4. Создает слой Repository

  5. Создает слой Service

  6. Создает слой Controller

Многие из этих вещей можно сделать автоматически с помощью ChatGPT. И так сразу к делу, и посмотрим на что способен ChatGPT. В качестве Entity будем использовать простой класс.

@Entity
@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor
@FieldDefaults(level = AccessLevel.PRIVATE)
public class Client {

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

  /**
   * Имя клиента
   */
  String firstName;

  /**
   * Фамилия клиента
   */
  String lastName;

  /**
   * Номер телефона клиента
   */
  String phoneNumber;

  /**
   * Айди в кейклоке для зарегистрированных клиентов, пустое поле для незарегистрированных
   */
  UUID keycloakId;

  /**
   * Филиал, к которому относится клиент
   */
  @ManyToOne(fetch = FetchType.LAZY)
  Place place;

}

Мы создали простой Entity, дальше мы будем пытаться через Chat GPT создать все остальные слои логики. Для этой Entity. В формате "Цитат" я буду писать какие запросы я отправляю в ChatGPT, и в формате кода это ответы от этой потрясающей технологии.

И так начнем...

Сделай из этого Java класса DTO

public class ClientDTO {
   private String firstName;
   private String lastName;
   private String phoneNumber;
   private UUID keycloakId;
   private LocalDate createdDate;

   public ClientDTO(String firstName, String lastName, String phoneNumber, UUID keycloakId, LocalDate createdDate) {
      this.firstName = firstName;
      this.lastName = lastName;
      this.phoneNumber = phoneNumber;
      this.keycloakId = keycloakId;
      this.createdDate = createdDate;
   }

   public String getFirstName() {
      return firstName;
   }

   public void setFirstName(String firstName) {
      this.firstName = firstName;
   }

   public String getLastName() {
      return lastName;
   }

   public void setLastName(String lastName) {
      this.lastName = lastName;
   }

   public String getPhoneNumber() {
      return phoneNumber;
   }

   public void setPhoneNumber(String phoneNumber) {
      this.phoneNumber = phoneNumber;
   }

   public UUID getKeycloakId() {
      return keycloakId;
   }

   public void setKeycloakId(UUID keycloakId) {
      this.keycloakId = keycloakId;
   }

   public LocalDate getCreatedDate() {
      return createdDate;
   }

   public void setCreatedDate(LocalDate createdDate) {
      this.createdDate = createdDate;
   }
}

Очень не плохо, но не хватает Lombok-a

Добавь в этот класс Lombok

@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor
public class ClientDTO {
   private String firstName;
   private String lastName;
   private String phoneNumber;
   private UUID keycloakId;
   private LocalDate createdDate;
}

Уверен если попросить GPT сразу сгенерировать класс с Lombok, то он это сделает. Но я ведь не уточнял, что надо сгенерировать именно с Lombok.

Даже нейронная сеть понимает что без четкого ТЗ результат ХЗ

Сделай из Entity CRUD репозиторий

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

@Repository
public interface ClientRepository extends JpaRepository<Client, Long> {

}

Сделай из Entity CRUD Service, со следующими методами:
1. Получение пагинированного списка
2. Получение по ID
3. Удаление по ID
4. Создание новой записи

@Service
public class ClientService {

  private final ClientRepository clientRepository;

  @Autowired
  public ClientService(ClientRepository clientRepository) {
    this.clientRepository = clientRepository;
  }

  public Page<Client> getAllClients(Pageable pageable) {
    return clientRepository.findAll(pageable);
  }

  public Optional<Client> getClientById(UUID id) {
    return clientRepository.findById(id);
  }

  public void deleteClientById(UUID id) {
    clientRepository.deleteById(id);
  }

  public Client createClient(Client client) {
    return clientRepository.save(client);
  }
}

Сделай из Entity миграцию в Postgresql

CREATE TABLE Client (
  id SERIAL PRIMARY KEY,
  first_name VARCHAR(255) NOT NULL,
  last_name VARCHAR(255) NOT NULL,
  phone_number VARCHAR(255) NOT NULL,
  keycloak_id UUID NOT NULL,
  place_id INTEGER NOT NULL,
  FOREIGN KEY (place_id) REFERENCES Place(id)
);

Сгенерируй из этой DTO:

@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor
public class ClientDTO {
private String firstName;
private String lastName;
private String phoneNumber;
private UUID keycloakId;
private LocalDate createdDate;
}

JSON формат с Mock данными

{
   "firstName": "John",
   "lastName": "Doe",
   "phoneNumber": "1234567890",
   "keycloakId": "1b7f00c9-2aaf-4c28-a7b8-aeb0c7dfc8f0",
   "createdDate": "2022-01-01"
}
Хочу отметить что он дал дельные замечания касательно UUID

Напиши Unit тесты на этот класс

Ответ от Chat GPT

import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.verify;

import java.util.Arrays;
import java.util.Optional;
import java.util.UUID;

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;

@RunWith(MockitoJUnitRunner.class)
public class ClientServiceTest {

  @Mock
  private ClientRepository clientRepository;

  private ClientService clientService;

  @Before
  public void setUp() {
    clientService = new ClientService(clientRepository);
  }

  @Test
  public void getAllClients_shouldReturnAllClients() {
    // given
    Client client1 = new Client();
    client1.setId(UUID.randomUUID());
    client1.setFirstName("John");
    client1.setLastName("Doe");

    Client client2 = new Client();
    client2.setId(UUID.randomUUID());
    client2.setFirstName("Jane");
    client2.setLastName("Doe");

    Page<Client> clientsPage = new PageImpl<>(Arrays.asList(client1, client2));
    Pageable pageable = PageRequest.of(0, 10);

    doReturn(clientsPage).when(clientRepository).findAll(any(Pageable.class));

    // when
    Page<Client> result = clientService.getAllClients(pageable);

    // then
    assertThat(result.getTotalElements()).isEqualTo(2);
    assertThat(result.getContent().get(0).getFirstName()).isEqualTo("John");
    assertThat(result.getContent().get(1).getFirstName()).isEqualTo("Jane");
  }

  @Test
  public void getClientById_shouldReturnClient() {
    // given
    UUID id = UUID.randomUUID();

    Client client = new Client();
    client.setId(id);
    client.setFirstName("John");
    client.setLastName("Doe");

    doReturn(Optional.of(client)).when(clientRepository).findById(id);

    // when
    Optional<Client> result = clientService.getClientById(id);

    // then
    assertThat(result.isPresent()).isTrue();
    assertThat(result.get().getFirstName()).isEqualTo("John");
    assertThat(result.get().getLastName()).isEqualTo("Doe");

К сожалению тесты он часто не заканчивает.... И тесты которые он пишет довольно сомнительного качества.

Вывод. Chat GPT инструмент который уже сейчас, может помочь программисту в повседневной работе, ускоряя его работу. Это полезный инструмент который позволит немного экономить время на создании новых классов.

Это не тот инструмент на который можно положиться на 100%. Есть страхи что Junior разработчики будут бездумно использовать его. Но если вы опытный программист, то вам достаточно сделать пару запросов в ChatGPT получить от него ответы, провести Code Review, поправить косяки и использовать его код в работе.