Spring Boot 创建新行而不是更新
Posted
技术标签:
【中文标题】Spring Boot 创建新行而不是更新【英文标题】:Spring boot creates new row instead of updating 【发布时间】:2017-11-03 22:39:19 【问题描述】:这些是豆子:
@Entity
@Table(name = "bands")
public class Band implements Serializable
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
public Integer band_id;
@Column(name = "name")
@NotEmpty
public String name;
@Column(name = "formed")
@NotNull
public Integer formed;
@ManyToOne
@JoinColumn(name = "genre_id")
public Genre genre;
public Integer getBandId()
return band_id;
public void setBandId(Integer band_id)
this.band_id = band_id;
public String getName()
return this.name;
public void setName(String name)
this.name = name;
public Integer getFormed()
return this.formed;
public void setFormed(Integer formed)
this.formed = formed;
public Genre getGenre()
return genre;
public void setGenre(Genre genre)
this.genre = genre;
@XmlElement
public Genre getGenres()
Genre genre = getGenre();
return genre;
@Entity
@Table(name = "genres")
@Access(AccessType.FIELD)
public class Genre implements Serializable
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
public Integer genre_id;
@Column(name = "name")
@NotEmpty
public String name;
@OneToMany(cascade = CascadeType.ALL, mappedBy = "genre")
public Set<Band> bands;
public Integer getGenreId()
return genre_id;
public void setGenreId(Integer genre_id)
this.genre_id = genre_id;
public String getName()
return this.name;
public void setName(String name)
this.name = name;
public Set<Band> getBands()
return this.bands;
public void setBands(Set<Band> bands)
this.bands = bands;
这是控制器中初始化页面然后调用保存操作的部分:
@RequestMapping(value = "/bands/band_id/edit", method = RequestMethod.GET)
public String initUpdateBandForm(@PathVariable("band_id") int band_id, ModelMap model)
model.addAttribute("genres", this.bandRepository.findAllGenres());
Band band = this.bandRepository.findById(band_id);
model.addAttribute("band", band);
return "bands/updateBandForm";
@RequestMapping(value = "bands/band_id/edit", method = RequestMethod.POST)
public String processUpdateBandForm(@Valid @ModelAttribute("band") Band band, BindingResult result)
if (result.hasErrors())
return "bands/updateBandForm";
else
this.bandRepository.save(band);
return "redirect:/bands/band_id";
这是存储库保存操作:
void save(Band band);
这是 updateBandForm:
<form th:object="$band" method="post">
<label>Name</label>
<input type="text" th:field="*name" />
<label>Formed</label>
<input type="text" th:field="*formed" />
<label>Genre</label>
<select th:field="*genre">
<option th:each="genre: $genres" th:value="$genre" th:text="$genre.name" />
</select>
<br>
<button type="submit">Update Band</button>
</form>
我也使用格式化程序:
@Service
public class GenreFormatter implements Formatter<Genre>
@Autowired
GenreRepository genreRepository;
@Override
public String print(Genre genre, Locale locale)
return (genre != null ? genre.getGenreId().toString() : "");
@Override
public Genre parse(String text, Locale locale) throws ParseException
Integer id = Integer.valueOf(text);
return this.genreRepository.findById(id);
@Configuration
@EnableWebMvc
@ComponentScan(value = "org.springframework.samples.discography.system")
public class WebConfig extends WebMvcConfigurerAdapter
@Autowired
private GenreFormatter genreFormatter;
@Override
public void addFormatters(FormatterRegistry registry)
registry.addFormatter(genreFormatter);
控制器方法创建一个新行而不是更新现有行...有人可以帮忙吗? 我错过了什么吗?
【问题讨论】:
【参考方案1】:首先在您的 processUpdateBandForm 函数中,您需要先从 Db 获取带对象,然后对其进行更新。现在您只是添加一个新对象。所以框架认为它是一个新对象。
public String processUpdateBandForm(@Valid @ModelAttribute("band") Band band, BindingResult result)
Band bandFromDb = this.bandRepository.findById(band.getBandId);
//compare band and bandFromDb and update fields from band to bandFromDb.
//Dont change the id field which is band_id(this will create new object)
this.bandRepository.save(bandFromDb)
【讨论】:
这里的问题是band.getBandId()返回null。 是的,因为在这种情况下 ID 是自动生成的。因此,在这种情况下,您需要使用其他一些唯一键来搜索数据库。【参考方案2】:您的 html 表单没有 ID 信息。
@ModelAttribute
将创建一个 Band
对象,其中包含在 HTML 表单发送的请求参数中找到的数据。
由于您的表单只有name
、formed
和genre
,所以processUpdateBandForm
中的Band
对象有一个未初始化的band_id
字段,从而导致在@987654330 上创建一个新的Band
@。
在表单中添加 ID 信息以解决此问题。
<input type="hidden" th:field="*bandId" />
【讨论】:
谢谢你的回答,不幸的是我现在得到这个错误:org.springframework.beans.NotReadablePropertyException: Invalid property 'band_id' of bean class [org.springframework.samples.discography.band.Band] : Bean 属性 'band_id' 不可读或有无效的 getter 方法:getter 的返回类型是否与 setter 的参数类型匹配? 您的Band
Java bean getter 和 setter 错误。将字段更改为 bandId
或将您的 getter/setter 修复为 getBand_id
和 setBand_id
(如果您执行后者,请将 Thymeleaf 中的输入更改为 "*band_id"
)。
我的荣幸。 :^)以上是关于Spring Boot 创建新行而不是更新的主要内容,如果未能解决你的问题,请参考以下文章
更新 Spring Boot 以生成 WAR 文件而不是 JAR 文件
spring boot 配置属性 之 spring.profiles.include