GVKun编程网logo

使用 Spring Boot + RestAPI + JPA + CrudRepository +MySQL 创建 CRUD 时出现异常

5

关于使用SpringBoot+RestAPI+JPA+CrudRepository+MySQL创建CRUD时出现异常的问题就给大家分享到这里,感谢你花时间阅读本站内容,更多关于gitclone时出现异

关于使用 Spring Boot + RestAPI + JPA + CrudRepository +MySQL 创建 CRUD 时出现异常的问题就给大家分享到这里,感谢你花时间阅读本站内容,更多关于git clone 时出现异常:fatal: unable to access 'https://github.com/spring-projects/spring-framework.gi、IntelliJ IDEA 2017 版 spring-boot2.0.2 搭建 JPA springboot DataSource JPA 环境搭建,JPA 注解 @ManyToOne 使用详情;JPA...、JPA CrudRepository 关于删除 DataIntegrityViolationException 错误消息、restapi(2)- generic restful CRUD:通用的restful风格数据库表维护工具等相关知识的信息别忘了在本站进行查找喔。

本文目录一览:

使用 Spring Boot + RestAPI + JPA + CrudRepository +MySQL 创建 CRUD 时出现异常

使用 Spring Boot + RestAPI + JPA + CrudRepository +MySQL 创建 CRUD 时出现异常

如何解决使用 Spring Boot + RestAPI + JPA + CrudRepository +MySQL 创建 CRUD 时出现异常

我正在尝试使用 Spring Boot + RestAPI + JPA + CrudRepository +MysqL 创建我的第一个项目电影存储库。我得到了非常难以理解的巨大堆栈跟踪。

实体类:

  1. package com.it.skill.movies;
  2. import javax.persistence.Column;
  3. import javax.persistence.Entity;
  4. import javax.persistence.Id;
  5. import javax.persistence.Table;
  6. @Entity
  7. @Table(name="movie")
  8. public class Movie {
  9. @Id
  10. private String mNo;
  11. @Column
  12. private String mName;
  13. @Column
  14. private Integer rating;
  15. @Column
  16. private String genre;
  17. public Movie() {}
  18. public Movie(String mNo,String mName,int rating,String genre) {
  19. super();
  20. this.mNo = mNo;
  21. this.mName = mName;
  22. this.rating = rating;
  23. this.genre = genre;
  24. }
  25. public String getmNo() {
  26. return mNo;
  27. }
  28. public void setmNo(String mNo) {
  29. this.mNo = mNo;
  30. }
  31. public String getmName() {
  32. return mName;
  33. }
  34. public void setmName(String mName) {
  35. this.mName = mName;
  36. }
  37. public int getrating() {
  38. return rating;
  39. }
  40. public void setrating(int rating) {
  41. this.rating = rating;
  42. }
  43. public String getGenre() {
  44. return genre;
  45. }
  46. public void setGenre(String genre) {
  47. this.genre = genre;
  48. }
  49. @Override
  50. public String toString() {
  51. return "Movie [mNo=" + mNo + ",mName=" + mName + ",rating=" + rating + ",genre=" + genre + "]";
  52. }
  53. }

界面:

  1. package com.it.skill.repo;
  2. import org.springframework.data.repository.CrudRepository;
  3. import org.springframework.stereotype.Repository;
  4. import com.it.skill.movies.Movie;
  5. @Repository
  6. public interface IMovieRepo extends CrudRepository<Movie,Integer>{
  7. public Movie addMovie(String movieName,Integer rating,String Genre);
  8. }

服务类

  1. package com.it.skill.service;
  2. import org.springframework.beans.factory.annotation.Autowired;
  3. import org.springframework.stereotype.Service;
  4. import com.it.skill.movies.Movie;
  5. import com.it.skill.repo.IMovieRepo;
  6. @Service
  7. public class IMovieService {
  8. @Autowired
  9. private IMovieRepo movieRepository;
  10. public Integer addMovie(Movie movie)
  11. {
  12. //Movie movie = new Movie();
  13. movieRepository.save(movie);
  14. return movie.getrating();
  15. }
  16. }

以下是我的电影控制器类

  1. package com.it.skill.controller;
  2. import org.springframework.beans.factory.annotation.Autowired;
  3. import org.springframework.http.HttpStatus;
  4. import org.springframework.http.ResponseEntity;
  5. import org.springframework.web.bind.annotation.PostMapping;
  6. import org.springframework.web.bind.annotation.RequestBody;
  7. import org.springframework.web.bind.annotation.RestController;
  8. import com.it.skill.movies.Movie;
  9. import com.it.skill.service.IMovieService;
  10. @RestController
  11. public class MovieController {
  12. @Autowired
  13. private IMovieService movieService;
  14. //add single project
  15. @PostMapping(path = "/movies/add/",consumes = "application/json")
  16. public ResponseEntity<String> addNewMovie(@RequestBody Movie movie) {
  17. Integer irating = movieService.addMovie(movie);
  18. if(irating!=null)
  19. {
  20. return new ResponseEntity<String>("Movie saved with rating: " +irating,HttpStatus.CREATED);
  21. }
  22. return new ResponseEntity<String>("Movie not saved",HttpStatus.NOT_ACCEPTABLE);
  23. }
  24. }

以下是我的 Application.properties 文件

  1. spring.application.name=Restful-App-Movies
  2. server.servlet.context-path=/Restful-App-Movies
  3. server.port=8082
  4. ## MysqL
  5. spring.datasource.url=jdbc:MysqL://localhost:3306/sakila
  6. spring.datasource.username=root
  7. spring.datasource.password=root

以下是我的 pom.xml

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  3. xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
  4. <modelVersion>4.0.0</modelVersion>
  5. <parent>
  6. <groupId>org.springframework.boot</groupId>
  7. <artifactId>spring-boot-starter-parent</artifactId>
  8. <version>2.4.6</version>
  9. <relativePath/> <!-- lookup parent from repository -->
  10. </parent>
  11. <groupId>com.it.skill</groupId>
  12. <artifactId>rest-app-1</artifactId>
  13. <version>0.0.1-SNAPSHOT</version>
  14. <name>rest-app-1</name>
  15. <description>Demo project for Spring Boot</description>
  16. <properties>
  17. <java.version>1.8</java.version>
  18. </properties>
  19. <dependencies>
  20. <!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-data-jpa -->
  21. <dependency>
  22. <groupId>org.springframework.boot</groupId>
  23. <artifactId>spring-boot-starter-data-jpa</artifactId>
  24. </dependency>
  25. <dependency>
  26. <groupId>MysqL</groupId>
  27. <artifactId>mysql-connector-java</artifactId>
  28. </dependency>
  29. <!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.dataformat/jackson-dataformat-xml -->
  30. <dependency>
  31. <groupId>com.fasterxml.jackson.dataformat</groupId>
  32. <artifactId>jackson-dataformat-xml</artifactId>
  33. <version>2.11.3</version>
  34. </dependency>
  35. <dependency>
  36. <groupId>org.springframework.boot</groupId>
  37. <artifactId>spring-boot-starter-web</artifactId>
  38. </dependency>
  39. <dependency>
  40. <groupId>org.springframework.boot</groupId>
  41. <artifactId>spring-boot-starter-test</artifactId>
  42. <scope>test</scope>
  43. </dependency>
  44. <!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-devtools -->
  45. <dependency>
  46. <groupId>org.springframework.boot</groupId>
  47. <artifactId>spring-boot-devtools</artifactId>
  48. </dependency>
  49. </dependencies>
  50. <build>
  51. <plugins>
  52. <plugin>
  53. <groupId>org.springframework.boot</groupId>
  54. <artifactId>spring-boot-maven-plugin</artifactId>
  55. </plugin>
  56. </plugins>
  57. </build>
  58. </project>

2021-06-11 12:14:41.308 WARN 4108 --- [restartedMain] ConfigServletWebServerApplicationContext:上下文初始化期间遇到异常 - 取消刷新尝试:org.springframework.beans.factory.UnsatisfiedDependencyException:创建名为“movieController”的 bean 时出错'':通过字段''movieService''表达的不满意的依赖;嵌套异常是 org.springframework.beans.factory.UnsatisfiedDependencyException:创建名为“IMovieService”的 bean 时出错:通过字段“movieRepository”表达的不满意依赖;嵌套异常是 org.springframework.beans.factory.BeanCreationException:在 JpaRepositoriesRegistrar.EnableJpaRepositoriesConfiguration 上声明的 @EnableJpaRepositories 中定义的 com.it.skill.repo.IMovieRepo 中定义的名称为 ''IMovieRepo'' 的 bean 创建时出错:调用 init 方法失败;嵌套异常是 java.lang.IllegalArgumentException:无法为方法 public abstract com.it.skill.movi​​es.Movie com.it.skill.repo.IMovieRepo.addMovie(java.lang.String,java.lang.Integer,java.lang.String)!找不到类型 Movie 的属性 addMovie! 2021-06-11 12:14:41.308 INFO 4108 --- [restartedMain] j.LocalContainerEntityManagerfactorybean:关闭 JPA EntityManagerFactory 以获取持久性单元“默认” 2021-06-11 12:14:41.312 INFO 4108 --- [restartedMain] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - 关闭启动... 2021-06-11 12:14:41.322 INFO 4108 --- [restartedMain] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - 关闭完成。 2021-06-11 12:14:41.324 INFO 4108 --- [restartedMain] o.apache.catalina.core.StandardService:停止服务 [Tomcat] 2021-06-11 12:14:41.337 INFO 4108 --- [restartedMain] ConditionEvaluationReportLoggingListener :

  1. Error starting ApplicationContext. To display the conditions report re-run your application with ''debug'' enabled.
  2. 2021-06-11 12:14:41.362 ERROR 4108 --- [ restartedMain] o.s.boot.SpringApplication : Application run Failed
  3. org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name ''movieController'': Unsatisfied dependency expressed through field ''movieService''; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name ''IMovieService'': Unsatisfied dependency expressed through field ''movieRepository''; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name ''IMovieRepo'' defined in com.it.skill.repo.IMovieRepo defined in @EnableJpaRepositories declared on JpaRepositoriesRegistrar.EnableJpaRepositoriesConfiguration: Invocation of init method Failed; nested exception is java.lang.IllegalArgumentException: Failed to create query for method public abstract com.it.skill.movies.Movie com.it.skill.repo.IMovieRepo.addMovie(java.lang.String,java.lang.String)! No property addMovie found for type Movie!
  4. at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.resolveFieldValue(AutowiredAnnotationBeanPostProcessor.java:660) ~[spring-beans-5.3.7.jar:5.3.7]
  5. at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:640) ~[spring-beans-5.3.7.jar:5.3.7]
  6. at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:119) ~[spring-beans-5.3.7.jar:5.3.7]
  7. at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessproperties(AutowiredAnnotationBeanPostProcessor.java:399) ~[spring-beans-5.3.7.jar:5.3.7]
  8. at org.springframework.beans.factory.support.AbstractAutowireCapablebeanfactory.populateBean(AbstractAutowireCapablebeanfactory.java:1413) ~[spring-beans-5.3.7.jar:5.3.7]
  9. at org.springframework.beans.factory.support.AbstractAutowireCapablebeanfactory.doCreateBean(AbstractAutowireCapablebeanfactory.java:601) ~[spring-beans-5.3.7.jar:5.3.7]
  10. at org.springframework.beans.factory.support.AbstractAutowireCapablebeanfactory.createBean(AbstractAutowireCapablebeanfactory.java:524) ~[spring-beans-5.3.7.jar:5.3.7]
  11. at org.springframework.beans.factory.support.Abstractbeanfactory.lambda$doGetBean$0(Abstractbeanfactory.java:335) ~[spring-beans-5.3.7.jar:5.3.7]
  12. at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) ~[spring-beans-5.3.7.jar:5.3.7]
  13. at org.springframework.beans.factory.support.Abstractbeanfactory.doGetBean(Abstractbeanfactory.java:333) ~[spring-beans-5.3.7.jar:5.3.7]
  14. at org.springframework.beans.factory.support.Abstractbeanfactory.getBean(Abstractbeanfactory.java:208) ~[spring-beans-5.3.7.jar:5.3.7]
  15. at org.springframework.beans.factory.support.DefaultListablebeanfactory.preInstantiateSingletons(DefaultListablebeanfactory.java:944) ~[spring-beans-5.3.7.jar:5.3.7]
  16. at org.springframework.context.support.AbstractApplicationContext.finishbeanfactoryInitialization(AbstractApplicationContext.java:918) ~[spring-context-5.3.7.jar:5.3.7]
  17. at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:583) ~[spring-context-5.3.7.jar:5.3.7]
  18. at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:144) ~[spring-boot-2.4.6.jar:2.4.6]
  19. at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:771) ~[spring-boot-2.4.6.jar:2.4.6]
  20. at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:763) ~[spring-boot-2.4.6.jar:2.4.6]
  21. at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:438) ~[spring-boot-2.4.6.jar:2.4.6]
  22. at org.springframework.boot.SpringApplication.run(SpringApplication.java:339) ~[spring-boot-2.4.6.jar:2.4.6]
  23. at org.springframework.boot.SpringApplication.run(SpringApplication.java:1329) ~[spring-boot-2.4.6.jar:2.4.6]
  24. at org.springframework.boot.SpringApplication.run(SpringApplication.java:1318) ~[spring-boot-2.4.6.jar:2.4.6]
  25. at com.it.skill.MovieApplication.main(MovieApplication.java:13) ~[classes/:na]
  26. at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]
  27. at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:64) ~[na:na]
  28. at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
  29. at java.base/java.lang.reflect.Method.invoke(Method.java:564) ~[na:na]
  30. at org.springframework.boot.devtools.restart.RestartLauncher.run(RestartLauncher.java:49) ~[spring-boot-devtools-2.4.6.jar:2.4.6]
  31. Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name ''IMovieService'': Unsatisfied dependency expressed through field ''movieRepository''; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name ''IMovieRepo'' defined in com.it.skill.repo.IMovieRepo defined in @EnableJpaRepositories declared on JpaRepositoriesRegistrar.EnableJpaRepositoriesConfiguration: Invocation of init method Failed; nested exception is java.lang.IllegalArgumentException: Failed to create query for method public abstract com.it.skill.movies.Movie com.it.skill.repo.IMovieRepo.addMovie(java.lang.String,java.lang.String)! No property addMovie found for type Movie!
  32. at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.resolveFieldValue(AutowiredAnnotationBeanPostProcessor.java:660) ~[spring-beans-5.3.7.jar:5.3.7]
  33. at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:640) ~[spring-beans-5.3.7.jar:5.3.7]
  34. at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:119) ~[spring-beans-5.3.7.jar:5.3.7]
  35. at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessproperties(AutowiredAnnotationBeanPostProcessor.java:399) ~[spring-beans-5.3.7.jar:5.3.7]
  36. at org.springframework.beans.factory.support.AbstractAutowireCapablebeanfactory.populateBean(AbstractAutowireCapablebeanfactory.java:1413) ~[spring-beans-5.3.7.jar:5.3.7]
  37. at org.springframework.beans.factory.support.AbstractAutowireCapablebeanfactory.doCreateBean(AbstractAutowireCapablebeanfactory.java:601) ~[spring-beans-5.3.7.jar:5.3.7]
  38. at org.springframework.beans.factory.support.AbstractAutowireCapablebeanfactory.createBean(AbstractAutowireCapablebeanfactory.java:524) ~[spring-beans-5.3.7.jar:5.3.7]
  39. at org.springframework.beans.factory.support.Abstractbeanfactory.lambda$doGetBean$0(Abstractbeanfactory.java:335) ~[spring-beans-5.3.7.jar:5.3.7]
  40. at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) ~[spring-beans-5.3.7.jar:5.3.7]
  41. at org.springframework.beans.factory.support.Abstractbeanfactory.doGetBean(Abstractbeanfactory.java:333) ~[spring-beans-5.3.7.jar:5.3.7]
  42. at org.springframework.beans.factory.support.Abstractbeanfactory.getBean(Abstractbeanfactory.java:208) ~[spring-beans-5.3.7.jar:5.3.7]
  43. at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:276) ~[spring-beans-5.3.7.jar:5.3.7]
  44. at org.springframework.beans.factory.support.DefaultListablebeanfactory.doResolveDependency(DefaultListablebeanfactory.java:1380) ~[spring-beans-5.3.7.jar:5.3.7]
  45. at org.springframework.beans.factory.support.DefaultListablebeanfactory.resolveDependency(DefaultListablebeanfactory.java:1300) ~[spring-beans-5.3.7.jar:5.3.7]
  46. at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.resolveFieldValue(AutowiredAnnotationBeanPostProcessor.java:657) ~[spring-beans-5.3.7.jar:5.3.7]
  47. ... 26 common frames omitted
  48. Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name ''IMovieRepo'' defined in com.it.skill.repo.IMovieRepo defined in @EnableJpaRepositories declared on JpaRepositoriesRegistrar.EnableJpaRepositoriesConfiguration: Invocation of init method Failed; nested exception is java.lang.IllegalArgumentException: Failed to create query for method public abstract com.it.skill.movies.Movie com.it.skill.repo.IMovieRepo.addMovie(java.lang.String,java.lang.String)! No property addMovie found for type Movie!
  49. at org.springframework.beans.factory.support.AbstractAutowireCapablebeanfactory.initializeBean(AbstractAutowireCapablebeanfactory.java:1786) ~[spring-beans-5.3.7.jar:5.3.7]
  50. at org.springframework.beans.factory.support.AbstractAutowireCapablebeanfactory.doCreateBean(AbstractAutowireCapablebeanfactory.java:602) ~[spring-beans-5.3.7.jar:5.3.7]
  51. at org.springframework.beans.factory.support.AbstractAutowireCapablebeanfactory.createBean(AbstractAutowireCapablebeanfactory.java:524) ~[spring-beans-5.3.7.jar:5.3.7]
  52. at org.springframework.beans.factory.support.Abstractbeanfactory.lambda$doGetBean$0(Abstractbeanfactory.java:335) ~[spring-beans-5.3.7.jar:5.3.7]
  53. at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) ~[spring-beans-5.3.7.jar:5.3.7]
  54. at org.springframework.beans.factory.support.Abstractbeanfactory.doGetBean(Abstractbeanfactory.java:333) ~[spring-beans-5.3.7.jar:5.3.7]
  55. at org.springframework.beans.factory.support.Abstractbeanfactory.getBean(Abstractbeanfactory.java:208) ~[spring-beans-5.3.7.jar:5.3.7]
  56. at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:276) ~[spring-beans-5.3.7.jar:5.3.7]
  57. at org.springframework.beans.factory.support.DefaultListablebeanfactory.doResolveDependency(DefaultListablebeanfactory.java:1380) ~[spring-beans-5.3.7.jar:5.3.7]
  58. at org.springframework.beans.factory.support.DefaultListablebeanfactory.resolveDependency(DefaultListablebeanfactory.java:1300) ~[spring-beans-5.3.7.jar:5.3.7]
  59. at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.resolveFieldValue(AutowiredAnnotationBeanPostProcessor.java:657) ~[spring-beans-5.3.7.jar:5.3.7]
  60. ... 40 common frames omitted
  61. Caused by: java.lang.IllegalArgumentException: Failed to create query for method public abstract com.it.skill.movies.Movie com.it.skill.repo.IMovieRepo.addMovie(java.lang.String,java.lang.String)! No property addMovie found for type Movie!
  62. at org.springframework.data.jpa.repository.query.PartTreeJpaQuery.<init>(PartTreeJpaQuery.java:96) ~[spring-data-jpa-2.4.9.jar:2.4.9]
  63. at org.springframework.data.jpa.repository.query.JpaQueryLookupStrategy$createqueryLookupStrategy.resolveQuery(JpaQueryLookupStrategy.java:107) ~[spring-data-jpa-2.4.9.jar:2.4.9]
  64. at org.springframework.data.jpa.repository.query.JpaQueryLookupStrategy$CreateIfNotFoundQueryLookupStrategy.resolveQuery(JpaQueryLookupStrategy.java:218) ~[spring-data-jpa-2.4.9.jar:2.4.9]
  65. at org.springframework.data.jpa.repository.query.JpaQueryLookupStrategy$AbstractQueryLookupStrategy.resolveQuery(JpaQueryLookupStrategy.java:81) ~[spring-data-jpa-2.4.9.jar:2.4.9]
  66. at org.springframework.data.repository.core.support.QueryExecutorMethodInterceptor.lookupQuery(QueryExecutorMethodInterceptor.java:100) ~[spring-data-commons-2.4.9.jar:2.4.9]
  67. at org.springframework.data.repository.core.support.QueryExecutorMethodInterceptor.lambda$mapMethodsToQuery$1(QueryExecutorMethodInterceptor.java:93) ~[spring-data-commons-2.4.9.jar:2.4.9]
  68. at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:195) ~[na:na]
  69. at java.base/java.util.Iterator.forEachRemaining(Iterator.java:133) ~[na:na]
  70. at java.base/java.util.Collections$UnmodifiableCollection$1.forEachRemaining(Collections.java:1056) ~[na:na]
  71. at java.base/java.util.Spliterators$IteratorSpliterator.forEachRemaining(Spliterators.java:1801) ~[na:na]
  72. at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:484) ~[na:na]
  73. at java.base/java.util.stream.AbstractPipeline.wrapAndcopyInto(AbstractPipeline.java:474) ~[na:na]
  74. at java.base/java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:913) ~[na:na]
  75. at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234) ~[na:na]
  76. at java.base/java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:578) ~[na:na]
  77. at org.springframework.data.repository.core.support.QueryExecutorMethodInterceptor.mapMethodsToQuery(QueryExecutorMethodInterceptor.java:95) ~[spring-data-commons-2.4.9.jar:2.4.9]
  78. at org.springframework.data.repository.core.support.QueryExecutorMethodInterceptor.lambda$new$0(QueryExecutorMethodInterceptor.java:85) ~[spring-data-commons-2.4.9.jar:2.4.9]
  79. at java.base/java.util.Optional.map(Optional.java:258) ~[na:na]
  80. at org.springframework.data.repository.core.support.QueryExecutorMethodInterceptor.<init>(QueryExecutorMethodInterceptor.java:85) ~[spring-data-commons-2.4.9.jar:2.4.9]
  81. at org.springframework.data.repository.core.support.RepositoryFactorySupport.getRepository(RepositoryFactorySupport.java:303) ~[spring-data-commons-2.4.9.jar:2.4.9]
  82. at org.springframework.data.repository.core.support.RepositoryfactorybeanSupport.lambda$afterPropertiesSet$5(RepositoryfactorybeanSupport.java:323) ~[spring-data-commons-2.4.9.jar:2.4.9]
  83. at org.springframework.data.util.Lazy.getNullable(Lazy.java:230) ~[spring-data-commons-2.4.9.jar:2.4.9]
  84. at org.springframework.data.util.Lazy.get(Lazy.java:114) ~[spring-data-commons-2.4.9.jar:2.4.9]
  85. at org.springframework.data.repository.core.support.RepositoryfactorybeanSupport.afterPropertiesSet(RepositoryfactorybeanSupport.java:329) ~[spring-data-commons-2.4.9.jar:2.4.9]
  86. at org.springframework.data.jpa.repository.support.JpaRepositoryfactorybean.afterPropertiesSet(JpaRepositoryfactorybean.java:144) ~[spring-data-jpa-2.4.9.jar:2.4.9]
  87. at org.springframework.beans.factory.support.AbstractAutowireCapablebeanfactory.invokeInitMethods(AbstractAutowireCapablebeanfactory.java:1845) ~[spring-beans-5.3.7.jar:5.3.7]
  88. at org.springframework.beans.factory.support.AbstractAutowireCapablebeanfactory.initializeBean(AbstractAutowireCapablebeanfactory.java:1782) ~[spring-beans-5.3.7.jar:5.3.7]
  89. ... 50 common frames omitted
  90. Caused by: org.springframework.data.mapping.PropertyReferenceException: No property addMovie found for type Movie!
  91. at org.springframework.data.mapping.PropertyPath.<init>(PropertyPath.java:90) ~[spring-data-commons-2.4.9.jar:2.4.9]
  92. at org.springframework.data.mapping.PropertyPath.create(PropertyPath.java:437) ~[spring-data-commons-2.4.9.jar:2.4.9]
  93. at org.springframework.data.mapping.PropertyPath.create(PropertyPath.java:413) ~[spring-data-commons-2.4.9.jar:2.4.9]
  94. at org.springframework.data.mapping.PropertyPath.lambda$from$0(PropertyPath.java:366) ~[spring-data-commons-2.4.9.jar:2.4.9]
  95. at java.base/java.util.concurrent.ConcurrentMap.computeIfAbsent(ConcurrentMap.java:330) ~[na:na]
  96. at org.springframework.data.mapping.PropertyPath.from(PropertyPath.java:348) ~[spring-data-commons-2.4.9.jar:2.4.9]
  97. at org.springframework.data.mapping.PropertyPath.from(PropertyPath.java:331) ~[spring-data-commons-2.4.9.jar:2.4.9]
  98. at org.springframework.data.repository.query.parser.Part.<init>(Part.java:81) ~[spring-data-commons-2.4.9.jar:2.4.9]
  99. at org.springframework.data.repository.query.parser.PartTree$OrPart.lambda$new$0(PartTree.java:249) ~[spring-data-commons-2.4.9.jar:2.4.9]
  100. at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:195) ~[na:na]
  101. at java.base/java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:177) ~[na:na]
  102. at java.base/java.util.Spliterators$ArraySpliterator.forEachRemaining(Spliterators.java:948) ~[na:na]
  103. at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:484) ~[na:na]
  104. at java.base/java.util.stream.AbstractPipeline.wrapAndcopyInto(AbstractPipeline.java:474) ~[na:na]
  105. at java.base/java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:913) ~[na:na]
  106. at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234) ~[na:na]
  107. at java.base/java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:578) ~[na:na]
  108. at org.springframework.data.repository.query.parser.PartTree$OrPart.<init>(PartTree.java:250) ~[spring-data-commons-2.4.9.jar:2.4.9]
  109. at org.springframework.data.repository.query.parser.PartTree$Predicate.lambda$new$0(PartTree.java:383) ~[spring-data-commons-2.4.9.jar:2.4.9]
  110. at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:195) ~[na:na]
  111. at java.base/java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:177) ~[na:na]
  112. at java.base/java.util.Spliterators$ArraySpliterator.forEachRemaining(Spliterators.java:948) ~[na:na]
  113. at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:484) ~[na:na]
  114. at java.base/java.util.stream.AbstractPipeline.wrapAndcopyInto(AbstractPipeline.java:474) ~[na:na]
  115. at java.base/java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:913) ~[na:na]
  116. at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234) ~[na:na]
  117. at java.base/java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:578) ~[na:na]
  118. at org.springframework.data.repository.query.parser.PartTree$Predicate.<init>(PartTree.java:384) ~[spring-data-commons-2.4.9.jar:2.4.9]
  119. at org.springframework.data.repository.query.parser.PartTree.<init>(PartTree.java:92) ~[spring-data-commons-2.4.9.jar:2.4.9]
  120. at org.springframework.data.jpa.repository.query.PartTreeJpaQuery.<init>(PartTreeJpaQuery.java:89) ~[spring-data-jpa-2.4.9.jar:2.4.9]
  121. ... 76 common frames omitted

解决方法

在存储库界面中删除以下方法。 JPA 只有 find…By、read…By、get…By、query…By、search…By、stream…By…等等。

  1. public Movie addMovie(String movieName,Integer rating,String Genre);

有一个默认方法repository.save() 用于将对象插入到数据库中。

在https://docs.spring.io/spring-data/jpa/docs/current/reference/html/#repository-query-keywords查看更多

git clone 时出现异常:fatal: unable to access 'https://github.com/spring-projects/spring-framework.gi

git clone 时出现异常:fatal: unable to access 'https://github.com/spring-projects/spring-framework.gi

git在 clone 代码的时候出现:fatal: unable to access ''https://github.com/spring-projects/spring-framework.git/'': OpenSSL SSL_read: Connection was reset, errno 10054

解决方法:

只需要执行以下两行命令:

  git config --global --unset http.proxy

  git config --global --unset https.proxy

IntelliJ IDEA 2017 版 spring-boot2.0.2 搭建 JPA springboot DataSource JPA 环境搭建,JPA 注解 @ManyToOne 使用详情;JPA...

IntelliJ IDEA 2017 版 spring-boot2.0.2 搭建 JPA springboot DataSource JPA 环境搭建,JPA 注解 @ManyToOne 使用详情;JPA...

一、数据库原型

       

数据库模型如图所示,而现在需要根据数据库模型,建立对应的实体类,这在项目重构老数据库,采用新的框架重构上应该是比较常见的。

数据库脚本如下:

 1 CREATE TABLE `bomsub` (
 2   `subId` varchar(40) NOT NULL COMMENT ''子类型ID'',
 3   `mainId` varchar(40) NOT NULL COMMENT ''主类型ID'',
 4   `subName` varchar(40) NOT NULL COMMENT ''子类型名称'',
 5   `engName` varchar(255) NOT NULL,
 6   `deleted` int(1) NOT NULL DEFAULT ''1'' COMMENT ''当前是否删除'',
 7   PRIMARY KEY (`subId`),
 8   KEY `FK_Reference_47` (`mainId`),
 9   CONSTRAINT `FK_Reference_47` FOREIGN KEY (`mainId`) REFERENCES `bommain` (`mainId`)
10 ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT=''Bom表的小类'';
View Code

实体类构成:

 1 @Entity
 2 @Table(name = "bomsub")
 3 public class BomSub extends SuperEntity {
 4 
 5 
 6     /**
 7      * 子类型ID
 8      */
 9     @Id
10     @GenericGenerator(strategy = "uuid", name = "subId")
11     @GeneratedValue(generator = "subId")
12     @Column(length = 40)
13     public String subId;
14 
15     /**
16      * 主类型ID
17      */
18     @ManyToOne(cascade = {CascadeType.ALL})
19     @JoinColumn(name = "mainId", foreignKey = @ForeignKey(name = "FK_Reference_47"), columnDefinition = "varchar(40) NOT NULL COMMENT ''主类型ID''")
20     public BomMain bomMain;
21 
22     /**
23      * 子类型名称
24      */
25     @Column(nullable = false, length = 40)
26     public String subName;
27 
28     /**
29      * 英文名称
30      */
31     @Column(nullable = false)
32     public String engName;
33 
34     /**
35      * 所有字段的是否存在
36      */
37     @Column(nullable = false, columnDefinition = "int(1) default 1 COMMENT ''当前是否删除''")
38     public Integer deleted;
39 
40 
41 }
View Code

主要部分:

/**
* 主类型ID
*/
@ManyToOne(cascade = {CascadeType.ALL})
@JoinColumn(name = "mainId", foreignKey = @ForeignKey(name = "FK_Reference_47"), columnDefinition = "varchar(40) NOT NULL COMMENT ''主类型ID''")
public BomMain bomMain;

@ManyToOne 表明表的关系是多对一,就是子表 bomsub 的 mainId,是一个,但是对应着多个 bomMain 的 Id

@JoinColumn 表明两个表是如何关联的,关联需要的条件

       内部属性  name : 关联两个表外键的名称

                     foreignKey :外键的设置,这里对其名称进行设置,就会将索引的名称设置为这里名字的设置                 

             columnDefinition :DDL 拼接,这里指的是这个属性的 SQL 语句的设置

当这个表生成的时候就会把剩下的部分在 JPA 模式下自动生成设置的 SQL 语句。

JPA CrudRepository 关于删除 DataIntegrityViolationException 错误消息

JPA CrudRepository 关于删除 DataIntegrityViolationException 错误消息

如何解决JPA CrudRepository 关于删除 DataIntegrityViolationException 错误消息

我有一个 Spring Boot 应用程序,它在 h2 数据库中有 2 个表:计算机 和一个 处理器

计算机和处理器之间存在单向、多对一关系,因此许多计算机可以有一个处理器。在架构中,关系上存在外键约束,因此您不能删除某些计算机正在使用的处理器。

我希望能够向用户显示有用的错误消息,例如:“无法删除处理器‘M1’,因为它被计算机‘MacBook、MacBook Pro’使用。 ” 我能够成功捕获 DataIntegrityViolationException 但是这个错误没有包含足够的信息让我生成所需的错误消息。它只提到存在违反foreignKeyConstraint 定义。

因此,作为一种解决方法,当抛出 DataIntegrityViolationException 时,我会捕获它并查询特定实例的数据库,为什么无法删除处理器并以这种方式生成错误消息。我可以很容易地不在架构中添加 FK 约束,只需检查服务中的数据库以确保要删除的处理器未在数据库中的任何计算机中使用,并生成适当的错误。然而,以编程方式检查 FK 约束感觉就像代码味道一样。

有没有办法在数据库级别使用 FK 约束并使用 DataIntegrityViolationException 生成有用的错误消息?

  1. // ENTITIES
  2. @Entity
  3. @Table(name = "Computer",schema = "CS")
  4. public class Computer extends BaseEntity {
  5. @Id
  6. @GeneratedValue(strategy = GenerationType.IDENTITY)
  7. @Column(name = "computer_id")
  8. @Getter
  9. @Setter
  10. private long id;
  11. ...
  12. @ManyToOne(fetch = FetchType.EAGER)
  13. @JoinColumn(name = "processor_id")
  14. @OnDelete(action= OnDeleteAction.NO_ACTION)
  15. @Getter
  16. @Setter
  17. private Processor processor;
  18. ...
  19. }
  20. @Entity
  21. @Table(name = "Processor",schema = "CS")
  22. public class Processor extends BaseEntity {
  23. @Id
  24. @GeneratedValue(strategy = GenerationType.IDENTITY)
  25. @Column(name = "processor_id")
  26. @Getter@Setter
  27. private long id;
  28. ...
  29. }
  30. // PROCESSOR_CONTROLLER
  31. public ResponseEntity<Void> deleteByName(@PathVariable("name")) String name) {
  32. try {
  33. processorService.deleteByName(name);
  34. } catch (DataIntegrityViolationException e) {
  35. List<String> computerList = new ArrayList<>();
  36. computerService.findAllByHoldName(name).forEach(computer -> computerList.add(computer.getProcessor()));
  37. String computeRSString = computersList.stream().reduce("",(res,next) -> res += next + ",");
  38. throw new DataIntegrityViolationException (String.format("Processor ''%s'' is used by Computer(s) ''%s''. It cannot be deleted.",name,computeRSString));
  39. }
  40. return ResponseEntity.noContent().build();
  41. }
  42. // PROCESSOR_SERVICE
  43. @Transactional
  44. public void deleteByName(String name) {
  45. Processor existingProcessor = processorRepository.findByName(name);
  46. processorRepository.delete(existingProcessor);
  47. }

预先感谢您的帮助!!

restapi(2)- generic restful CRUD:通用的restful风格数据库表维护工具

restapi(2)- generic restful CRUD:通用的restful风格数据库表维护工具

   研究关于restapi的初衷是想搞一套通用的平台数据表维护http工具。前面谈过身份验证和使用权限、文件的上传下载,这次来到具体的数据库表维护。我们在这篇示范里设计一套通用的对平台每一个数据表的标准维护方式。http服务端数据表维护CRUD有几个标准的部分组成:Model,Repository,Route。我们先看看这几个类型的基类:

trait ModelBase[M,E] {
  def to: M => E
  def from: E => M
}


trait RepoBase[M] {
  def getById(id: Long) : Future[Option[M]]
  def getAll : Future[Seq[M]]
  def filter(expr: M => Boolean): Future[Seq[M]]
  def save(row: M) : Future[AnyRef]
  def deleteById(id: Long) : Future[Int]
  def updateById(id: Long, row: M) : Future[Int]
}


abstract class RouteBase[M](val pathName: String, repository: RepoBase[M])(
  implicit m: Manifest[M]) extends Directives with JsonConverter {

  val route = path(pathName) {
    get {
      complete(futureToJson(repository.getAll))
    } ~ post {
      entity(as[String]) { json =>
        val extractedEntity = fromJson[M](json)
        complete(futureToJson(repository.save(extractedEntity)))
      }
    }
  } ~ path(pathName / LongNumber) { id =>
    get {
      complete(futureToJson(repository.getById(id)))
    } ~ put {
      entity(as[String]) { json =>
        val extractedEntity = fromJson[M](json)
        complete(futureToJsonAny(repository.updateById(id, extractedEntity)))
      }
    } ~ delete {
      complete(futureToJsonAny(repository.deleteById(id)))
    }
  }
}

很明显,Model是数据库表行类型的表达方式、Repository是数据库表操作方法、Route是操作方法的调用。下面是这几个类型的实例示范:

object MockModels {
  case class DataRow (
                     name: String,
                     age: Int
                     )
  case class Person(name: String, age: Int)
       extends ModelBase[Person,DataRow] {
    def to: Person => DataRow = p => DataRow (
      name = p.name,
      age = p.age
    )
    def from: DataRow => Person = m => Person(
      name = m.name,
      age = m.age
    )
  }
}


package com.datatech.restapi
import MockModels._

import scala.concurrent.Future
object MockRepo {
   class PersonRepo extends RepoBase[Person] {
    override def getById(id: Long): Future[Option[Person]] = Future.successful(Some(Person("johnny lee",23)))

    override def getAll: Future[Seq[Person]] = Future.successful(
      Seq(Person("jonny lee",23),Person("candy wang",45),Person("jimmy kowk",34))
    )

    override def filter(expr: Person => Boolean): Future[Seq[Person]] = Future.successful(
      Seq(Person("jonny lee",23),Person("candy wang",45),Person("jimmy kowk",34))
    )

    override def save(row: Person): Future[Person] = Future.successful(row)

    override def deleteById(id: Long): Future[Int] = Future.successful(1)

    override def updateById(id: Long, row: Person): Future[Int] = Future.successful(1)
  }

}


object PersonRoute {

  class PersonRoute(pathName: String, repo: RepoBase[Person])
     extends RouteBase[Person](pathName,repo)

  val route = new PersonRoute("person",new PersonRepo).route
}

Model代表数据表结构以及某种数据库的表行与Model之间的转换。而repository则代表某种数据库对库表具体操作的实现。我们把焦点拉回到RouteBase上来,这里包含了rest标准的get,post,put,delete http操作。实际上就是request/response处理机制。因为数据需要在线上on-the-wire来回移动,所以需要进行数据转换。通用的数据传输模式是:类->json->类,即序列化/反序列化。akka-http提供了丰富的Marshaller来实现自动的数据转换,但在编译时要提供Marshaller的隐式实例implicit instance,所以用类参数是无法通过编译的。只能手工进行类和json之间的转换。json转换是通过json4s实现的:

import java.text.SimpleDateFormat
import akka.http.scaladsl.model._
import org.json4s.JsonAST.{JNull, JString}
import org.json4s.{CustomSerializer, DefaultFormats, Formats}
import org.json4s.jackson.Serialization

import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.Future

trait DateSerializer {
  case object SqlDateSerializer extends CustomSerializer[java.sql.Date](format => ( {
    case JString(date) => {
      val utilDate = new SimpleDateFormat("yyyy-MM-dd").parse(date);
      new java.sql.Date(utilDate.getTime)
    }
    case JNull         => null
  }, {
    case date: java.sql.Date => JString(date.toString)
  }))

}

trait JsonConverter extends DateSerializer {
  implicit val formats: Formats = new DefaultFormats {
    override def dateFormatter = new SimpleDateFormat("yyyy-MM-dd")
  } ++ List(SqlDateSerializer)

  def toJson(obj: AnyRef): String = {
    Serialization.write(obj)
  }

  def futureToJson(obj: Future[AnyRef]): Future[HttpResponse] = {
    obj.map { x =>
      HttpResponse(status = StatusCodes.OK, entity = HttpEntity(MediaTypes.`application/json`, Serialization.write(x)))
    }.recover {
      case ex => ex.printStackTrace(); HttpResponse(status = StatusCodes.InternalServerError)
    }

  }

  def futureToJsonAny(obj: Future[Any]): Future[HttpResponse] = {
    obj.map { x =>
      HttpResponse(status = StatusCodes.OK, entity = HttpEntity(MediaTypes.`application/json`, s"""{status : ${x}"""))
    }.recover {
      case ex => HttpResponse(status = StatusCodes.InternalServerError)
    }

  }

  def fromJson[E](json: String)(implicit m: Manifest[E]): E = {
    Serialization.read[E](json)
  }
}

当然对于一些特别的数据库表,我们还是希望使用akka-http强大的功能,如streaming。这时对于每一个这样的表单就需要要定制Route了。下面是一个定制Route的例子:

object MockModel {
  case class AddressRow (
                       province: String,
                       city: String,
                       street: String,
                       zip: String
                     )
  case class Address(
                      province: String,
                      city: String,
                      street: String,
                      zip: String
                    )
    extends ModelBase[Address,AddressRow] {
    def to: Address => AddressRow = addr => AddressRow (
      province = addr.province,
      city = addr.city,
      street = addr.street,
      zip = addr.zip
    )
    def from: AddressRow => Address = row => Address(
      province = row.province,
      city = row.city,
      street = row.street,
      zip = row.zip
    )
  }
}

  object AddressRepo {
     def getById(id: Long): Future[Option[Address]] = ???

     def getAll: Source[Address,_] = ???

     def filter(expr: Address => Boolean): Future[Seq[Address]] = ???

     def saveAll(rows: Source[Address,_]): Future[Int] = ???
     def saveAll(rows: Future[Seq[Address]]): Future[Int] = ???

     def deleteById(id: Long): Future[Address] = ???

     def updateById(id: Long, row: Address): Future[Address] = ???
  }


package com.datatech.restapi
import akka.actor._
import akka.stream._
import akka.http.scaladsl.common._
import spray.json.DefaultJsonProtocol
import akka.http.scaladsl.marshallers.sprayjson.SprayJsonSupport
import akka.http.scaladsl.server._
import MockModels.Address
import MockRepo._


trait FormatConverter extends SprayJsonSupport with DefaultJsonProtocol{
  implicit val addrFormat = jsonFormat4(Address.apply)
}

case class AddressRoute(val pathName: String)(implicit akkaSys: ActorSystem) extends Directives with FormatConverter{
  implicit val mat = ActorMaterializer()
  implicit val jsonStreamingSupport = EntityStreamingSupport.json()
    .withParallelMarshalling(parallelism = 2, unordered = false)

  val route = path(pathName) {
    get {
      complete(AddressRepo.getAll)
    } ~ post {
      withoutSizeLimit {
          entity(asSourceOf[Address]) { source =>
 /*           val futSavedRows: Future[Seq[Address]] =
              source.runFold(Seq[Address]())((acc, addr) => acc :+ addr)
            onComplete(futSavedRows) { rows =>  */
            onComplete(AddressRepo.saveAll(source)) {rows =>
            complete { s"$rows address saved."}
          }
        }
      }

  } ~ path(pathName / LongNumber) { id =>
    get {
      complete(AddressRepo.getById(id)))
    } ~ put {
      entity(as[Address]) { addr =>
        onComplete(AddressRepo.updateById(id,addr)) { addr =>
        complete(s"address updated to: $addr")
      }
    } ~ delete {
        onComplete(AddressRepo.deleteById(id)) { addr =>
          complete(s"address deleted: $addr")
    }
  }
}

这样做可以灵活的使用akka-stream提供的功能。

上面的例子Mock PersonRoute.route可以直接贴在主route后面:

  val route =
     path("auth") {
        authenticateBasic(realm = "auth", authenticator.getUserInfo) { userinfo =>
          post { complete(authenticator.issueJwt(userinfo))}
        }
     } ~
       pathPrefix("openspace") {
         (path("hello") & get) {
           complete(s"Hello, you are in open space.")
         }
       } ~
       pathPrefix("api") {
          authenticateOAuth2(realm = "api", authenticator.authenticateToken) { validToken =>
            (path("hello") & get) {
              complete(s"Hello! userinfo = ${authenticator.getUserInfo(validToken)}")
            } ~
            (path("how are you") & get) {
              complete(s"Hello! userinfo = ${authenticator.getUserInfo(validToken)}")
            } ~
            PersonRoute.route
            // ~ ...
          }
     }

和前面的示范一样,我们还是写一个客户端来测试:

import akka.actor._
import akka.http.scaladsl.model.headers._
import scala.concurrent._
import scala.concurrent.duration._
import akka.http.scaladsl.Http
import spray.json.DefaultJsonProtocol
import akka.http.scaladsl.marshallers.sprayjson.SprayJsonSupport
import akka.http.scaladsl.marshalling._
import akka.http.scaladsl.model._
import akka.stream.ActorMaterializer

trait JsonFormats extends SprayJsonSupport with DefaultJsonProtocol
object JsonConverters extends JsonFormats {
  case class Person(name: String,age: Int)
  implicit val fmtPerson = jsonFormat2(Person)
}

object TestCrudClient  {
  type UserInfo = Map[String,Any]
  def main(args: Array[String]): Unit = {
    implicit val system = ActorSystem()
    implicit val materializer = ActorMaterializer()
    // needed for the future flatMap/onComplete in the end
    implicit val executionContext = system.dispatcher

    val helloRequest = HttpRequest(uri = "http://192.168.11.189:50081/")

    val authorization = headers.Authorization(BasicHttpCredentials("johnny", "p4ssw0rd"))
    val authRequest = HttpRequest(
      HttpMethods.POST,
      uri = "http://192.168.11.189:50081/auth",
      headers = List(authorization)
    )


    val futToken: Future[HttpResponse] = Http().singleRequest(authRequest)

    val respToken = for {
      resp <- futToken
      jstr <- resp.entity.dataBytes.runFold("") {(s,b) => s + b.utf8String}
    } yield jstr

    val jstr =  Await.result[String](respToken,2 seconds)
    println(jstr)

    scala.io.StdIn.readLine()

    val authentication = headers.Authorization(OAuth2BearerToken(jstr))

    val getAllRequest = HttpRequest(
      HttpMethods.GET,
      uri = "http://192.168.11.189:50081/api/crud/person",
    ).addHeader(authentication)
    val futGet: Future[HttpResponse] = Http().singleRequest(getAllRequest)
    println(Await.result(futGet,2 seconds))
    scala.io.StdIn.readLine()

    import JsonConverters._

    val saveRequest = HttpRequest(
      HttpMethods.POST,
      uri = "http://192.168.11.189:50081/api/crud/person"
    ).addHeader(authentication)
    val futPost: Future[HttpResponse] =
      for {
        reqEntity <- Marshal(Person("tiger chan",18)).to[RequestEntity]
        response <- Http().singleRequest(saveRequest.copy(entity=reqEntity))
      } yield response

    println(Await.result(futPost,2 seconds))
    scala.io.StdIn.readLine()
    system.terminate()
  }

}

下面是restapi发展到现在状态的源代码:

build.sbt

 

name := "restapi"

version := "0.3"

scalaVersion := "2.12.8"

libraryDependencies ++= Seq(
  "com.typesafe.akka" %% "akka-http"   % "10.1.8",
  "com.typesafe.akka" %% "akka-stream" % "2.5.23",
  "com.pauldijou" %% "jwt-core" % "3.0.1",
  "de.heikoseeberger" %% "akka-http-json4s" % "1.22.0",
  "org.json4s" %% "json4s-native" % "3.6.1",
  "com.typesafe.akka" %% "akka-http-spray-json" % "10.1.8",
  "com.typesafe.scala-logging" %% "scala-logging" % "3.9.0",
  "org.slf4j" % "slf4j-simple" % "1.7.25",
  "org.json4s" %% "json4s-jackson" % "3.6.7",
  "org.json4s" %% "json4s-ext" % "3.6.7"
)

RestApiServer.scala

package com.datatech.restapi

import akka.actor._
import akka.stream._
import akka.http.scaladsl.Http
import akka.http.scaladsl.server.Directives._
import pdi.jwt._
import AuthBase._
import MockUserAuthService._

object RestApiServer extends App {

  implicit val httpSys = ActorSystem("httpSystem")
  implicit val httpMat = ActorMaterializer()
  implicit val httpEC = httpSys.dispatcher



  implicit val authenticator = new AuthBase()
    .withAlgorithm(JwtAlgorithm.HS256)
    .withSecretKey("OpenSesame")
    .withUserFunc(getValidUser)

  val route =
    path("auth") {
      authenticateBasic(realm = "auth", authenticator.getUserInfo) { userinfo =>
        post { complete(authenticator.issueJwt(userinfo))}
      }
    } ~
      pathPrefix("api") {
        authenticateOAuth2(realm = "api", authenticator.authenticateToken) { validToken =>
            FileRoute(validToken)
              .route ~
            (pathPrefix("crud")) {
              PersonRoute.route
            }
          // ~ ...
        } ~
          (pathPrefix("crud")) {
            PersonRoute.route
            // ~ ...
          }
      }

  val (port, host) = (50081,"192.168.11.189")

  val bindingFuture = Http().bindAndHandle(route,host,port)

  println(s"Server running at $host $port. Press any key to exit ...")

  scala.io.StdIn.readLine()


  bindingFuture.flatMap(_.unbind())
    .onComplete(_ => httpSys.terminate())


}

 

原文出处:https://www.cnblogs.com/tiger-xc/p/11229767.html

今天关于使用 Spring Boot + RestAPI + JPA + CrudRepository +MySQL 创建 CRUD 时出现异常的介绍到此结束,谢谢您的阅读,有关git clone 时出现异常:fatal: unable to access 'https://github.com/spring-projects/spring-framework.gi、IntelliJ IDEA 2017 版 spring-boot2.0.2 搭建 JPA springboot DataSource JPA 环境搭建,JPA 注解 @ManyToOne 使用详情;JPA...、JPA CrudRepository 关于删除 DataIntegrityViolationException 错误消息、restapi(2)- generic restful CRUD:通用的restful风格数据库表维护工具等更多相关知识的信息可以在本站进行查询。

本文标签: