【发布时间】:2017-03-20 17:46:35
【问题描述】:
我在使用 Angular 2 应用程序将新行插入数据库时遇到问题。
当我尝试在数据库中插入一个具有指向数据库中另一个表的外键的新条目时,就会出现问题。我在 Spring 中定义的两个模型是:
@Entity
public class A{
@Id
@NotNull
@GeneratedValue(strategy = GenerationType.AUTO)
private int id;
@OneToMany(mappedBy = "A")
private List<B> b = new ArrayList<B>();
...
}
@Entity
public class B{
@Id
@NotNull
@GeneratedValue(strategy = GenerationType.AUTO)
private long id;
@NotNull
@ManyToOne
@JoinColumn(name="aId")
private A a;
...
}
后端的这两个模型在前端有对应的模型。我添加了 _links 部分,因为 Spring Rest api 提供链接而不是外键:
export class A{
id: number;
b: B[];
_links:{...}
...
}
export class B{
id: number;
a: A;
_links:{...}
...
}
我根据从 api 获得的信息创建了这些模型。例如,在 localhost:8080/api/b/1 上的 get 请求给出:
{
"id" : 1,
"_links" : {
"self" : {
"href" : "http://localhost:4200/api/b/1"
},
"b" : {
"href" : "http://localhost:4200/api/b/1"
},
"a" : {
"href" : "http://localhost:4200/api/b/1/a"
}
}
}
我可以使用下面显示的 Angular 2 服务方法轻松地将新行插入表 A(因为它不包含外键):
createA(a: A): Observable<A[]>{
return this.http.post(this.AUrl, a)
.map((res:Response) => res.json())
.catch((error:any) => Observable.throw(error.json().error || 'Server Error'));
}
同样,创建新模型 B 的服务方法如下:
createB(b: B): Observable<B[]>{
return this.http.post(this.BUrl, b)
.map((res:Response) => res.json())
.catch((error:any) => Observable.throw(error.json().error || 'Server Error'));
}
我在 Spring 中的存储库定义为:
@RepositoryRestResource(collectionResourceRel="a", path="a", itemResourceRel="a")
public interface ARepository extends JpaRepository<A, Integer>{
}
@RepositoryRestResource(collectionResourceRel="b", path="b", itemResourceRel="b"))
public interface BRepository extends JpaRepository<B, Long>{
}
我在 Spring 中的存储库配置是:
@Configuration
public class MyRestConfiguration extends RepositoryRestMvcConfiguration{
@Override
protected void configureRepositoryRestConfiguration(RepositoryRestConfiguration config){
config.setBasePath("/api");
config.exposeIdsFor(A.class);
config.exposeIdsFor(B.class);
}
}
当我尝试在表 B 中插入新行时,我在春季收到以下错误:
javax.validation.ConstraintViolationException: Validation failed for classes [......model.B] during update time for groups [javax.validation.groups.Default, ]
List of constraint violations:[
ConstraintViolationImpl{interpolatedMessage='may not be null', propertyPath=a, rootBeanClass=class ........model.B, messageTemplate='{javax.validation.constraints.NotNull.message}'}
]
我想知道 http post 请求的请求负载到底应该是什么样子,以便应用程序将 B 的新行插入数据库。非常感谢任何帮助。
编辑:
我用这个映射制作了一个弹簧休息控制器:
@PostMapping("/api/b")
@ResponseBody
public String createServis(@RequestBody B b){
}
如果我使用此有效负载发出 http 发布请求(使用 curl 或其他方式,但这不是重点):
{
id:1,
aId:1
}
或者这个:
{
id:1,
a:{id:1}
}
甚至这个:
{
id:1,
aId:1,
a:{id:1}
}
对象 b 的属性 a 保持为空 / 未正确初始化。
【问题讨论】:
-
我对“AId”部分有点困惑。这反映在您的角度实现中吗?另外,请您添加其余的堆栈跟踪吗?可以加B类的完整模型吗?
-
实际上是'aId'。它基本上告诉连接应该发生在表 a 的列 id 上。在数据库表 B 中会有一个名为 a_id 的新列,它会将外键放入其中。至于堆栈跟踪的其余部分,我将其粘贴在这里:pastebin.com/raw/6KyM63Ux
-
我知道这一点。但在我看来,这种确切的行为似乎没有反映在您的角度实现中,因此 B 对象的 aId 属性为空。你能显示代码,你的 a 在客户端连接到 b 吗?
-
除了有属性b: B[];在模型 A 和属性 a 中:A;在客户端的模型 B 中没有其他连接。在调用服务的 createB 方法之前,我确保参数 b 的属性 a 设置为 A 的实例。我从 http.get() 获取该实例
-
我编辑了我的帖子,以阐明为什么我像这样在 Angular 2 中创建模型。我应该以不同的方式创建它们吗?
标签: spring spring-mvc post angular2-services spring-hateoas