AMP API REST COM

62280 ワード

ESSE Artigo Fai Elaboradoエム馬Epapaデdesafioは、processo seletivo para o programamaオレンジ才能da ZUPをします.
Tarefa Aquiはdesformver em formatoデartigo、estiloのブログのポスト、sobreのum projeto emの春を好む.
パウロのパスフォイについてlottery-orange-talents

文脈


Passoは、passo利用をパラシュートで降下させます.
API Deverは、Gerar N - Strae Meros Aleatはriosパラシュートで降下します.Aposta Do Soleliante、Cada Nは、Mero DeveエスターAssociadoに電子メールパラIdentificar A Pessoa que est conconrendoです.
Essentalmenteは、2つのエンドポイント、umレイバーo o電子メールDA Pessoa e Retornar - Comのために、o o ' jeto de resposta com s n n ' s meros sorteadosパラシュートで降下します.
Javaを使用して、春+ HibernateのJavaを実行します.

を実装する


モデル


パラシュートは、クラス、relacionamentosなどとしてdescrevendoをします.
NIESE Contexto , DREOS UML Mesclando Modelagem Connitual COM Modelagem L - Don GICA
Entidadesとしての信憑性は、システマティックである
GICA = EndDadesとしてのDESCRVE , relacionamentos e determina umパラダイムcomo poo , relacionalなど;

ジェラードAは、スプリングブーツをAplica


Pierinino o Projeto、IREE利用者は、Segintesとして春初期のInitiizr comを作ります
  • マヴェンcomo gerenciadorデは、NCIASに入ります;
  • Verは2.2.4.2春を行う
  • ジャバ11
  • E adicionarei Aは、NCIA春ウェブパラシュートで降下しているウェブパラシュートで降下しているウェブパラシュートで降下します.
    o pom .XML Infincial Ficar - Per - assim :
    <parent>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-parent</artifactId>
      <version>2.4.2</version>
      <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.armandotdelcol</groupId>
    <artifactId>lottery-api</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>lottery-api</name>
    <description>Desafio Orange Talents</description>
    <properties>
      <java.version>11</java.version>
    </properties>
    <dependencies>
      <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
      </dependency>
    </dependencies>
    
    <build>
      <plugins>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
        </plugin>
      </plugins>
    </build>
    

    カマダラパナド


    パラエサAplicaは、Padrによって、padrを得ます.

    としての


    Penote実体をentidadesとしてのCriareiは、アンドペリエンドデッドロッターyチケットを来ます.
    EndDades SerがOとして、Aを使用してください、そして、Pera isso、Ire Preisar Adicionar UMA formaはProjto春Foozer O Mapeamento Dasクラスをします.
    <研究ノート> Java Persistence APIとしてのJava e - queの実装について
    Euossistema Spring MuitoはHibernateを利用していません、Basta Adicionar Umaは、nncia e o o maven ira fazer oをダウンロードします.
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-jpa</artifactId>
    </dependency>
    
    ESAは、JPA API、Implenta Splireo o JPA com Hibernate como Default、JDBC E outras BityNotecas Necess Leu riasにNCIA inclui iを依存させます.
    コモンド・デ・ダドス第二次世界大戦におけるイェーク・デ・ダドスのカルデドゥ・エ・メム・トゥ・ラ・エム・プン・ドゥ・エクスタルについて
    パラUtilizar o H 2、EISは、DepedされたNCIA a ser adicionadaなしpomです.XML :
    <dependency>
        <groupId>com.h2database</groupId>
        <artifactId>h2</artifactId>
        <scope>runtime</scope>
    </dependency>
    

    宝くじ


    @Entity
    @Table(name = "tb_lottery_tickets")
    public class LotteryTicket implements Serializable {
    
        private static final long serialVersionUID = 1L;
    
        @Id
        @GeneratedValue(strategy = GenerationType.IDENTITY)
        private Long id;
    
        @Column(nullable = false)
        private Integer bet1;
    
        @Column(nullable = false)
        private Integer bet2;
    
        @Column(nullable = false)
        private Integer bet3;
    
        @Column(nullable = false)
        private Integer bet4;
    
        @Column(columnDefinition = "TIMESTAMP WITHOUT TIME ZONE")
        private Instant createdAt;
    
        public LotteryTicket() {
        }
    
        public LotteryTicket(Long id, Integer bet1, Integer bet2, Integer bet3, Integer bet4) {
            this.id = id;
            this.bet1 = bet1;
            this.bet2 = bet2;
            this.bet3 = bet3;
            this.bet4 = bet4;
        }
    
        // OMITIDO AQUI OS GETTERS AND SETTERS DE id, bet1, bet2, bet3 e bet4.
    
        public Instant getCreatedAt() {
            return createdAt;
        }
    
        @PrePersist
        public void prePersist() {
            createdAt = Instant.now();
        }
    
        @Override
        public boolean equals(Object o) {
            if (this == o) return true;
            if (o == null || getClass() != o.getClass()) return false;
            LotteryTicket that = (LotteryTicket) o;
            return Objects.equals(id, that.id);
        }
    
        @Override
        public int hashCode() {
            return Objects.hash(id);
        }
    }
    
    Abstratei anotaは、o @ @エンティティda jpa para indicar queを分類します.
    E @ GeneratedValue para Definir a Chave Privia Autoincrementav { l }、@列para - Inpuzar o nullable = false e n - no o Aceitar valores nulos ...
    パラオは、o o campo createdat利用して、インスタントeを定義します.

    ベター


    @Entity
    @Table(name = "tb_bettors")
    public class Bettor implements Serializable {
    
        private static final long serialVersionUID = 1L;
    
        @Id
        @GeneratedValue(strategy = GenerationType.IDENTITY)
        private Long id;
    
        @Column(nullable = false)
        private String email;
    
        public Bettor() {
        }
    
        public Bettor(Long id, String email) {
            this.id = id;
            this.email = email;
        }
    
        // OMITINDO GETTERS AND SETTERS E HASHCODE E EQUALS
    }
    

    アソシア


    AdionareiエムLotteryチケットAは、NCIAパラシュートで降下する人Bettor com Aを見つけます@ anoytoone e @ JoinColumnパラシュートで降下してください
    @ManyToOne
    @JoinColumn(name = "bettor_id", nullable = false)
    private Bettor bettor;
    
    ConsiutorタミールMジュントAosデミエAributosを経たAdicionando OS devidosゲッターとセッターe Colocandoパラinstanciar.
    Jは、bettor adicioneiをanotaにしますo o @ onetomany com aオペ
    @OneToMany(mappedBy="bettor")
    private Set<LotteryTicket> lotteryTickets;
    
    Nemse Coco comoは、セットをセットしました、nは、iを形容します.

    Verificando a a a a a a a a a no o o o o o o bd h 2


    Nesa Pr ' s Xia etapa IREE HAVILLAR A CRIA AREM AUM MATM AND TAL DAS Tabelas e fazer Algunts Testes Savvando Alguns Registros NAS Tabelas
    Primeiro irei Criar um Perfil de test emsrc/main/resources チャドイド応用試験.プロパティo o seguinte conte api - do para habilar a conex - no & o com o h 2 :
    spring.datasource.url=jdbc:h2:mem:testdb
    spring.datasource.username=sa
    spring.datasource.password=
    
    spring.h2.console.enabled=true
    spring.h2.console.path=/h2-console
    
    EいいえArquivoアプリケーション.プロパティー
    spring.profiles.active=test
    
    spring.jpa.open-in-view=false
    
    Ativando oは、テストA Definindo queとしてテストe Definindo queとしてTransA Ses . es com o o ser ser o o feitas fechadas dentro das camadasサービスリポジトリN . o o deixandoとしてTransa - es .
    インターフェイスとしてのインターフェイスとしてのDepois IREI Criar : A . A . A . A . Da JPA Per - Acessoを用いて
    @Repository
    public interface LotteryTicketRepository extends JpaRepository<LotteryTicket, Long> {
    }
    
    // E
    
    @Repository
    public interface BettorRepository extends JpaRepository<Bettor, Long> {
    }
    
    パラテスターa a a a a a a a a a a exo o o com o Banco de Dados , Ire Criar um Arquivo Testdbmain na Rayo do Pacote com O seguinte c - didigo :
    public static void main(String[] args) {
    
        ApplicationContext applicationContext = new SpringApplicationBuilder(LotteryApiApplication.class)
                .web(WebApplicationType.SERVLET)
                .run(args);
    
        BettorRepository bettorRepository = applicationContext.getBean(BettorRepository.class);
        LotteryTicketRepository lotteryTicketRepository = applicationContext.getBean(LotteryTicketRepository.class);
    
        Bettor bettor1 = new Bettor();
        bettor1.setEmail("[email protected]");
        bettorRepository.save(bettor1);
    
        Random betGenerator = new Random();
        LotteryTicket lotteryTicket1 = new LotteryTicket();
        lotteryTicket1.setBet1(betGenerator.nextInt(100));
        lotteryTicket1.setBet2(betGenerator.nextInt(100));
        lotteryTicket1.setBet3(betGenerator.nextInt(100));
        lotteryTicket1.setBet4(betGenerator.nextInt(100));
        lotteryTicket1.setBettor(bettor1);
        lotteryTicketRepository.save(lotteryTicket1);
    }
    
    A A A Plataa e acessando Aは、h h consigo verificar a a a o a a a a a a a a a a a a a a a a a a a a a sisigo verificar a a a a a a a a a a a a a a sisigo verificar a a a a a a a a a a sisigo verificar a a a a a a a a a a a a sisigo verificar a a a a a a a a a a sisigo verificar a a a a a a a a a a sisigo verificar a a a a a a a a a a sisigo verificar a a a a a a a a a a a a sisigo verificar a a a a a a a a a aアゴラVamosパラミネーターは、Old Tamas Camadasを得ます.

    DTO


    Ire Criar - Ma Classeパラシュートで降下する人ServirデモルレデDados para Transitarは、CamadaデコントローラE A Camadaデサービス、PenseiエムCriar - um TicketLotterydto Nesse formatoに入ります
    public class LotteryTicketDTO implements Serializable {
    
        private static final long serialVersionUID = 1L;
    
        private Long id;
        private Integer bet1;
        private Integer bet2;
        private Integer bet3;
        private Integer bet4;
        private Bettor bettor;
    
        public LotteryTicketDTO() {
        }
    
        public LotteryTicketDTO(Long id, Integer bet1, Integer bet2, Integer bet3, Integer bet4, Bettor bettor) {
            this.id = id;
            this.bet1 = bet1;
            this.bet2 = bet2;
            this.bet3 = bet3;
            this.bet4 = bet4;
            this.bettor = bettor;
        }
    
        public LotteryTicketDTO(LotteryTicket entity) {
            this.id = entity.getId();
            this.bet1 = entity.getBet1();
            this.bet2 = entity.getBet2();
            this.bet3 = entity.getBet3();
            this.bet4 = entity.getBet4();
            this.bettor = entity.getBettor();
        }
    
        // OMITINDO OS GETTERS AND SETTERS
    }
    

    サービス


    na camadaサービスiRe Criar mは、todos Publicos、umパラInserir馬ノバapostaなしBanco e outro para Listarとしてapostas por電子メールです.
    これは、先ほどのUSS OSのdoisリポジトリである.
    TANTO TOTO INSERT CODO NOT TO TODO FINDALYBYEWAY QUE IREE CRUR VOO PRIISISER DE UMA BUSCA NO bd Better POR Email , Por isso Forceisi Fazer - uma FifyIa - a - no - meu bettorposia :
    @Repository
    public interface BettorRepository extends JpaRepository<Bettor, Long> {
    
      @Query("SELECT b FROM Bettor b WHERE b.email=:email")
      public Optional<Bettor> findByEmail(@Param("email") String email);
    
    }
    
    エッセNOVO MfindByEmail デフォルトでは、PNAのデフォルトのNAを実行します.
    フィフスアッシム
    @Transactional
    public LotteryTicketDTO insert(LotteryTicketDTO dto) {
        Random betGenerator = new Random();
        Bettor bettor = getOrCreateBettor(dto.getBettor().getEmail());
        LotteryTicket entity = new LotteryTicket();
        entity.setBet1(betGenerator.nextInt(100));
        entity.setBet2(betGenerator.nextInt(100));
        entity.setBet3(betGenerator.nextInt(100));
        entity.setBet4(betGenerator.nextInt(100));
        entity.setBettor(bettor);
        entity = lotteryTicketRepository.save(entity);
        return new LotteryTicketDTO(entity);
    }
    
    @Transactional
    public List<LotteryTicketDTO> findAllByEmail(LotteryTicketDTO dto) {
        Optional<Bettor> obj = bettorRepository.findByEmail(dto.getBettor().getEmail());
        Set<LotteryTicket> lotteryTickets = obj.get().getLotteryTickets();
        List<LotteryTicketDTO> dtoList = lotteryTickets.stream().map(x -> new LotteryTicketDTO(x)).collect(Collectors.toList());
        return dtoList;
    }
    
    @Transactional
    private Bettor getOrCreateBettor(String email) {
        Optional<Bettor> obj = bettorRepository.findByEmail(email);
        try {
            return obj.get();
        } catch (Exception e) {
            Bettor bettor = new Bettor();
            bettor.setEmail(email);
            return bettorRepository.save(bettor);
        }
      }
    
    Anota条例o o@TranstionalインディカParo O春que Aquele M . Take Dafz Ua Intera
    東方藤堂getOrCreateBettor garante que nño o crie um bettor com電子メール繰り返しは、パラシュートで降下します.

    コントローラ


    A . A . Acontece Aquiのコントローラー:
    @RestController
    @RequestMapping(value = "/lottery_tickets")
    public class LotteryTicketsController {
    
      @Autowired
      private LotteryTicketService lotteryTicketService;
    
      @GetMapping
      public ResponseEntity<List<LotteryTicketDTO>> findAllByEmail(@RequestBody LotteryTicketDTO dto) {
          List<LotteryTicketDTO> dtoList = lotteryTicketService.findAllByEmail(dto);
          return ResponseEntity.ok(dtoList);
      }
    
      @PostMapping
      public ResponseEntity<LotteryTicketDTO> insert(@RequestBody LotteryTicketDTO dto) {
          dto = lotteryTicketService.insert(dto);
          return ResponseEntity.ok().body(dto);
      }
    
    }
    
    A o@@ restcontroller garante que minha classe seja um Controlor残りe e@resquestmapping permite que euは、rotaデacesso pela uriをカスタマイズします.
    LogterytickService eクリオDois m Tesは、ポストパラFazer AインサMisrano oデDa Nova Aposta e UseにPosterListをapostas por電子メールとして得ます.
    AO Retornkdto to ou uma Lista deles , Terho - um Probema de recurse de a o pois ao trazer o better dentro do json de Lotterytickddto , Apostas dentro do Bettor e Bettor dentro da aposta , as para resolver isso adicionei as a a a a o @ jsonignore no a atbuto LotteryClip da Entidade Better :
    @JsonIgnore
    @OneToMany(mappedBy="bettor")
    @OrderBy("createdAt DESC")
    private Set<LotteryTicket> lotteryTickets;
    
    POR FIM OSはFinais , COM A Aplica SystiSo o Starta e umソフトウェアde RETSI SIM SI ES es como insmnia posso fazer um post :http://localhost:8080/lottery_tickets :
    JSONボディ
    {
        "bettor": {
            "email": "[email protected]"
        }
    }
    
    Responsta :
    {
      "id": 5,
      "bet1": 44,
      "bet2": 86,
      "bet3": 68,
      "bet4": 72,
      "bettor": {
        "id": 1,
        "email": "[email protected]"
      }
    }
    
    E get get :http://localhost:8080/lottery_tickets :
    JSONボディ
    {
        "bettor": {
            "email": "[email protected]"
        }
    }
    
    Responsta :
    [
      {
        "id": 5,
        "bet1": 44,
        "bet2": 86,
        "bet3": 68,
        "bet4": 72,
        "bettor": {
          "id": 1,
          "email": "[email protected]"
        }
      },
      {
        "id": 4,
        "bet1": 13,
        "bet2": 62,
        "bet3": 78,
        "bet4": 1,
        "bettor": {
          "id": 1,
          "email": "[email protected]"
        }
      }
    ]
    
    EアッシムFicaは、IBMの春+ Hibernateの上で実行します.

    エキストラ


    <資料>


    藤堂なしfindAllByEmail サービスvai disparar um erro comステータス500 caso o電子メールinformado n .パラトレーラーISSOクリエリservices.exceptions :
    public class ResourceNotFoundException extends RuntimeException{
      public ResourceNotFoundException(String message) {
          super(message);
      }
    }
    
    <研究ノート>トド・パラ・キャプチュラー『エル・エ・ラン』について
    @Transactional
    public List<LotteryTicketDTO> findAllByEmail(LotteryTicketDTO dto) {
        Optional<Bettor> obj = bettorRepository.findByEmail(dto.getBettor().getEmail());
        Set<LotteryTicket> lotteryTickets = obj.orElseThrow(() -> new ResourceNotFoundException("Entity not found.")).getLotteryTickets();
        List<LotteryTicketDTO> dtoList = lotteryTickets.stream().map(x -> new LotteryTicketDTO(x)).collect(Collectors.toList());
        return dtoList;
    }
    
    E Criei um標準的なパラダイムMuldar Acontrollers.exceptions :
    public class StandardError implements Serializable {
    
        private static final long serialVersionUID = 1L;
    
        private Instant timestamp;
        private Integer status;
        private String error;
        private String message;
        private String path;
    
        public StandardError() {
        }
    
        // OMITINDO GETTERS AND SETTERS
    
    }
    
    E Ma ClassseデHandler Paradiarar UMA Relosta de Erro Amigavel Quand O ResourceToFoundDeception
    @ControllerAdvice
    public class ResourceExceptionHandler {
      @ExceptionHandler(ResourceNotFoundException.class)
      public ResponseEntity<StandardError> entityNotFound(ResourceNotFoundException exception, HttpServletRequest request) {
          HttpStatus status = HttpStatus.NOT_FOUND;
          StandardError error = new StandardError();
          error.setTimestamp(Instant.now());
          error.setStatus(status.value());
          error.setError("Resource Not Found");
          error.setMessage(exception.getMessage());
          error.setPath(request.getRequestURI());
    
          return ResponseEntity.status(status).body(error);
      }
    }
    
    Anotaは、o @ ControllerAdvider ColocaエサClasseデErro Sob Comaddoをします.

    Vicificando Sequenceは、NCIAデnをとります


    Criei um mは、Thedo Em LotterytickServiceパラシュートで降下します、そして、Meros - A n - Ment da Aposta、Mas AntesデAtribuirは、Enterdade LotteryチケットEU Verifico SE O Bettor N - Astro O Possu Le Uma Aposta comです.
    @Transactional
    private void generateBets(Bettor bettor, LotteryTicket entity) {
        Boolean allRight = false;
        Random betGenerator = new Random();
        Integer attempedBet1 = betGenerator.nextInt(100);
        Integer attempedBet2 = betGenerator.nextInt(100);
        Integer attempedBet3 = betGenerator.nextInt(100);
        Integer attempedBet4 = betGenerator.nextInt(100);
        Optional<Bettor> obj = bettorRepository.findByEmail(bettor.getEmail());
        Set<LotteryTicket> lotteryTickets = obj.get().getLotteryTickets();
        try {
            for (LotteryTicket lotteryTicket : lotteryTickets) {
                List<Integer> bets = new ArrayList<>();
                bets.add(lotteryTicket.getBet1());
                bets.add(lotteryTicket.getBet2());
                bets.add(lotteryTicket.getBet3());
                bets.add(lotteryTicket.getBet4());
                if (!bets.contains(attempedBet1) &&
                        !bets.contains(attempedBet2) &&
                        !bets.contains(attempedBet3) &&
                        !bets.contains(attempedBet4)) {
                    allRight = true;
                }
            }
            if (!allRight) {
                generateBets(bettor, entity);
            } else {
                entity.setBet1(betGenerator.nextInt(100));
                entity.setBet2(betGenerator.nextInt(100));
                entity.setBet3(betGenerator.nextInt(100));
                entity.setBet4(betGenerator.nextInt(100));
            }
        } catch (Exception e) {
            entity.setBet1(betGenerator.nextInt(100));
            entity.setBet2(betGenerator.nextInt(100));
            entity.setBet3(betGenerator.nextInt(100));
            entity.setBet4(betGenerator.nextInt(100));
        }
    }