Java Spring boot创建新行而不是更新

Java Spring boot创建新行而不是更新,java,spring,spring-boot,spring-data-jpa,thymeleaf,Java,Spring,Spring Boot,Spring Data Jpa,Thymeleaf,这些是豆子: @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") @NotNul

这些是豆子:

@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);
<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);
}

}
这是存储库保存操作:

@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);
<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);
}

}
这是updateBandForm:

@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);
<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);
}

}

名称
形成
体裁

更新波段
我还使用格式化程序:

@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);
<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);
}

}
@服务
公共类GenreFormatter实现格式化程序{
@自动连线
基因再报告基因再报告;
@凌驾
公共字符串打印(类型、区域设置){
return(genre!=null?genre.getGenreId().toString():“”);
}
@凌驾
公共类型分析(字符串文本、区域设置)引发ParseException{
整数id=Integer.valueOf(文本);
返回此.genreRepository.findById(id);
}
}
@配置
@EnableWebMvc
@ComponentScan(值={“org.springframework.samples.discography.system”})
公共类WebConfig扩展了WebMVCConfigureAdapter{
@自动连线
私有GenreFormatter GenreFormatter;
@凌驾
公共void addFormatters(FormatterRegistry注册表){
addFormatter(genreFormatter);
}
}
控制器方法创建新行,而不是更新现有行。。。有人能帮忙吗?
我遗漏了什么吗?

您的HTML表单没有ID信息

@modeldattribute
将创建一个
Band
对象,其中包含在HTML表单发送的请求参数上找到的数据

由于您的表单只有
名称
格式
类型
,因此
processUpdateBandForm
中的
对象有一个未初始化的
带id
字段,导致在
保存
时创建一个新的

在表单中添加ID信息以解决此问题

<input type="hidden" th:field="*{bandId}" /> 

在processUpdateBandForm函数中,首先需要从Db获取band对象,然后更新它。现在您只需添加一个新对象。因此,框架认为这是一个新的对象

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)
}

感谢您的回答,不幸的是,我现在得到了以下错误:org.springframework.beans.NotReadablePropertyException:bean类[org.springframework.samples.discography.band.band]的无效属性“band_id”:Bean属性“band_id”不可读或具有无效的getter方法:getter的返回类型是否与setter的参数类型匹配?您的
band
Java Bean getter和setter错误。将字段更改为
bandId
或将您的getter/setter改为
getBand\u id
setBand\u id
(如果您选择后者,请将Thymeleaf中的输入更改为
“*{band\u id}”
)。我的荣幸。:^)这里的问题是band.getBandId()返回null.ya,这是正确的,因为在本例中Id是自动生成的。所以,在这种情况下,您需要使用其他一些唯一键来搜索数据库。