From 3b55c97e0fd4253cbbf12fbf94e92c5bb2a1749d Mon Sep 17 00:00:00 2001 From: minuk926 Date: Fri, 14 Jan 2022 18:12:02 +0900 Subject: [PATCH] graphql --- build.gradle | 23 +++++--- .../java/com/xit/biz/cmm/entity/CmmUser.java | 23 ++++---- .../xit/biz/sample/graphql/MyMutation.java | 31 +++++++++++ .../com/xit/biz/sample/graphql/MyQuery.java | 22 ++++++++ .../xit/biz/sample/graphql/PostResolver.java | 19 +++++++ .../biz/sample/graphql/dto/PostResponse.java | 36 ++++++++++++ .../xit/biz/sample/graphql/entity/Author.java | 22 ++++++++ .../xit/biz/sample/graphql/entity/Post.java | 25 +++++++++ .../graphql/repository/AuthorRepository.java | 9 +++ .../graphql/repository/PostRepository.java | 15 +++++ .../service/CustomOAuth2UserService.java | 5 +- .../com/xit/core/support/jpa/AuditEntity.java | 12 ++-- src/main/resources/config/application.yml | 38 +++++++++++-- src/main/resources/graphqls/cmmuser.graphqls | 55 +++++++++++++++++++ src/main/resources/graphqls/root.graphqls | 0 15 files changed, 301 insertions(+), 34 deletions(-) create mode 100644 src/main/java/com/xit/biz/sample/graphql/MyMutation.java create mode 100644 src/main/java/com/xit/biz/sample/graphql/MyQuery.java create mode 100644 src/main/java/com/xit/biz/sample/graphql/PostResolver.java create mode 100644 src/main/java/com/xit/biz/sample/graphql/dto/PostResponse.java create mode 100644 src/main/java/com/xit/biz/sample/graphql/entity/Author.java create mode 100644 src/main/java/com/xit/biz/sample/graphql/entity/Post.java create mode 100644 src/main/java/com/xit/biz/sample/graphql/repository/AuthorRepository.java create mode 100644 src/main/java/com/xit/biz/sample/graphql/repository/PostRepository.java create mode 100644 src/main/resources/graphqls/cmmuser.graphqls create mode 100644 src/main/resources/graphqls/root.graphqls diff --git a/build.gradle b/build.gradle index d228668..37f44bb 100644 --- a/build.gradle +++ b/build.gradle @@ -64,21 +64,12 @@ dependencies { //-----------------------------------------------------------------------------------// // spring boot core implementation 'org.springframework.boot:spring-boot-starter' - // spring-boot-starter-validation을 포함 - // 2.3 이상 부터 제외, 따라서 반드시 Validation 필요 implementation 'org.springframework.boot:spring-boot-starter-web' - - implementation 'org.springframework.boot:spring-boot-starter-hateoas' implementation 'org.springframework.boot:spring-boot-configuration-processor' implementation 'org.springframework.boot:spring-boot-starter-security' implementation 'org.springframework.boot:spring-boot-starter-data-jpa' implementation 'org.springframework.boot:spring-boot-starter-jdbc' - // jta module - //implementation('org.springframework.boot:spring-boot-starter-jta-atomikos') - - // yaml 다국화 lib - implementation 'net.rakugakibox.util:yaml-resource-bundle:1.2' // spring-boot 2.3 까지는 사용 불가 - spring-boot-starter-web에 포함되어 있다 // hibernate-validator:5.2.4.Final 사용 @@ -86,6 +77,20 @@ dependencies { // spring-boot 2.3 까지는 아래 lib 사용 //implementation 'org.hibernate:hibernate-validator:5.2.4.Final' + // graphql + implementation 'com.graphql-java-kickstart:graphql-spring-boot-starter:12.0.0' + //implementation 'com.graphql-java-kickstart:graphiql-spring-boot-starter:12.0.0' + implementation 'com.graphql-java-kickstart:graphql-java-tools:12.0.1' + // graphql-like sql usual + implementation 'io.leangen.graphql:graphql-spqr-spring-boot-starter:0.0.6' + + // jta module + //implementation('org.springframework.boot:spring-boot-starter-jta-atomikos') + + // yaml 다국화 lib + implementation 'net.rakugakibox.util:yaml-resource-bundle:1.2' + + // social login implementation 'org.springframework.boot:spring-boot-starter-oauth2-client' //-----------------------------------------------------------------------------------// diff --git a/src/main/java/com/xit/biz/cmm/entity/CmmUser.java b/src/main/java/com/xit/biz/cmm/entity/CmmUser.java index 48e56cb..3b3043f 100644 --- a/src/main/java/com/xit/biz/cmm/entity/CmmUser.java +++ b/src/main/java/com/xit/biz/cmm/entity/CmmUser.java @@ -44,13 +44,6 @@ public class CmmUser extends AuditEntity implements Serializable { //extends Rep //@Size(max = 64) private String userId; - @Setter - @Schema(required = true, title = "사용자 이름", example = "홍길동") - @Column(name="user_name", length = 100, nullable = false) - //@NotNull - //@Size(max = 100) - private String userName; - //TODO : ??? @Setter @JsonProperty(access = JsonProperty.Access.WRITE_ONLY) @@ -61,10 +54,11 @@ public class CmmUser extends AuditEntity implements Serializable { //extends Rep private String password; @Setter - @Schema(title = "전화번호", example = "01012341234") - @Column(name="user_mbl", length = 100) - //@Size(max = 128) - private String userMbl; + @Schema(required = true, title = "사용자 이름", example = "홍길동") + @Column(name="user_name", length = 100, nullable = false) + //@NotNull + //@Size(max = 100) + private String userName; @Setter @Schema(title = "사용자 이메일", example = "a@b.com") @@ -72,6 +66,13 @@ public class CmmUser extends AuditEntity implements Serializable { //extends Rep //@Size(max = 100) private String email; + @Setter + @Schema(title = "전화번호", example = "01012341234") + @Column(name="user_mbl", length = 100) + //@Size(max = 128) + private String userMbl; + + @Setter @Column(name = "role_type", length = 20, nullable = false) @Enumerated(EnumType.STRING) diff --git a/src/main/java/com/xit/biz/sample/graphql/MyMutation.java b/src/main/java/com/xit/biz/sample/graphql/MyMutation.java new file mode 100644 index 0000000..54d942a --- /dev/null +++ b/src/main/java/com/xit/biz/sample/graphql/MyMutation.java @@ -0,0 +1,31 @@ +package com.xit.biz.sample.graphql; + +//import com.coxautodev.graphql.tools.GraphQLMutationResolver; +import com.xit.biz.sample.graphql.dto.PostResponse; +import com.xit.biz.sample.graphql.entity.Post; +import com.xit.biz.sample.graphql.repository.AuthorRepository; +import com.xit.biz.sample.graphql.repository.PostRepository; +import graphql.kickstart.tools.GraphQLMutationResolver; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Component; + +@Component +@RequiredArgsConstructor +public class MyMutation implements GraphQLMutationResolver { + private final PostRepository postRepository; + private final AuthorRepository authorRepository; + + public PostResponse writePost(String title, String text, String category) { + //public Post writePost(String title, String text, String category) { + Post post = new Post(); + post.setTitle(title); + post.setText(text); + post.setCategory(category); + //post.setAuthor(authorRepository.getOne(1L)); + + final Post save = postRepository.save(post); + + return PostResponse.from(save); + //return save; + } +} \ No newline at end of file diff --git a/src/main/java/com/xit/biz/sample/graphql/MyQuery.java b/src/main/java/com/xit/biz/sample/graphql/MyQuery.java new file mode 100644 index 0000000..2678208 --- /dev/null +++ b/src/main/java/com/xit/biz/sample/graphql/MyQuery.java @@ -0,0 +1,22 @@ +package com.xit.biz.sample.graphql; + +//import com.coxautodev.graphql.tools.GraphQLQueryResolver; +import com.xit.biz.sample.graphql.dto.PostResponse; +import com.xit.biz.sample.graphql.entity.Post; +import com.xit.biz.sample.graphql.repository.PostRepository; +import graphql.kickstart.tools.GraphQLQueryResolver; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Component; + +import java.util.List; + +@Component +@RequiredArgsConstructor +public class MyQuery implements GraphQLQueryResolver { + private final PostRepository postRepository; + + public List getRecentPosts(int count, int offset) { + final List all = postRepository.findAll(); + return PostResponse.from(all); + } +} \ No newline at end of file diff --git a/src/main/java/com/xit/biz/sample/graphql/PostResolver.java b/src/main/java/com/xit/biz/sample/graphql/PostResolver.java new file mode 100644 index 0000000..8e204b9 --- /dev/null +++ b/src/main/java/com/xit/biz/sample/graphql/PostResolver.java @@ -0,0 +1,19 @@ +package com.xit.biz.sample.graphql; + +//import com.coxautodev.graphql.tools.GraphQLResolver; +import com.xit.biz.sample.graphql.dto.PostResponse; +import com.xit.biz.sample.graphql.entity.Author; +import com.xit.biz.sample.graphql.repository.AuthorRepository; +import graphql.kickstart.tools.GraphQLResolver; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Component; + +@Component +@RequiredArgsConstructor +public class PostResolver implements GraphQLResolver { + private final AuthorRepository authorRepository; + + public Author getAuthor(PostResponse postResponse) { + return authorRepository.findById(postResponse.getAuthor().getId()).orElseThrow(NullPointerException::new); + } +} \ No newline at end of file diff --git a/src/main/java/com/xit/biz/sample/graphql/dto/PostResponse.java b/src/main/java/com/xit/biz/sample/graphql/dto/PostResponse.java new file mode 100644 index 0000000..1c5d448 --- /dev/null +++ b/src/main/java/com/xit/biz/sample/graphql/dto/PostResponse.java @@ -0,0 +1,36 @@ +package com.xit.biz.sample.graphql.dto; + +import com.xit.biz.sample.graphql.entity.Author; +import com.xit.biz.sample.graphql.entity.Post; +import lombok.*; + +import java.util.Collection; +import java.util.List; +import java.util.stream.Collectors; + +@Getter +@Setter +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class PostResponse { + private long id; + private String title; + private String text; + private String category; + private Author author; + + public static List from(Collection entities) { + return entities.stream().map(PostResponse::from).collect(Collectors.toList()); + } + + public static PostResponse from(Post entity) { + return PostResponse.builder() + .id(entity.getId()) + .title(entity.getTitle()) + .text(entity.getText()) + .category(entity.getCategory()) + //.author(entity.getAuthor()) + .build(); + } +} \ No newline at end of file diff --git a/src/main/java/com/xit/biz/sample/graphql/entity/Author.java b/src/main/java/com/xit/biz/sample/graphql/entity/Author.java new file mode 100644 index 0000000..9ba6fae --- /dev/null +++ b/src/main/java/com/xit/biz/sample/graphql/entity/Author.java @@ -0,0 +1,22 @@ +package com.xit.biz.sample.graphql.entity; + +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.Setter; + +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.Id; + +@Entity +@Getter +@Setter +@EqualsAndHashCode(of = "id") +public class Author { + @Id + @GeneratedValue + private Long id; + + private String name; + private String thumbnail; +} \ No newline at end of file diff --git a/src/main/java/com/xit/biz/sample/graphql/entity/Post.java b/src/main/java/com/xit/biz/sample/graphql/entity/Post.java new file mode 100644 index 0000000..91c17b4 --- /dev/null +++ b/src/main/java/com/xit/biz/sample/graphql/entity/Post.java @@ -0,0 +1,25 @@ +package com.xit.biz.sample.graphql.entity; + +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.Setter; + +import javax.persistence.*; + +@Entity +@Getter +@Setter +@EqualsAndHashCode(of = "id") +public class Post { + @Id + @GeneratedValue + private Long id; + + private String title; + private String text; + private String category; + +// @ManyToOne(fetch = FetchType.LAZY, optional = false) +// @JoinColumn(name = "author_id") +// private Author author; +} \ No newline at end of file diff --git a/src/main/java/com/xit/biz/sample/graphql/repository/AuthorRepository.java b/src/main/java/com/xit/biz/sample/graphql/repository/AuthorRepository.java new file mode 100644 index 0000000..527dedb --- /dev/null +++ b/src/main/java/com/xit/biz/sample/graphql/repository/AuthorRepository.java @@ -0,0 +1,9 @@ +package com.xit.biz.sample.graphql.repository; + +import com.xit.biz.sample.graphql.entity.Author; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +@Repository +public interface AuthorRepository extends JpaRepository { +} \ No newline at end of file diff --git a/src/main/java/com/xit/biz/sample/graphql/repository/PostRepository.java b/src/main/java/com/xit/biz/sample/graphql/repository/PostRepository.java new file mode 100644 index 0000000..5ba1a2e --- /dev/null +++ b/src/main/java/com/xit/biz/sample/graphql/repository/PostRepository.java @@ -0,0 +1,15 @@ +package com.xit.biz.sample.graphql.repository; + +import com.xit.biz.sample.graphql.entity.Post; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import org.springframework.stereotype.Repository; + +import java.util.List; + +@Repository +public interface PostRepository extends JpaRepository { + //@Query("SELECT p FROM Post p JOIN FETCH p.author") + @Query("SELECT p FROM Post p") + List findAll(); +} \ No newline at end of file diff --git a/src/main/java/com/xit/core/oauth2/oauth/service/CustomOAuth2UserService.java b/src/main/java/com/xit/core/oauth2/oauth/service/CustomOAuth2UserService.java index d4bfd64..068b60f 100644 --- a/src/main/java/com/xit/core/oauth2/oauth/service/CustomOAuth2UserService.java +++ b/src/main/java/com/xit/core/oauth2/oauth/service/CustomOAuth2UserService.java @@ -21,7 +21,6 @@ import org.springframework.stereotype.Service; import java.time.LocalDateTime; import java.util.Objects; import java.util.Optional; -import java.util.UUID; @Service @RequiredArgsConstructor @@ -94,8 +93,8 @@ public class CustomOAuth2UserService extends DefaultOAuth2UserService { user.setCmmUserId(CommUtil.getStringFromUUID()); user.setCreatedBy(userInfo.getId()); user.setModifiedBy(userInfo.getId()); - user.setCreatedDate(localDateTime); - user.setModifiedDate(localDateTime); + user.setCreatedDtm(localDateTime); + user.setModifiedDtm(localDateTime); return userRepository.saveAndFlush(user); } diff --git a/src/main/java/com/xit/core/support/jpa/AuditEntity.java b/src/main/java/com/xit/core/support/jpa/AuditEntity.java index 3405c57..a91f3e8 100644 --- a/src/main/java/com/xit/core/support/jpa/AuditEntity.java +++ b/src/main/java/com/xit/core/support/jpa/AuditEntity.java @@ -43,18 +43,18 @@ public class AuditEntity implements Serializable { @CreatedDate //@JsonIgnore //@Temporal(TemporalType.TIMESTAMP) - //@Column(name = "created_date", updatable = false, columnDefinition = "TIMESTAMP DEFAULT CURRENT_TIMESTAMP") - @Column(name = "created_date", updatable = false) - private LocalDateTime createdDate; + //@Column(name = "created_dtm", updatable = false, columnDefinition = "TIMESTAMP DEFAULT CURRENT_TIMESTAMP") + @Column(name = "created_dtm", updatable = false) + private LocalDateTime createdDtm; @Setter @Schema(description = "변경시 변경일시 자동 할당", example = " ") @LastModifiedDate //@JsonIgnore //@Temporal(TemporalType.TIMESTAMP) - //@Column(name = "modified_date", insertable = false, columnDefinition = "TIMESTAMP DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP") - @Column(name = "modified_date", insertable = false) - private LocalDateTime modifiedDate; + //@Column(name = "modified_dtm", insertable = false, columnDefinition = "TIMESTAMP DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP") + @Column(name = "modified_dtm", insertable = false) + private LocalDateTime modifiedDtm; @Schema(example = "Y", required = true) @Column(name = "use_yn", nullable = false, length = 1) diff --git a/src/main/resources/config/application.yml b/src/main/resources/config/application.yml index 1c79c2e..d9ce3ac 100644 --- a/src/main/resources/config/application.yml +++ b/src/main/resources/config/application.yml @@ -134,6 +134,11 @@ spring: serialization: fail-on-empty-beans: false time-zone: Asia/Seoul + + # devtools + devtools: + livereload: + enabled: true # ================================================================================================================== # spring-doc setting @@ -171,11 +176,8 @@ springdoc: # # profiles 별로 분리 # #cache: false # view-names: thymeleaf/* - - # devtools - devtools: - livereload: - enabled: true + + # ================================================================================================================== # JPA logging lib setting @@ -192,6 +194,32 @@ decorator: tracing: include-parameter-values: true +# ================================================================================================================== +# graphql setting +# ================================================================================================================== +graphql: + servlet: + enabled: true + mapping: /graphql + corsEnabled: false + cors: + allowed-origins: http://localhost:3000 + allowed-methods: GET, HEAD, POST, PATCH + exception-handlers-enabled: true + context-setting: PER_REQUEST_WITH_INSTRUMENTATION + async-mode-enabled: true + tools: + schema-location-pattern: "**/*.graphqls" + introspection-enabled: true + spqr: + gui: + enabled: true + + + + + + # ================================================================================================================== # xit-framework logging setting # ================================================================================================================== diff --git a/src/main/resources/graphqls/cmmuser.graphqls b/src/main/resources/graphqls/cmmuser.graphqls new file mode 100644 index 0000000..6a7c447 --- /dev/null +++ b/src/main/resources/graphqls/cmmuser.graphqls @@ -0,0 +1,55 @@ +schema { + query: Query, + mutation: Mutation +} + +type CmmUser { + cmmUserId: String + userId: String! + password: String! + userName: String! + email: String! + userMbl: String + providerType: String! + profileImageUrl: String + emailVerifiedYn: String! + roleType: RoleType + #created_by: String + #modified_by: String +} + +enum RoleType { + USER + ADMIN + GUEST +} + +input CmmUserDto { + cmmUserId: String + userId: String! + password: String! + userName: String! + email: String! + userMbl: String + providerType: String! + profileImageUrl: String + emailVerifiedYn: String! + roleType: RoleType + #createdBy: String + #modifiedBy: String +} + +# Root query +type Query { + getUserByUserId(userId: String!): CmmUser! +} + + + +# Root Mutation +type Mutation { + createUser(cmmUserDto: CmmUserDto!): CmmUser! +} + + + diff --git a/src/main/resources/graphqls/root.graphqls b/src/main/resources/graphqls/root.graphqls new file mode 100644 index 0000000..e69de29