外键为空:Hibernate Spring

huangapple go评论70阅读模式
英文:

Foreign key is null : Hibernate Spring

问题

我试图将 Run 对象保存到数据库中。我在 Run 和 City 之间定义了关联关系。一个城市可以有多个跑步记录。我遇到了关于 city_id 的问题,它是空的。

City 实体和控制器:

City

@Entity
@Getter
@Setter
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Table(name = "cities")
public class City {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "city_id")
    private long id;
    @OneToMany(mappedBy = "city", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
    private List<Run> runs = new ArrayList<>();
    private String name;
}

Run

@Entity
@Builder
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@Table(name = "runs")
public class Run {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private long id;
    @Column(name = "name_run")
    private String nameRun;
    @Column(name = "distance")
    private double distance;
    @Column(name = "date")
    private Date date;
    @Column(name = "my_time")
    private String myTime;
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "city_id", nullable = false)
    @OnDelete(action = OnDeleteAction.CASCADE)
    @JsonIgnore
    private City city;
}

Controller

@CrossOrigin
@RestController
@RequestMapping("/api/")
public class RunController {

    private RunRepository runRepository;
    private RunService runService;

    public RunController(RunRepository runRepository, RunService runService) {
        this.runRepository = runRepository;
        this.runService = runService;
    }

    @GetMapping("runs")
    public ResponseEntity<List<Run>> getRuns() {
        return runService.getRuns();
    }

    @PostMapping("runs")
    public ResponseEntity addRun(@RequestBody Run run) {
        return new ResponseEntity<>(runRepository.save(run), HttpStatus.OK);
    }
}

我想将运动记录保存到数据库中。我的测试请求如下:

{
    "nameRun": "test",
    "distance": "5.0",
    "date": "2020-12-12",
    "myTime": "50:40",
    "city": "test1"
}

从 Intelijj 中评估表达式的结果如下:

外键为空:Hibernate Spring

为什么 City 为 null?在映射中是否存在错误?

英文:

I try to save object Run to database. I defined relation between Run and City. One city could have many runs. I got problem with city_id. Is null.

Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.springframework.dao.DataIntegrityViolationException: could not execute statement; SQL [n/a]; constraint [null]; nested exception is org.hibernate.exception.ConstraintViolationException: could not execute statement] with root cause
java.sql.SQLIntegrityConstraintViolationException: Column &#39;city_id&#39; cannot be null

My entieties and controller:
City

@Entity
@Getter
@Setter
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Table(name = &quot;cities&quot;)
public class City {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = &quot;city_id&quot;)
    private long id;
    @OneToMany(mappedBy = &quot;city&quot;, cascade = CascadeType.ALL, fetch = FetchType.LAZY)
    private List&lt;Run&gt; runs = new ArrayList&lt;&gt;();
    private String name;
}

Run

@Entity
@Builder
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@Table(name = &quot;runs&quot;)
public class Run {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private long id;
    @Column(name = &quot;name_run&quot;)
    private String nameRun;
    @Column(name = &quot;distance&quot;)
    private double distance;
    @Column(name = &quot;date&quot;)
    private Date date;
    @Column(name = &quot;my_time&quot;)
    private String myTime;
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = &quot;city_id&quot;, nullable = false)
    @OnDelete(action = OnDeleteAction.CASCADE)
    @JsonIgnore
    private City city;
}

Controller


@CrossOrigin
@RestController
@RequestMapping(&quot;/api/&quot;)
public class RunController {

    private RunRepository runRepository;
    private RunService runService;

    public RunController(RunRepository runRepository, RunService runService) {
        this.runRepository = runRepository;
        this.runService = runService;
    }

    @GetMapping(&quot;runs&quot;)
    public ResponseEntity&lt;List&lt;Run&gt;&gt; getRuns() {
        return runService.getRuns();
    }

    @PostMapping(&quot;runs&quot;)
    public ResponseEntity addRun(@RequestBody Run run) {

        return new ResponseEntity&lt;&gt;(runRepository.save(run), HttpStatus.OK);
    }
}

I would like to save the run in DB.
My test request looks like :

{
"nameRun": "test",
"distance":"5.0",
"date":"2020-12-12",
"myTime":"50:40",
"city":"test1"
}

Result from evaluate expresion in Intelijj:

外键为空:Hibernate Spring

Why the City = null? Is here error in mapping?

答案1

得分: 1

这是你要的翻译内容:

你能尝试一下这个 JSON,但你需要在 JSON 中传递城市 ID。

{
	"nameRun": "test",
	"distance": "5.0",
	"date": "2020-12-12",
	"myTime": "50:40",
	"city": {
		"id": 1,
		"name": "test1"
	}
}
  
谢谢
英文:

Can you try with this json but you need to pass city id in json.

{
	&quot;nameRun&quot;: &quot;test&quot;,
	&quot;distance&quot;: &quot;5.0&quot;,
	&quot;date&quot;: &quot;2020-12-12&quot;,
	&quot;myTime&quot;: &quot;50:40&quot;,
	&quot;city&quot;: {
		&quot;id&quot;: 1,
		&quot;name&quot;: &quot;test1&quot;
	}
}

Thanks

答案2

得分: 0

首先,请使用 Long 类型来表示 id。最好还要添加 @Entity 注解。

@Entity
public class City {

    @Id
    @GeneratedValue
    private Long id;

    @OneToMany(mappedBy = "city", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
    private List<Run> runs = new ArrayList<>();

}
@Entity
public class Run {

    @Id
    @GeneratedValue
    private Long id;

    @ManyToOne(fetch = FetchType.LAZY)
    private City city;

}

当保存 Run 时,需要设置 city_id

最简单的方法是创建一个临时的虚拟 City 对象,并将 id 设置给它。

City city = new City();
city.setId(1L);

Run run = new Run();
run.setCity(city);

repository.save(run);

显然,你的数据库中应该有一个 id 为 1L 的城市记录。

其他选项包括:

  1. 使用类似于 Hibernate 中的 session.load() 方法,结合 Spring repository,可以创建一个不需要从数据库加载的 City 对象。
  2. 根据 id 完全加载 City 实体。
英文:

First of all, use Long for id please. It is better to add @Entity annotation too.

@Entity
public class City {

    @Id
    @GeneratedValue
    private Long id;

    @OneToMany(mappedBy = &quot;city&quot;, cascade = CascadeType.ALL, fetch = FetchType.LAZY)
    private List&lt;Run&gt; runs = new ArrayList&lt;&gt;();

}

@Entity
public class Run {

    @Id
    @GeneratedValue
    private Long id;

    @ManyToOne(fetch = FetchType.LAZY)
    private City city;

}

You need to set city_id when you save Run.

The simplest way to do that is just create a fake transient City and set id to it.

City city = new City();
city.setId(1L);

Run run = new Run();
run.setCity(city);

repository.save(run);

Obviously you should have a city with id 1L in the database.

Other options are

  1. Use something like session.load() Hibernate analogue with Spring repository to create City without loading it from datatbase.
  2. Load City entity entirely by id.

答案3

得分: 0

if you wanna save any run class, 

    Run run = new Run();
    City city = new City();
    city.getRuns().add(run);
    runRepository.save(run);

if you wanna save any run class, first you need to insert to (Arraylist) runs variable of city class like **city.getRuns().add(run)** after filling run then you can runRepository.save(run).

Also my samples are here. You can look at myclasses.

First class is called **Patient** .

    @Data
    @AllArgsConstructor
    @NoArgsConstructor
    @Entity
    @ToString
    @Table(name = "aapatient")
    public class Patient {
    
    	@Id
    	@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "AA_PATIENT_SEQ")
    	@SequenceGenerator(sequenceName = "AA_PATIENT_SEQ", allocationSize = 1, name = "AA_PATIENT_SEQ")
    	@Column(name = "patientid")
    	private Long patientid;
    	private String name;
    	private String lastname;  
    
    	@OneToMany(mappedBy = "patient", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
    	private List<Problem> problems; 
    }

Second Class called **Problem** is this one.


    @Data
    @AllArgsConstructor
    @NoArgsConstructor
    @ToString
    @Entity
    @Table(name="aaproblem")
    public class Problem{
    	
    	@Id
        @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "AA_PATIENT_SEQ")
        @SequenceGenerator(sequenceName = "AA_PATIENT_SEQ", allocationSize = 1, name = "AA_PATIENT_SEQ")
    	@Column(name = "problemid")
    	private Long problemid;
    	private String problemName;
    	private String problemDetail; 
    
        @Temporal(TemporalType.TIMESTAMP)
        Date creationDate;
    	
    	@NotNull
        @ManyToOne(optional = true, fetch = FetchType.LAZY)
        @JoinColumn(name = "patient_id")
        private Patient patient;
    	
    }
英文:

if you wanna save any run class,

Run run = new Run();
City city = new City();
city.getRuns().add(run);
runRepository.save(run);

if you wanna save any run class, first you need to insert to (Arraylist) runs variable of city class like city.getRuns().add(run) after filling run then you can runRepository.save(run).

Also my samples are here. You can look at myclasses.

First class is called Patient .

@Data
@AllArgsConstructor
@NoArgsConstructor
@Entity
@ToString
@Table(name = &quot;aapatient&quot;)
public class Patient {
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = &quot;AA_PATIENT_SEQ&quot;)
@SequenceGenerator(sequenceName = &quot;AA_PATIENT_SEQ&quot;, allocationSize = 1, name = &quot;AA_PATIENT_SEQ&quot;)
@Column(name = &quot;patientid&quot;)
private Long patientid;
private String name;
private String lastname;  
@OneToMany(mappedBy = &quot;patient&quot;, cascade = CascadeType.ALL, fetch = FetchType.LAZY)
private List&lt;Problem&gt; problems; 
}

Second Class called Problem is this one.

@Data
@AllArgsConstructor
@NoArgsConstructor
@ToString
@Entity
@Table(name=&quot;aaproblem&quot;)
public class Problem{
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = &quot;AA_PATIENT_SEQ&quot;)
@SequenceGenerator(sequenceName = &quot;AA_PATIENT_SEQ&quot;, allocationSize = 1, name = &quot;AA_PATIENT_SEQ&quot;)
@Column(name = &quot;problemid&quot;)
private Long problemid;
private String problemName;
private String problemDetail; 
@Temporal(TemporalType.TIMESTAMP)
Date creationDate;
@NotNull
@ManyToOne(optional = true, fetch = FetchType.LAZY)
@JoinColumn(name = &quot;patient_id&quot;)
private Patient patient;
}

huangapple
  • 本文由 发表于 2020年3月16日 19:04:20
  • 转载请务必保留本文链接:https://go.coder-hub.com/60704774.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定