ãã®ããã¹ãã¯ãããŒã¿æ€èšŒã®ããŸããŸãªã¢ãããŒãã«çŠç¹ãåœãŠãŠããŸãããããžã§ã¯ãã§ééããå¯èœæ§ã®ããèœãšã穎ãšãJavaã¢ããªã±ãŒã·ã§ã³ã§ããŒã¿ãæ€èšŒããéã«åŸãã¹ãã¡ãœãããšãã¯ãããžãŒã§ãã

äœæè
ãããããããŒã¿æ€èšŒã®ã¢ãããŒããéžæããªãã£ããããžã§ã¯ããããèŠãŸããã ããŒã ã¯ãæéãšãããŸããªèŠä»¶ãšãã圢ã§ä¿¡ããããªãã»ã©ã®ãã¬ãã·ã£ãŒã®äžã§ãããžã§ã¯ãã«åãçµã¿ãŸããããã®çµæã圌ãã¯æ£ç¢ºã§äžè²«ããæ€èšŒã®æéãæã£ãŠããŸããã§ããã ãã®ãããJavascriptã¹ãããããã¹ã¯ãªãŒã³ã³ã³ãããŒã©ãŒãããžãã¹ããžãã¯ãã³ããã¡ã€ã³ãšã³ãã£ãã£ãããªã¬ãŒãããŒã¿ããŒã¹å¶çŽãªã©ãæ€èšŒã³ãŒãã¯ããããå Žæã«æ£ãã°ã£ãŠããŸãã ãã®ã³ãŒãã¯if-elseã¹ããŒãã¡ã³ãã§ãã£ã±ãã§ããã倿°ã®äŸå€ãã¹ããŒããããã§ç¹å®ã®ããŒã¿ãæ€èšŒãããå ŽæãèŠã€ããããšããŸã...ãã®çµæããããžã§ã¯ãã®éçºã«äŒŽããèŠä»¶ã«æºæ ããããšãé£ãããªããã³ã¹ããããããŸãïŒå€ãã®å Žåãéåžžã«æ··ä¹±ããŸãïŒããŒã¿æ€èšŒãžã®ã¢ãããŒãã®åäžæ§ã
ããŒã¿ãæ€èšŒããããã®ã·ã³ãã«ã§ãšã¬ã¬ã³ããªæ¹æ³ã¯ãããŸããïŒ èªã¿ã«ãããšãã眪ããç§ãã¡ãå®ãæ¹æ³ãæ€èšŒã®ãã¹ãŠã®ããžãã¯ããŸãšããæ¹æ³ããããŠäººæ°ã®ããJavaãã¬ãŒã ã¯ãŒã¯ã®éçºè
ã«ãã£ãŠãã§ã«äœæãããæ¹æ³ã¯ãããŸããïŒ
ã¯ãããã®ãããªæ¹æ³ããããŸãã
CUBAãã©ãããã©ãŒã ã®éçºè
ã§ããç§ãã¡ã«ãšã£ãŠããã¹ããã©ã¯ãã£ã¹ã䜿çšã§ããããšãéåžžã«éèŠã§ãã æ€èšŒã³ãŒãã¯æ¬¡ã®ããšãè¡ãå¿
èŠããããšèããŠããŸãã
- åå©çšå¯èœã§ãããDRYã®ååã«åŸã£ãŠãã ããã
- èªç¶ã§çè§£ãããããã®ã«ããŠãã ããã
- éçºè
ãèŠããå Žæã«é
眮ã
- ãŠãŒã¶ãŒã€ã³ã¿ãŒãã§ã€ã¹ãSOAPåŒã³åºããRESTãªã©ãããŸããŸãªãœãŒã¹ããã®ããŒã¿ãæ€èšŒã§ããããã«ããŸãã
- åé¡ãªããã«ãã¹ã¬ããç°å¢ã§åäœããŸãã
- ãã§ãã¯ãæåã§å®è¡ããå¿
èŠãªããã¢ããªã±ãŒã·ã§ã³å
ã§èªåçã«åŒã³åºãããŸãã
- ç°¡æœãªãã€ã¢ãã°ããã¯ã¹ã§ãŠãŒã¶ãŒã«æç¢ºã§ããŒã«ã©ã€ãºãããã¡ãã»ãŒãžãæäŸããããã
- æšæºã«åŸã£ãŠãã ããã
CUBAãã©ãããã©ãŒã ãã¬ãŒã ã¯ãŒã¯ã䜿çšããŠèšè¿°ããããµã³ãã«ã¢ããªã±ãŒã·ã§ã³ã䜿çšããŠããããå®è£
ããæ¹æ³ãèŠãŠã¿ãŸãããã ãã ããCUBAã¯SpringãšEclipseLinkã«åºã¥ããŠãããããããã§äœ¿çšãããæè¡ã®ã»ãšãã©ã¯ãJPAããã³Bean Validation仿§ããµããŒãããä»ã®Javaãã©ãããã©ãŒã ã§åäœããŸãã
ããŒã¿ããŒã¹å¶çŽã䜿çšããæ€èšŒ
ãããããããŒã¿ãæ€èšŒããæãäžè¬çã§æçœãªæ¹æ³ã¯ãããŒã¿ããŒã¹ã¬ãã«ã§å¶éã䜿çšããããšã§ããããšãã°ãå¿
é ãã©ã°ïŒå€ã空ã«ããããšã¯ã§ããªããã£ãŒã«ãïŒãæååã®é·ããäžæã®ã€ã³ããã¯ã¹ãªã©ã§ãã ãã®ã¿ã€ãã®ãœãããŠã§ã¢ã¯éåžžãããŒã¿åŠçã«å³å¯ã«çŠç¹ãåãããŠããããããã®æ¹æ³ã¯ãšã³ã¿ãŒãã©ã€ãºã¢ããªã±ãŒã·ã§ã³ã«æé©ã§ãã ãã ããããã§ããã¢ããªã±ãŒã·ã§ã³ã®åã¬ãã«ã«åå¥ã«å¶éãèšå®ããããšã«ãããéçºè
ã¯ééããç¯ããŸãã ã»ãšãã©ã®å Žåããã®çç±ã¯éçºè
éã®è²¬ä»»ã®åé
ã«ãããŸãã
ç§ãã¡ã®ã»ãšãã©ãç¥ã£ãŠããäŸãèããŠã¿ãŠãã ãããç§ãã¡èªèº«ã®çµéšããã§ã⊠RESTãµãŒãã¹ããããŠæåŸã«ãã¯ã©ã€ã¢ã³ãåŽã®UIéçºè
ã æ¬¡ã«ããã®èŠä»¶ã倿Žããããã£ãŒã«ãã15æåã«å¢å ããŸãã Devopsã¯ããŒã¿ããŒã¹ã®å¶çŽå€ã倿ŽããŸãããã¯ã©ã€ã¢ã³ãåŽã®å¶éã¯åãã§ããããããŠãŒã¶ãŒã«ãšã£ãŠã¯äœãå€ãããŸãã...
éçºè
ã¯ãã®åé¡ãåé¿ããæ¹æ³ãç¥ã£ãŠããŸããæ€èšŒã¯éäžåããå¿
èŠããããŸãã CUBAã§ã¯ããã®ãããªæ€èšŒã¯JPAãšã³ãã£ãã£ã¢ãããŒã·ã§ã³ã«ãããŸãã ãã®ã¡ã¿æ
å ±ã«åºã¥ããŠãCUBA Studioã¯æ£ããDDLã¹ã¯ãªãããçæããé©åãªã¯ã©ã€ã¢ã³ãåŽããªããŒã¿ãŒãé©çšããŸãã

泚éã倿ŽããããšãCUBAã¯DDLã¹ã¯ãªãããæŽæ°ããç§»è¡ã¹ã¯ãªãããçæããŸãããã®ãããæ¬¡åãããžã§ã¯ããå±éãããšãã«ãã€ã³ã¿ãŒãã§ã€ã¹ãšã¢ããªã±ãŒã·ã§ã³ããŒã¿ããŒã¹ã®äž¡æ¹ã§æ°ããJPAããŒã¹ã®å¶éãæå¹ã«ãªããŸãã
ãã®æ¹æ³ã«çµ¶å¯Ÿçãªä¿¡é Œæ§ãäžããããŒã¿ããŒã¹ã¬ãã«ã§ã®ã·ã³ãã«ããšå®è£
ã«ãããããããJPAã¢ãããŒã·ã§ã³ã®ç¯å²ã¯ãDDLæšæºã§è¡šçŸã§ããæãåçŽãªã±ãŒã¹ã«éå®ãããããŒã¿ããŒã¹ããªã¬ãŒãã¹ãã¢ãããã·ãŒãžã£ã¯å«ãŸããŸããã ãã®ãããJPAããŒã¹ã®å¶çŽã«ããããšã³ãã£ãã£ãã£ãŒã«ããäžæãŸãã¯å¿
é ã«ããããåã®æå€§é·ãèšå®ã§ããŸãã @UniqueConstraint
ã¢ãããŒã·ã§ã³ã䜿çšããŠãåã®çµã¿åããã«äžæã®å¶éãèšå®ããããšãã§ããŸãã ããããããããããããã¹ãŠã§ãã
å Žåã«ãã£ãŠã¯ããã£ãŒã«ãã®æå°/æå€§å€ã®ç¢ºèªãæ£èŠè¡šçŸã«ããæ€èšŒãã¢ããªã±ãŒã·ã§ã³åºæã®ã«ã¹ã¿ã ãã§ãã¯ã®å®è¡ãªã©ãããè€éãªæ€èšŒããžãã¯ãå¿
èŠãªå Žåã¯ã ãBean ValidationããšåŒã°ããã¢ãããŒããé©çšãããŸãã
Beanæ€èšŒ
誰ãããã©ã€ããµã€ã¯ã«ãé·ãããã®å¹æãäœåãã®ãããžã§ã¯ãã§èšŒæãããŠããæšæºã«åŸãããšããå§ãããŸãã Java Bean Validationã¯ã JSR 380ã349 ãããã³303ãšãã®ã¢ããªã±ãŒã·ã§ã³ïŒ Hibernate Validatorããã³Apache BValïŒã§ææžåãããã¢ãããŒãã§ã ã
ãã®ã¢ãããŒãã¯å€ãã®éçºè
ã«ããç¥ãããŠããŸãããå€ãã®å Žåéå°è©äŸ¡ãããŠããŸãã ããã¯ãã¬ã¬ã·ãŒãããžã§ã¯ãã«ãããŒã¿æ€èšŒãåã蟌ãç°¡åãªæ¹æ³ã§ããããã«ãããæç¢ºã§ã·ã³ãã«ã§ä¿¡é Œæ§ãé«ããããžãã¹ããžãã¯ã«å¯èœãªéãè¿ããã§ãã¯ãæ§ç¯ã§ããŸãã
Bean Validationã䜿çšãããšããããžã§ã¯ãã«å€ãã®å©ç¹ããããŸãã
- æ€èšŒããžãã¯ã¯ãµããžã§ã¯ãé åã®é£ã«ãããŸãããã³ã®ãã£ãŒã«ããšã¡ãœããã®å¶éã®å®çŸ©ã¯ãèªç¶ã§çã®ãªããžã§ã¯ãæåã®æ¹æ³ã§è¡ãããŸãã
- Bean Validationæšæºã¯ã
@Size
ã«äœ¿çšã§ãã@Min
ã®æ€èšŒã¢ãããŒã·ã§ã³ãæäŸããŸã ãããšãã°ã @Size
ã @Min
ã @Max
ã @Pattern
ã @Email
ã @Past
@Email
ã @Past
ãæšæºã§ã¯ãªã@URL
ã @Length
ãæã匷åãª@ScriptAssert
ãªã©ã - ãã®æšæºã¯æ¢è£œã®æ³šéã«éå®ãããã®ã§ã¯ãªããç¬èªã®æ³šéãäœæããããšãã§ããŸãã ãŸããä»ã®ããã€ããçµã¿åãããŠæ°ããæ³šéãäœæããããå¥ã®Javaã¯ã©ã¹ãããªããŒã¿ãšããŠäœ¿çšããŠå®çŸ©ãããããããšãã§ããŸãã
ããšãã°ãäžèšã®äŸã§ã¯ãã¯ã©ã¹ã¬ãã«ã®æ³šé@ValidPassportNumber
ãèšå®ããŠããã¹ããŒãçªå·ãcountry
ãã£ãŒã«ãã®å€ã«å¿ãã圢åŒãšäžèŽããããšã確èªã§ããŸãã - å¶çŽã¯ããã£ãŒã«ããŸãã¯ã¯ã©ã¹ã ãã§ãªããã¡ãœãããšãã®ãã©ã¡ãŒã¿ãŒã«ãèšå®ã§ããŸãã ãã®ã¢ãããŒãã¯ãå¥çŽã«ããæ€èšŒããšåŒã°ããåŸã»ã©èª¬æããŸãã
ãŠãŒã¶ãŒãå
¥åãããæ
å ±ãéä¿¡ãããšã CUBAãã©ãããã©ãŒã 㯠ïŒä»ã®ãã¬ãŒã ã¯ãŒã¯ãšåæ§ã«ïŒ Bean Validationãèªåçã«éå§ãããããæ€èšŒã倱æãããšå³åº§ã«ãšã©ãŒã¡ãã»ãŒãžã衚瀺ããããã³ããªããŒã¿ãŒãæåã§å®è¡ããå¿
èŠã¯ãããŸããã
ãã¹ããŒãçªå·ã䜿çšããŠäŸã«æ»ããŸãããããä»åã¯Personãšã³ãã£ãã£ã®ããã€ãã®å¶éã远å ããŸãã
name
ãã£ãŒã«ãã¯2æå以äžã§ãªããã°ãªãããæå¹ã§ãªããã°ãªããŸããã ïŒã芧ã®ãšãããæ£èŠè¡šçŸã¯åçŽã§ã¯ãããŸããããCharles Ogier de Batz de Castelmore Comte d'Artagnanã¯ãã¹ãã«åæ ŒããŸãããR2D2ã¯åæ ŒããŸããïŒãheight
ïŒé«ãïŒã¯æ¬¡ã®ééã§ããå¿
èŠããããŸã0 < height <= 300
cmãemail
ãã£ãŒã«ãã«ã¯ãæ£ããé»åã¡ãŒã«ã®åœ¢åŒã«äžèŽããæååãå«ãŸããŠããå¿
èŠããããŸãã
ããããã¹ãŠã®ãã§ãã¯ã«ãããPersonã¯ã©ã¹ã¯æ¬¡ã®ããã«ãªããŸãã
@Listeners("passportnumber_PersonEntityListener") @NamePattern("%s|name") @Table(name = "PASSPORTNUMBER_PERSON") @Entity(name = "passportnumber$Person") @ValidPassportNumber(groups = {Default.class, UiCrossFieldChecks.class}) @FraudDetectionFlag public class Person extends StandardEntity { private static final long serialVersionUID = -9150857881422152651L; @Pattern(message = "Bad formed person name: ${validatedValue}", regexp = "^[AZ][az]*(\\s(([az]{1,3})|(([az]+\\')?[AZ][az]*)))*$") @Length(min = 2) @NotNull @Column(name = "NAME", nullable = false) protected String name; @Email(message = "Email address has invalid format: ${validatedValue}", regexp = "^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\\.[a-zA-Z0-9-.]+$") @Column(name = "EMAIL", length = 120) protected String email; @DecimalMax(message = "Person height can not exceed 300 centimeters", value = "300") @DecimalMin(message = "Person height should be positive", value = "0", inclusive = false) @Column(name = "HEIGHT") protected BigDecimal height; @NotNull @Column(name = "COUNTRY", nullable = false) protected Integer country; @NotNull @Column(name = "PASSPORT_NUMBER", nullable = false, length = 15) protected String passportNumber; ... }
Person.java
@NotNull
ã @DecimalMin
ã @Length
ã @Pattern
@DecimalMin
ãªã©ã®æ³šéã®äœ¿çšã¯éåžžã«æçœã§ãããã³ã¡ã³ããå¿
èŠãšããªããšä¿¡ããŠããŸãã @ValidPassportNumber
ã¢ãããŒã·ã§ã³ã®å®è£
ã詳ããèŠãŠã¿ãŸãããã
æ°ãã@ValidPassportNumber
ã¯ã Person#passportNumber
ãPerson#country
ãã£ãŒã«ãã§æå®ãããååœã®æ£èŠè¡šçŸãã¿ãŒã³ãšäžèŽããããšã確èªããŸãã
ãŸããããã¥ã¡ã³ããã芧ãã ãã ïŒ CUBAãŸãã¯Hibernateã®ããã¥ã¢ã«ã§åé¡ãããŸããïŒãããã«å¿ããŠããã®æ°ããæ³šéã§ã¯ã©ã¹ãããŒã¯ããããã«groups
ãã©ã¡ãŒã¿ãŒãæž¡ãå¿
èŠããããŸãUiCrossFieldChecks.class
ã¯ããã®æ€èšŒãã¯ãã¹ã§å®è¡ãããããšãæå³ããŸããæ€èšŒ-ãã¹ãŠã®åã
ã®ãã£ãŒã«ãããã§ãã¯ããåŸã Default.class
ã¯ããã©ã«ãã®æ€èšŒã°ã«ãŒãã«å¶éãä¿åããŸãã
泚éã®èª¬æã¯æ¬¡ã®ããã«ãªããŸãã
@Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Constraint(validatedBy = ValidPassportNumberValidator.class) public @interface ValidPassportNumber { String message() default "Passport number is not valid"; Class<?>[] groups() default {}; Class<? extends Payload>[] payload() default {}; }
ValidPassportNumber.java
ããã§ã @Target(ElementType.TYPE)
ã¯ããã®ã©ã³ã¿ã€ã ã¢ãããŒã·ã§ã³ã®ç®çã¯ã¯ã©ã¹ã§ããã @Constraint(validatedBy = ⊠)
ã¯ã ConstraintValidator<...>
ã€ã³ã¿ãŒãã§ãŒã¹ãå®è£
ããValidPassportNumberValidator
ã¯ã©ã¹ã«ãã£ãŠæ€èšŒãå®è¡ãããããšã決å®ããŸãã æ€èšŒã³ãŒãèªäœã¯isValid(...)
ã¡ãœããã«ãããå®éã®æ€èšŒãããªãç°¡åãªæ¹æ³ã§å®è¡ããŸãã
public class ValidPassportNumberValidator implements ConstraintValidator<ValidPassportNumber, Person> { public void initialize(ValidPassportNumber constraint) { } public boolean isValid(Person person, ConstraintValidatorContext context) { if (person == null) return false; if (person.country == null || person.passportNumber == null) return false; return doPassportNumberFormatCheck(person.getCountry(), person.getPassportNumber()); } private boolean doPassportNumberFormatCheck(CountryCode country, String passportNumber) { ... } }
ValidPassportNumberValidator.java
以äžã§ãã CUBAãã©ãããã©ãŒã ã§ã¯ãã«ã¹ã¿ã æ€èšŒãæ©èœããããŠãŒã¶ãŒãšã©ãŒã¡ãã»ãŒãžã衚瀺ããã³ãŒãè¡ãèšè¿°ããã ãã§æžã¿ãŸãã
è€éãªããšã¯ãããŸãããïŒ
ããã§ã¯ããã¹ãŠã®ä»çµã¿ãèŠãŠã¿ãŸãããã ããã§CUBAã«ã¯ä»ã®nishtyakiããããŸãïŒãŠãŒã¶ãŒã«ãšã©ãŒã¡ãã»ãŒãžã衚瀺ããã ãã§ãªããBeanæ€èšŒã«åæ Œããªãã£ãèµ€ããã£ãŒã«ãã§åŒ·èª¿è¡šç€ºããŸãã

ããã¯ãšã¬ã¬ã³ããªè§£æ±ºçã§ã¯ãããŸãããïŒ ãµããžã§ã¯ãé åã®ãšã³ãã£ãã£ã«ããã€ãã®Java泚éã®ã¿ã远å ããããšã«ãããUIã«æ€èšŒãšã©ãŒã®é©åãªè¡šç€ºãåŸãããŸãã
ã»ã¯ã·ã§ã³ãèŠçŽããŠããšã³ãã£ãã£ã«å¯ŸããBean Validationã®å©ç¹ãããäžåºŠç°¡åã«ãªã¹ãããŸãããã
- ããã¯çè§£å¯èœã§èªã¿ãããã§ãã
- ãšã³ãã£ãã£ã¯ã©ã¹ã§å€ã®å¶çŽãçŽæ¥å®çŸ©ã§ããŸãã
- ã«ã¹ã¿ãã€ãºããã³è£è¶³ã§ããŸãã
- äžè¬çãªORMã«çµ±åããã倿ŽãããŒã¿ããŒã¹ã«ä¿åãããåã«ãã§ãã¯ãèªåçã«éå§ãããŸãã
- äžéšã®ãã¬ãŒã ã¯ãŒã¯ã¯ããŠãŒã¶ãŒãUIã«ããŒã¿ãéä¿¡ãããšãã«Beanæ€èšŒãèªåçã«å®è¡ããŸãïŒããã§ãªãå Žåã¯ã
Validator
ã€ã³ã¿ãŒãã§ã€ã¹ãæåã§ç°¡åã«åŒã³åºãããšãã§ããŸãïŒã - Bean Validationã¯èªèãããŠããæšæºã§ãããã€ã³ã¿ãŒãããäžã®ããã¥ã¡ã³ãã§äžæ¯ã§ãã
ããããå€éšã·ã¹ãã ããã®ããŒã¿ãæ€èšŒããããã«ãã¡ãœãããã³ã³ã¹ãã©ã¯ã¿ãŒããŸãã¯RESTã¢ãã¬ã¹ã«å¶éãèšå®ããå¿
èŠãããå Žåã¯ã©ãã§ããããïŒ ãŸãã¯ããã¹ããããåã¡ãœããã§å€ãã®if-elseæ¡ä»¶ãæã€éå±ãªã³ãŒããèšè¿°ããã«ãã¡ãœãããã©ã¡ãŒã¿ãŒã®å€ã宣èšçã«ãã§ãã¯ããå¿
èŠãããå Žåã¯ã©ãã§ããããã
çãã¯ç°¡åã§ãïŒBean Validationã¯ã¡ãœããã«ãé©çšãããŸãïŒ
å¥çŽã«ããæ€èšŒ
ããŒã¿ã¢ãã«ã®ç¶æ
ã®æ€èšŒãè¶
ããå¿
èŠãããå ŽåããããŸãã å€ãã®ã¡ãœããã¯ããã©ã¡ãŒã¿ãŒãšæ»ãå€ã®èªåæ€èšŒã®æ©æµãåããããšãã§ããŸãã ããã¯ãRESTãŸãã¯SOAPã¢ãã¬ã¹ã«éä¿¡ãããããŒã¿ããã§ãã¯ããã ãã§ãªããã¡ãœããåŒã³åºãã®åææ¡ä»¶ãšäºåŸæ¡ä»¶ãèŠå®ããŠãå
¥åãããããŒã¿ãã¡ãœããæ¬äœã®å®è¡åã«æ€èšŒãããããšããŸãã¯æ»ãå€ã確èªãããå Žåã«ãå¿
èŠã«ãªãå ŽåããããŸããäºæ³ãããç¯å²å
ã«ããããããšãã°ãå
¥åãã©ã¡ãŒã¿ãŒã®å€ã®ç¯å²ã宣èšçã«èšè¿°ããã ãã§ãã³ãŒãã®å¯èªæ§ãåäžããŸãã
Beanæ€èšŒã䜿çšããŠãã¡ãœããããã³ã³ã³ã¹ãã©ã¯ã¿ãŒã®å
¥åãã©ã¡ãŒã¿ãŒãšæ»ãå€ã«å¶éãé©çšããŠãJavaã¯ã©ã¹ã§ã®åŒã³åºãã®åææ¡ä»¶ãšäºåŸæ¡ä»¶ã確èªã§ããŸãã ãã®ãã¹ã«ã¯ããã©ã¡ãŒã¿ãŒãšæ»ãå€ã®æå¹æ§ããã§ãã¯ããåŸæ¥ã®æ¹æ³ã«æ¯ã¹ãŠããã€ãã®å©ç¹ããããŸãã
- åœä»€åã¹ã¿ã€ã«ã§æåã§ãã§ãã¯ãå®è¡ããå¿
èŠã¯ãããŸããïŒããšãã°ã
IllegalArgumentException
ãªã©ãã¹ããŒããããšã«ããïŒã å¶çŽã宣èšçã«å®çŸ©ããã³ãŒãããããããããã衚çŸåè±ãã«ããããšãã§ããŸãã - å¶çŽã®æ§æãåå©çšãæ§æãå¯èœã§ãããã§ãã¯ããšã«æ€èšŒããžãã¯ãèšè¿°ããå¿
èŠã¯ãããŸããã ã³ãŒããå°ãªãã»ã©ããã°ãå°ãªããªããŸãã
- ã¯ã©ã¹ãã¡ãœããã®æ»ãå€ããŸãã¯ãã©ã¡ãŒã¿ãŒã
@Validated
ã¢ãããŒã·ã§ã³ã§ããŒã¯ãããŠããå Žåããã§ãã¯ã¯ã¡ãœãããåŒã³åºããããã³ã«ãã©ãããã©ãŒã ã«ãã£ãŠèªåçã«å®è¡ãããŸãã - å®è¡å¯èœã¢ãžã¥ãŒã«ã
@Documented
ã¢ãããŒã·ã§ã³ã§ããŒã¯ãããŠãã@Documented
ããã®äºåæ¡ä»¶ãšäºåŸæ¡ä»¶ã¯çæãããJavaDocã«å«ãŸããŸãã
ãå¥çŽã®æ€èšŒãã䜿çšããŠãæç¢ºã§ã³ã³ãã¯ããªãä¿å®ã容æãªã³ãŒããååŸããŸãã
äŸãšããŠãCUBAã¢ããªã±ãŒã·ã§ã³ã®RESTã³ã³ãããŒã©ãŒã®ã€ã³ã¿ãŒãã§ãŒã¹ãèŠãŠã¿ãŸãããã PersonApiService
ã€ã³ã¿ãŒãã§ã€ã¹ã䜿çšãããšã getPersons()
ã¡ãœããã䜿çšããŠããŒã¿ããŒã¹ãã人ã®ãªã¹ããååŸãã addNewPerson(...)
åŒã³åºãã䜿çšããŠæ°ãã人ã远å ã§ããŸãã
ãããŠãBeanæ€èšŒãç¶æ¿ãããããšãå¿ããªãã§ãã ããïŒ ã€ãŸããç¹å®ã®ã¯ã©ã¹ããã£ãŒã«ãããŸãã¯ã¡ãœããã«æ³šéãä»ããå Žåããã®ã¯ã©ã¹ãç¶æ¿ãããããã®ã€ã³ã¿ãŒãã§ã€ã¹ãå®è£
ãããã¹ãŠã®ã¯ã©ã¹ã¯ãåãæ€èšŒæ³šéã®å¯Ÿè±¡ã«ãªããŸãã
@Validated public interface PersonApiService { String NAME = "passportnumber_PersonApiService"; @NotNull @Valid @RequiredView("_local") List<Person> getPersons(); void addNewPerson( @NotNull @Length(min = 2, max = 255) @Pattern(message = "Bad formed person name: ${validatedValue}", regexp = "^[AZ][az]*(\\s(([az]{1,3})|(([az]+\\')?[AZ][az]*)))*$") String name, @DecimalMax(message = "Person height can not exceed 300 cm", value = "300") @DecimalMin(message = "Person height should be positive", value = "0", inclusive = false) BigDecimal height, @NotNull CountryCode country, @NotNull String passportNumber ); }
PersonApiService.java
ãã®ã³ãŒãã¯ååã«æç¢ºã§ããïŒ
_ïŒCUBAãã©ãããã©ãŒã ã«åºæã®ã¢ãããŒã·ã§ã³@RequiredView(â_localâ)
é€ããè¿ãããPerson
ãªããžã§ã¯ãã«PASSPORTNUMBER_PERSON
ããŒãã«ã®ãã¹ãŠã®ãã£ãŒã«ããå«ãŸããŠããããšã確èªããŸãïŒ._
@Valid
ã¯ã getPersons()
ã¡ãœããã«ãã£ãŠè¿ãããåã³ã¬ã¯ã·ã§ã³ãªããžã§ã¯ããã Person
ã¯ã©ã¹ã®å¶éã«å¯ŸããŠæ€èšŒããå¿
èŠãããããšãå®çŸ©ããŸãã
CUBAã¢ããªã±ãŒã·ã§ã³ã§ã¯ããããã®ã¡ãœããã¯æ¬¡ã®ã¢ãã¬ã¹ã§å©çšã§ããŸãã
- / app / rest / v2 / services / passportnumber_PersonApiService / getPersons
- / app / rest / v2 / services / passportnumber_PersonApiService / addNewPerson
Postmanã¢ããªã±ãŒã·ã§ã³ãéããæ€èšŒãæ£åžžã«æ©èœããããšã確èªããŸãã

ãæ°ã¥ããããããŸããããäžèšã®äŸã§ã¯ãã¹ããŒãçªå·ã¯æ€èšŒãããŠããŸããã ããã¯ã passportNumber
ãæ€èšŒããããã®æ£èŠè¡šçŸãã³ãã¬ãŒãã®éžæãcountry
ãã£ãŒã«ãã®å€ã«äŸåããããããã®ãã£ãŒã«ãã¯addNewPerson
ã¡ãœããã®ãã©ã¡ãŒã¿ãŒã®ã¯ãã¹ãã§ãã¯ãå¿
èŠãšããããã§ãã ãã®çžäºæ€èšŒã¯ãã¯ã©ã¹ã¬ãã«ã®ãšã³ãã£ãã£å¶éã®å®å
šãªé¡äŒŒç©ã§ãïŒ
ãã©ã¡ãŒã¿ãŒã®çžäºæ€èšŒã¯JSR 349ããã³380ã§ãµããŒããããŠããŸããHibernateã®ããã¥ã¡ã³ããèªãã§ãç¬èªã®ã¯ã©ã¹/ã€ã³ã¿ãŒãã§ãŒã¹ã¡ãœããã®çžäºæ€èšŒãå®è£
ããæ¹æ³ãåŠã¶ããšãã§ããŸãã
å€éšBeanæ€èšŒ
äžçã«ã¯å®ç§ãªãã®ããªããããBeanã®æ€èšŒã«ã¯æ¬ ç¹ãšå¶éããããŸãã
- ããŒã¿ããŒã¹ã«å€æŽãä¿åããåã«ããªããžã§ã¯ãã®è€éãªã°ã©ãã®ç¶æ
ã確èªããã ãã§ããå ŽåããããŸãã ããšãã°ã顧客泚æã®ãã¹ãŠã®èŠçŽ ã1ã€ã®ããã±ãŒãžã«å
¥ããããŠããããšã確èªããå¿
èŠããããŸãã ããã¯ããªãé£ããæäœã§ããããŠãŒã¶ãŒã泚æã«æ°ããã¢ã€ãã ã远å ãããã³ã«å®è¡ããã®ã¯åŸçã§ã¯ãããŸããã ãããã£ãŠããã®ãããªãã§ãã¯ãå¿
èŠã«ãªãã®ã¯1åã ãã§ã
OrderItem
ãªããžã§ã¯ããšãã®OrderItem
ãµããªããžã§ã¯ããããŒã¿ããŒã¹ã«ä¿åããåã«ã - ãã©ã³ã¶ã¯ã·ã§ã³å
ã§ããã€ãã®ãã§ãã¯ãè¡ãå¿
èŠããããŸãã ããšãã°ãé»åã¹ãã¢ã·ã¹ãã ã¯ãããŒã¿ããŒã¹ã«ã³ãããããåã«æ³šæãå±¥è¡ããããã«ååãªååã®ã³ããŒããããã©ããã確èªããå¿
èŠããããŸãã ãã®ãããªãã§ãã¯ã¯ããã©ã³ã¶ã¯ã·ã§ã³å
ã§ã®ã¿å®è¡ã§ããŸãã ã·ã¹ãã ã¯ãã«ãã¹ã¬ããã§ãããåšåº«åã®æ°éã¯ãã€ã§ã倿Žãããå¯èœæ§ããããŸãã
CUBAãã©ãããã©ãŒã ã¯ã ãšã³ãã£ãã£ãªã¹ããŒãšãã©ã³ã¶ã¯ã·ã§ã³ãªã¹ããŒãšåŒã°ãã2ã€ã®äºåã³ãããããŒã¿æ€èšŒã¡ã«ããºã ãæäŸããŸãã ããããããè©³çŽ°ã«æ€èšããŸãããã
ãšã³ãã£ãã£ãªã¹ã
CUBAã®ãšã³ãã£ãã£ãªã¹ããŒã¯ ãJPAãéçºè
ã«æäŸããPreInsertEvent
ã PreUpdateEvent
ããã³PredDeleteEvent
ãªã¹ããŒã«éåžžã«äŒŒãŠããŸãã ã©ã¡ãã®ã¡ã«ããºã ã§ãããšã³ãã£ãã£ãªããžã§ã¯ããããŒã¿ããŒã¹ã«ä¿åããååŸã«ãã§ãã¯ã§ããŸãã
CUBAã§ã¯ããšã³ãã£ãã£ãªã¹ããŒãç°¡åã«äœæããŠæ¥ç¶ã§ããŸããããã«ã¯ã次ã®2ã€ãå¿
èŠã§ãã
- ãšã³ãã£ãã£ãªã¹ããŒã€ã³ã¿ãŒãã§ã€ã¹ã®1ã€ãå®è£
ãããããŒãžãBeanãäœæããŸãã æ€èšŒã«ã¯3ã€ã®ã€ã³ã¿ãŒãã§ã€ã¹ãéèŠã§ãã
BeforeDeleteEntityListener<T>
ã
BeforeInsertEntityListener<T>
ã
BeforeUpdateEntityListener<T>
- 远跡ããäºå®ã®ãšã³ãã£ãã£ãªããžã§ã¯ãã«
@Listeners
ã¢ãããŒã·ã§ã³ã远å ããŸãã
ãããŠããã ãã§ãã
JPAæšæºïŒJSR 338ãã»ã¯ã·ã§ã³3.5ïŒãšæ¯èŒãããšãCUBAãã©ãããã©ãŒã ãªã¹ããŒã€ã³ã¿ãŒãã§ã€ã¹ã¯åæå®ãããŠããããã Object
åã®åŒæ°ããšã³ãã£ãã£åã«ãã£ã¹ãããŠäœæ¥ãéå§ããå¿
èŠã¯ãããŸããã CUBAãã©ãããã©ãŒã ã¯ãé¢é£ãããšã³ãã£ãã£ãŸãã¯EntityManagerã®åŒã³åºãå
ã«ãä»ã®ãšã³ãã£ãã£ãããŒãããã³å€æŽããæ©èœã远å ããŸãã ãããã®å€æŽã¯ãã¹ãŠã察å¿ãããšã³ãã£ãã£ãªã¹ããŒãåŒã³åºããŸãã
CUBAãã©ãããã©ãŒã ã¯ãããŒã¿ããŒã¹ããå®éã«ã¬ã³ãŒããåé€ãã代ããã«ãå逿žã¿ãšããŠããŒã¯ãããéåžžã®äœ¿çšã§ã¯ã¢ã¯ã»ã¹ã§ããªããªãã¢ãããŒãã§ããããœããåé€ãããµããŒãããŠããŸãã ãããã£ãŠããœããåé€ã®å Žåããã©ãããã©ãŒã ã¯BeforeDeleteEntityListener
/ AfterDeleteEntityListener
ãªã¹ããŒãåŒã³åºããŸãããæšæºã®å®è£
ã§ã¯PreUpdate
/ PostUpdate
åŒã³åºãPostUpdate
ã
äŸãèŠãŠã¿ãŸãããã ããã§ãã€ãã³ããªã¹ãBeanã¯ã1è¡ã®ã³ãŒãã§ãšã³ãã£ãã£ã¯ã©ã¹ã«æ¥ç¶ããŸãã @Listeners
ã¢ãããŒã·ã§ã³ã¯ããªã¹ãã¯ã©ã¹ã®ååã@Listeners
ããŸãã
@Listeners("passportnumber_PersonEntityListener") @NamePattern("%s|name") @Table(name = "PASSPORTNUMBER_PERSON") @Entity(name = "passportnumber$Person") @ValidPassportNumber(groups = {Default.class, UiCrossFieldChecks.class}) @FraudDetectionFlag public class Person extends StandardEntity { ... }
Person.java
ãªã¹ããŒã®å®è£
èªäœã¯æ¬¡ã®ããã«ãªããŸãã
@Component("passportnumber_PersonEntityListener") public class PersonEntityListener implements BeforeDeleteEntityListener<Person>, BeforeInsertEntityListener<Person>, BeforeUpdateEntityListener<Person> { @Override public void onBeforeDelete(Person person, EntityManager entityManager) { if (!checkPassportIsUnique(person.getPassportNumber(), person.getCountry(), entityManager)) { throw new ValidationException( "Passport and country code combination isn't unique"); } } @Override public void onBeforeInsert(Person person, EntityManager entityManager) {
PersonEntityListener.java
ãšã³ãã£ãã£ãªã¹ããŒã¯ã次ã®å Žåã«æé©ã§ãã
- ãšã³ãã£ãã£ãªããžã§ã¯ããããŒã¿ããŒã¹ã«ä¿åãããåã«ããã©ã³ã¶ã¯ã·ã§ã³å
ã®ããŒã¿ã確èªããå¿
èŠããããŸãã
- æ€èšŒããã»ã¹äžã«ããŒã¿ããŒã¹ã®ããŒã¿ã確èªããå¿
èŠããããŸããããšãã°ã泚æãåãä»ããã®ã«ååãªè£œåãåšåº«ã«ããããšã確èªããŸãã
Order
ãªã©ã®ãšã³ãã£ãã£ãªããžã§ã¯ãã ãã§ãªããé¢é£ãããšã³ãã£ãã£ïŒ Order
ãšã³ãã£ãã£ã®OrderItems
ãªããžã§ã¯ããªã©ïŒã調ã¹ãå¿
èŠããããŸãã- ç¹å®ã®ãšã³ãã£ãã£ã¯ã©ã¹ïŒããšãã°ã
Order
ããã³OrderItem
ã®ã¿ïŒã«å¯ŸããŠã®ã¿æ¿å
¥ãæŽæ°ããŸãã¯åé€ã®æäœã远跡ãããã©ã³ã¶ã¯ã·ã§ã³äžã«ä»ã®ãšã³ãã£ãã£ã¯ã©ã¹ã®å€æŽã確èªããå¿
èŠã¯ãããŸããã
ãã©ã³ã¶ã¯ã·ã§ã³ãªã¹ããŒ
CUBAãã©ã³ã¶ã¯ã·ã§ã³ãªã¹ããŒããã©ã³ã¶ã¯ã·ã§ã³ã®ã³ã³ããã¹ãã§åäœããŸããããšã³ãã£ãã£ãªã¹ããŒãšæ¯èŒããŠãåããŒã¿ããŒã¹ãã©ã³ã¶ã¯ã·ã§ã³ã«å¯ŸããŠåŒã³åºãããŸãã
ãããã¯åœŒãã«è¶
匷åãäžããŸãïŒ
- äœã圌ãã®æ³šæãéžããããšã¯ã§ããŸããã
ããããåãããšã圌ãã®æ¬ ç¹ã«ãã£ãŠæ±ºå®ãããŸãïŒ
- æžãã®ãããé£ããã
- ããã©ãŒãã³ã¹ã倧å¹
ã«äœäžãããå¯èœæ§ããããŸãã
- ãããã¯éåžžã«æ
éã«äœæããå¿
èŠããããŸãããã©ã³ã¶ã¯ã·ã§ã³ãªã¹ããŒã®ãã°ã¯ãã¢ããªã±ãŒã·ã§ã³ã®åæããŒãã劚ããå¯èœæ§ããããŸãã
ãããã£ãŠããã©ã³ã¶ã¯ã·ã§ã³ãªã¹ãã¯ãåãã¢ã«ãŽãªãºã ã䜿çšããŠããŸããŸãªçš®é¡ã®ãšã³ãã£ãã£ãæ€æ»ããå¿
èŠãããå ŽåïŒããšãã°ããã¹ãŠã®ããžãã¹ãªããžã§ã¯ãã«å¯Ÿå¿ããåäžã®ãµãŒãã¹ã§ãµã€ããŒè©æ¬ºã®ãã¹ãŠã®ããŒã¿ããã§ãã¯ããå ŽåïŒã«é©ãããœãªã¥ãŒã·ã§ã³ã§ãã

ãšã³ãã£ãã£ã«@FraudDetectionFlag
泚éããããã©ããã確èªããååšããå Žåã¯äžæ£æ€åºãéå§ãããµã³ãã«ãèŠãŠãã ããã ç¹°ãè¿ããŸããããã®ã¡ãœããã¯åããŒã¿ããŒã¹ãã©ã³ã¶ã¯ã·ã§ã³ãã³ãããããåã«ã·ã¹ãã ã§åŒã³åºãããã®ã§ãã³ãŒãã¯ã§ããã ãå°ãªããªããžã§ã¯ãããã§ãã¯ããããšããŸãã
@Component("passportnumber_ApplicationTransactionListener") public class ApplicationTransactionListener implements BeforeCommitTransactionListener { private Logger log = LoggerFactory.getLogger(ApplicationTransactionListener.class); @Override public void beforeCommit(EntityManager entityManager, Collection<Entity> managedEntities) { for (Entity entity : managedEntities) { if (entity instanceof StandardEntity && !((StandardEntity) entity).isDeleted() && entity.getClass().isAnnotationPresent(FraudDetectionFlag.class) && !fraudDetectorFeedAndFastCheck(entity)) { logFraudDetectionFailure(log, entity); String msg = String.format( "Fraud detection failure in '%s' with id = '%s'", entity.getClass().getSimpleName(), entity.getId()); throw new ValidationException(msg); } } } ... }
ApplicationTransactionListener.java
ãã©ã³ã¶ã¯ã·ã§ã³ãªã¹ããŒã«ãªãã«ã¯ããããŒãžãBeanãBeforeCommitTransactionListener
ã€ã³ã¿ãŒãã§ã€ã¹ãšbeforeCommit
ã¡ãœãããå®è£
ããå¿
èŠããããŸãã ãã©ã³ã¶ã¯ã·ã§ã³ãªã¹ããŒã¯ãã¢ããªã±ãŒã·ã§ã³ã®èµ·åæã«èªåçã«ãã€ã³ãããŸãã CUBAã¯ã BeforeCommitTransactionListener
ãŸãã¯AfterCompleteTransactionListener
ãå®è£
ãããã¹ãŠã®ã¯ã©ã¹ããã©ã³ã¶ã¯ã·ã§ã³ãªã¹ããŒãšããŠç»é²ããŸãã
ãããã«
Beanæ€èšŒïŒJPA 303ã349ãããã³980ïŒã¯ãäŒæ¥ãããžã§ã¯ãã§çºçããããŒã¿æ€èšŒã±ãŒã¹ã®95ïŒ
ã®ä¿¡é Œã§ããåºç€ãšããŠåœ¹ç«ã€ã¢ãããŒãã§ãã ãã®ã¢ãããŒãã®äž»ãªå©ç¹ã¯ãæ€èšŒããžãã¯ã®ã»ãšãã©ããã¡ã€ã³ã¢ãã«ã¯ã©ã¹ã«çŽæ¥éäžããŠããããšã§ãã ãããã£ãŠãèŠã€ãããããèªã¿ããããä¿å®ãç°¡åã§ãã SpringãCUBAãããã³ä»ã®å€ãã®ã©ã€ãã©ãªã¯ãããã®æšæºããµããŒãããUIã¬ã€ã€ãŒã§ããŒã¿ãåä¿¡ãããšããæ€èšŒæžã¿ã®ã¡ãœãããåŒã³åºããšãããŸãã¯ORMãä»ããŠããŒã¿ãä¿åãããšãã«æ€èšŒãã§ãã¯ãèªåçã«å®è¡ããŸãã
äžéšã®ãœãããŠã§ã¢éçºè
ã¯ããµããžã§ã¯ãã¢ãã«ã®ã¯ã©ã¹ã¬ãã«ã§ã®æ€èšŒãäžèªç¶ã§è€éããããšèŠãªããUIã¬ãã«ã§ã®ããŒã¿æ€èšŒã¯ããªã广çãªæŠç¥ã§ãããšèšããŸãã ãã ããã³ã³ããŒãã³ãããã³UIã³ã³ãããŒã©ãŒã®å€æ°ã®æ€èšŒãã€ã³ãã¯ãæãåççãªã¢ãããŒãã§ã¯ãªããšèããŠããŸãã , , , , , listener' .
, , :
- JPA , , DDL.
- Bean Validation â , , , . , .
- bean validation, . , , REST.
- Entity listeners: , Bean Validation, . , . Hibernate .
- Transaction listeners â , , . , , .
PS: , Java, , , .
é衚瀺ã®ããã¹ãæšæºãšãã®å®è£
峿žé€š