我正在尝试创建一个html“编辑/新建”页面来编辑或添加新的发布者。其中一个细节是subPublishers的ArrayList。虽然如果发布者没有子发布者或者我添加新的发布者,ArrayList可能为空。
我的问题在于输入字段。我正在尝试按如下方式显示ArrayList ......
<form id="publisherForm" th:object="${publisherForm}" th:action="@{/publishers/publishers-edit/}" method="post" class="form-horizontal">
<input type="hidden" th:field="*{id}" />
<div class="row">
<div class="col-sm-6 b-r">
<div class="form-group">
<label class="col-sm-3 control-label">Publisher name: </label>
<div class="col-sm-9">
<input th:field="*{publisherName}" type="text" class="form-control" th:maxlength="45"/>
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">Description: </label>
<div class="col-sm-9">
<input th:field="*{description}" type="text" class="form-control" th:maxlength="200"/>
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">Enabled: </label>
<div class="col-sm-9">
<input th:field="*{status}" value="ENABLED" type="checkbox"/>
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">Website URL: </label>
<div class="col-sm-9">
<input th:field="*{websiteURL}" type="text" class="form-control" th:maxlength="50"/>
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">Subpublishers: </label>
<div class="col-sm-9">
<div class="table-responsive">
<table class="table table-bordered table-striped">
<thead>
<th>
<button class="btn btn-white" type="submit" name="addRow">+</button>
</th>
</thead>
<tbody>
<tr th:each="subPublisher,stat : *{subPublishers}">
<td>
<input type="text" class="form-control" th:field="*{subPublishers[__${stat.index}__].name}" />
</td>
<td>
<button class="btn btn-white" type="submit" name="removeRow" th:value="${stat.index}">-</button>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-sm-6">
<div class="form-group">
<div class="col-sm-9 col-sm-offset-3">
<button class="btn btn-primary" type="submit">Save</button>
<a class="btn btn-white" th:href="@{/publishers}">Cancel</a>
</div>
</div>
</div>
</div>
</form>
控制器
@MenuController(value = "/publisher", item = Item.Publishers)
public class PublisherController {
private PublisherService publisherService;
private PublisherConverter publisherConverter;
private SubPublisherConverter subPublisherConverter;
public PublisherController(PublisherService publisherService, PublisherConverter publisherConverter, SubPublisherConverter subPublisherConverter) {
this.publisherService = publisherService;
this.publisherConverter = publisherConverter;
this.subPublisherConverter = subPublisherConverter;
}
@GetMapping
public String newPublisher( Model model) {
PublisherResource publisher = new PublisherResource();
publisher.setStatus(true);
publisher.setSubPublishers(new ArrayList<SubPublisherResource>());
return showPage(publisher, model);
}
protected String showPage(PublisherResource publisher, Model model) {
model.addAttribute("publisherForm", publisher);
return "publishers/publishers-edit";
}
@PostMapping
public String createPublisher(@ModelAttribute("publisherForm") @Validated PublisherResource resource, BindingResult result, Model model) {
if (result.hasErrors()) {
return showPage(resource, model);
}
return savePublisher(0, resource);
}
@GetMapping("/{publisherId}")
public String editPublisher(@PathVariable int publisherId, Model model) {
Publisher publisher = publisherService.getPublisher(publisherId);
PublisherResource res = publisherConverter.convert(publisher);
res.setSubPublishers(publisherService.getSubPublishers(publisher).stream()
.map(s -> subPublisherConverter.convert(s))
.collect(Collectors.toList())
);
return showPage(res, model);
}
@PostMapping("/{publisherId}")
public String updatePublisher(@PathVariable int publisherId, @ModelAttribute("publisherForm") @Validated PublisherResource resource, BindingResult result, Model model) {
if (result.hasErrors()) {
return showPage(resource, model);
}
return savePublisher(publisherId, resource);
}
protected String savePublisher(int publisherId, PublisherResource resource) {
Publisher publisher = populatePublisher(publisherId, resource);
List<SubPublisher> subPublishers = populateSubPublishers(resource);
if (publisherId == 0) {
publisherService.createPublisher(publisher, subPublishers);
} else {
publisherService.updatePublisher(publisher, subPublishers);
}
return "redirect:/publishers";
}
protected Publisher populatePublisher(int publisherId, PublisherResource resource) {
Publisher publisher = null;
if (publisherId == 0) {
publisher = new Publisher();
publisher.setTimeAdded(new Date());
} else {
publisher = publisherService.getPublisher(publisherId);
}
publisher.setPublisherName(resource.getPublisherName());
publisher.setDescription(resource.getDescription());
publisher.setStatus(resource.isStatus());
publisher.setWebsiteURL(resource.getWebsiteURL());
return publisher;
}
protected List<SubPublisher> populateSubPublishers(PublisherResource resource){
if(resource.getSubPublishers() != null){
return resource.getSubPublishers().stream()
.map(s -> {
SubPublisher subPublisher = new SubPublisher();
subPublisher.setName(s.getName());
return subPublisher;
})
.collect(Collectors.toList());
}
return Collections.emptyList();
}
@PostMapping(params={"addRow"})
public String addRow(final PublisherResource publisher, final BindingResult bindingResult, Model model) {
publisher.getSubPublishers().add(new SubPublisherResource());
return showPage(publisher, model);
}
@PostMapping(params={"removeRow"})
public String removeRow(final PublisherResource publisher, final BindingResult bindingResult,
final HttpServletRequest req, Model model) {
final Integer rowId = Integer.valueOf(req.getParameter("removeRow"));
publisher.getSubPublishers().remove(rowId.intValue());
return showPage(publisher, model);
}
}
PublisherResource
public class PublisherResource {
private int id;
private String publisherName;
private String description;
private boolean status;
private String websiteURL;
private List<SubPublisherResource> subPublishers = new ArrayList<>();
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getPublisherName() {
return publisherName;
}
public void setPublisherName(String publisherName) {
this.publisherName = publisherName;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public boolean isStatus() {
return status;
}
public void setStatus(boolean status) {
this.status = status;
}
public String getWebsiteURL() {
return websiteURL;
}
public void setWebsiteURL(String websiteURL) {
this.websiteURL = websiteURL;
}
public List<SubPublisherResource> getSubPublishers() {
return subPublishers;
}
public void setSubPublishers(List<SubPublisherResource> subPublishers) {
this.subPublishers = subPublishers;
}
}
我使用来自thymeleaf文档http://www.thymeleaf.org/doc/tutorials/2.1/thymeleafspring.html#dynamic-fields
的exampel问题是当ArrayList为空时,输入字段不会显示在页面上!此外,当编辑具有子发布者的发布者时,如果我删除所有这些,我会丢失输入字段,并且我无法添加任何其他子发布者。这几乎使得无法添加子发布者。
这是如何处理Thymeleaf的?
更新控制器
@MenuController(value = "/publisher", item = Item.Publishers)
public class PublisherController {
private PublisherResource publisherResource;
private PublisherService publisherService;
private PublisherConverter publisherConverter;
private SubPublisherConverter subPublisherConverter;
public PublisherController(PublisherResource publisherResource, PublisherService publisherService,
PublisherConverter publisherConverter, SubPublisherConverter subPublisherConverter) {
this.publisherResource = publisherResource;
this.publisherService = publisherService;
this.publisherConverter = publisherConverter;
this.subPublisherConverter = subPublisherConverter;
}
@GetMapping
public String newPublisher( Model model) {
PublisherResource publisher = new PublisherResource();
publisher.setStatus(true);
publisher.setSubPublishers(new ArrayList<SubPublisherResource>());
return showPage(publisher, model);
}
protected String showPage(PublisherResource publisher, Model model) {
model.addAttribute("publisherForm", publisher);
return "publishers/publishers-edit";
}
@PostMapping
public String createPublisher(@ModelAttribute("publisherForm") @Validated PublisherResource resource, BindingResult result, Model model) {
if (result.hasErrors()) {
return showPage(resource, model);
}
return savePublisher(0, resource);
}
@GetMapping
public String editPublisher(Model model) {
Publisher publisher = publisherService.getPublisher(publisherResource.getId());
PublisherResource res = publisherConverter.convert(publisher);
res.setSubPublishers(publisherService.getSubPublishers(publisher).stream()
.map(s -> subPublisherConverter.convert(s))
.collect(Collectors.toList())
);
return showPage(res, model);
}
@PostMapping
public String updatePublisher( @ModelAttribute("publisherForm") @Validated PublisherResource resource, BindingResult result, Model model) {
if (result.hasErrors()) {
return showPage(resource, model);
}
return savePublisher(publisherResource.getId(), resource);
}
protected String savePublisher(int publisherId, PublisherResource resource) {
Publisher publisher = populatePublisher(publisherId, resource);
List<SubPublisher> subPublishers = populateSubPublishers(resource);
if (publisherId == 0) {
publisherService.createPublisher(publisher, subPublishers);
} else {
publisherService.updatePublisher(publisher, subPublishers);
}
return "redirect:/publishers";
}
protected Publisher populatePublisher(int publisherId, PublisherResource resource) {
Publisher publisher = null;
if (publisherId == 0) {
publisher = new Publisher();
publisher.setTimeAdded(new Date());
} else {
publisher = publisherService.getPublisher(publisherId);
}
publisher.setPublisherName(resource.getPublisherName());
publisher.setDescription(resource.getDescription());
publisher.setStatus(resource.isStatus());
publisher.setWebsiteURL(resource.getWebsiteURL());
return publisher;
}
protected List<SubPublisher> populateSubPublishers(PublisherResource resource){
if(resource.getSubPublishers() != null){
return resource.getSubPublishers().stream()
.map(s -> {
SubPublisher subPublisher = new SubPublisher();
subPublisher.setName(s.getName());
return subPublisher;
})
.collect(Collectors.toList());
}
return Collections.emptyList();
}
@PostMapping(params={"addRow"})
public String addRow(final PublisherResource publisher, final BindingResult bindingResult, Model model) {
publisher.getSubPublishers().add(new SubPublisherResource());
return showPage(publisher, model);
}
@PostMapping(params={"removeRow"})
public String removeRow(final PublisherResource publisher, final BindingResult bindingResult,
final HttpServletRequest req, Model model) {
final Integer rowId = Integer.valueOf(req.getParameter("removeRow"));
publisher.getSubPublishers().remove(rowId.intValue());
return showPage(publisher, model);
}
}
更新2 - 所有代码:
实体发布商和子发布商:
@Entity
@Table(name = "publisher")
public class Publisher {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id")
private int id;
@Column(name = "name")
private String publisherName;
@Column(name = "description")
private String description;
@Column(name = "status")
private boolean status;
@Column(name = "website_url")
private String websiteURL;
@Column(name = "time_added")
private Date timeAdded;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getPublisherName() {
return publisherName;
}
public void setPublisherName(String publisherName) {
this.publisherName = publisherName;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public boolean isStatus() {
return status;
}
public void setStatus(boolean status) {
this.status = status;
}
public String getWebsiteURL() {
return websiteURL;
}
public void setWebsiteURL(String websiteURL) {
this.websiteURL = websiteURL;
}
public Date getTimeAdded() {
return timeAdded;
}
public void setTimeAdded(Date timeAdded) {
this.timeAdded = timeAdded;
}
}
@Entity
@Table(name = "sub_publisher")
public class SubPublisher {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id")
private int id;
@OneToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "publisher_id")
private Publisher publisher;
@Column(name = "name")
private String name;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public Publisher getPublisher() {
return publisher;
}
public void setPublisher(Publisher publisher) {
this.publisher = publisher;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
存储库
public interface PublisherRepository extends JpaDataTableRepository<Publisher, Integer> {
public Publisher findById(int id);
}
public interface SubPublisherRepository extends JpaRepository<SubPublisher, Integer> {
List<SubPublisher> findByPublisher(Publisher publisher);
void deleteByPublisher(Publisher publisher);
}
PublisherResource
public class PublisherResource {
private int id;
private String publisherName;
private String description;
private boolean status;
private String websiteURL;
private List<SubPublisherResource> subPublishers = new ArrayList<>();
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getPublisherName() {
return publisherName;
}
public void setPublisherName(String publisherName) {
this.publisherName = publisherName;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public boolean isStatus() {
return status;
}
public void setStatus(boolean status) {
this.status = status;
}
public String getWebsiteURL() {
return websiteURL;
}
public void setWebsiteURL(String websiteURL) {
this.websiteURL = websiteURL;
}
public List<SubPublisherResource> getSubPublishers() {
return subPublishers;
}
public void setSubPublishers(List<SubPublisherResource> subPublishers) {
this.subPublishers = subPublishers;
}
}
SubPublisherResource
public class SubPublisherResource {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
PublisherController
@Controller
@RequestMapping("/publisher")
public class PublisherController {
private PublisherService publisherService;
private PublisherConverter publisherConverter;
private SubPublisherConverter subPublisherConverter;
@Autowired
public PublisherController(PublisherService publisherService, PublisherConverter publisherConverter, SubPublisherConverter subPublisherConverter) {
this.publisherService = publisherService;
this.publisherConverter = publisherConverter;
this.subPublisherConverter = subPublisherConverter;
}
@GetMapping
public String newPublisher(Model model) {
PublisherResource publisher = new PublisherResource();
publisher.setStatus(true);
return showPage(publisher, model);
}
protected String showPage(PublisherResource publisher, Model model) {
model.addAttribute("publisherForm", publisher);
return "/publishers/publishers-edit";
}
@PostMapping
public String createPublisher(@ModelAttribute("publisherForm") @Validated PublisherResource resource, BindingResult result, Model model) {
if(result.hasErrors()) {
return showPage(resource, model);
}
return savePublisher(resource);
}
@GetMapping("/{id}")
public String editPublisher(@PathVariable("id") Integer id, Model model) {
Publisher publisher = publisherService.getPublisher(id);
PublisherResource res = publisherConverter.convert(publisher);
res.setSubPublishers(publisherService.getSubPublishers(publisher).stream().map(s->subPublisherConverter.convert(s)).collect(Collectors.toList()));
return showPage(res, model);
}
protected String savePublisher(PublisherResource resource) {
Publisher publisher = populatePublisher(resource);
List<SubPublisher> subPublishers = populateSubPublishers(resource);
if(resource.getId() == 0) {
publisherService.createPublisher(publisher, subPublishers);
} else {
publisherService.updatePublisher(publisher, subPublishers);
}
return "redirect:/publishers";
}
protected Publisher populatePublisher(PublisherResource resource) {
Publisher publisher;
if(resource.getId() == 0) {
publisher = new Publisher();
publisher.setTimeAdded(new Date());
} else {
publisher = publisherService.getPublisher(resource.getId());
}
publisher.setPublisherName(resource.getPublisherName());
publisher.setDescription(resource.getDescription());
publisher.setStatus(resource.isStatus());
publisher.setWebsiteURL(resource.getWebsiteURL());
return publisher;
}
protected List<SubPublisher> populateSubPublishers(PublisherResource resource) {
if(resource.getSubPublishers() != null) {
return resource.getSubPublishers().stream().map(s->{
SubPublisher subPublisher = new SubPublisher();
subPublisher.setName(s.getName());
return subPublisher;
}).collect(Collectors.toList());
}
return Collections.emptyList();
}
@PostMapping(params = { "addRow" })
public String addRow(final PublisherResource publisher, Model model) {
publisher.getSubPublishers().add(new SubPublisher());
return showPage(publisher, model);
}
@PostMapping(params = { "removeRow" })
public String removeRow(final PublisherResource publisher, final HttpServletRequest req, Model model) {
final Integer rowId = Integer.valueOf(req.getParameter("removeRow"));
publisher.getSubPublishers().remove(rowId.intValue());
return showPage(publisher, model);
}
}
PublishersController
@MenuController(value = "/publishers", item = Item.Publishers)
public class PublishersController {
private PublisherService publisherService;
private PublisherConverter publisherConverter;
public PublishersController(PublisherService publisherService, PublisherConverter publisherConverter) {
this.publisherService = publisherService;
this.publisherConverter = publisherConverter;
}
@GetMapping
public String showPage() {
return "publishers/publishers";
}
@PostMapping("/data")
public @ResponseBody DataTableResponse<PublisherResource> getPublishers(@RequestBody DataTableRequest request) {
return publisherConverter.convertResponse(publisherService.getPublishers(request));
}
@DeleteMapping("/{publisherIds}")
@ResponseStatus(HttpStatus.NO_CONTENT)
public void deletePublishers(@PathVariable Integer[] publisherIds) {
for (Integer publisherId: publisherIds) {
publisherService.deletePublisher(publisherId);
}
}
@PutMapping("/{publisherIds}/disable")
@ResponseStatus(HttpStatus.ACCEPTED)
public void disablePublishers(@PathVariable Integer[] publisherIds) {
changeStatus(publisherIds);
}
@PutMapping("/{publisherIds}/enable")
@ResponseStatus(HttpStatus.ACCEPTED)
public void enablePublishers(@PathVariable Integer[] publisherIds) {
changeStatus(publisherIds);
}
protected void changeStatus(Integer[] publisherIds) {
for (Integer publisherId: publisherIds) {
publisherService.updateStatus(publisherId);
}
}
}
PublisherConverter
@Component
public class PublisherConverter implements ResourceConverter<Publisher, PublisherResource> {
public PublisherResource convert(Publisher publisher) {
PublisherResource resource = new PublisherResource();
resource.setId(publisher.getId());
resource.setPublisherName(publisher.getPublisherName());
resource.setDescription(publisher.getDescription());
resource.setStatus(publisher.isStatus());
resource.setWebsiteURL(publisher.getWebsiteURL());
return resource;
}
}
PublisherService
@Service
public class PublisherService {
private PublisherRepository publisherRepository;
private SubPublisherRepository subPublisherRepository;
public PublisherService(PublisherRepository publisherRepository, SubPublisherRepository subPublisherRepository) {
this.publisherRepository = publisherRepository;
this.subPublisherRepository = subPublisherRepository;
}
public DataTableResponse<Publisher> getPublishers(DataTableRequest request) {
return publisherRepository.findAll(request);
}
@Transactional
public Publisher getPublisher(int publisherId) {
Publisher publisher = publisherRepository.findById(publisherId);
if(publisher != null){
List<SubPublisher> subPublishers = subPublisherRepository.findByPublisher(publisher);
//populateSubPublishers(subPublishers);
subPublishers.stream().forEach(s -> {
if(s.getId() == 0){
s.setPublisher(publisher);
subPublisherRepository.save(s);
}
});
}
if(publisher == null) {
throw new NotFoundException("Publisher " + publisherId + " not found.");
}
return publisher;
}
private void populateSubPublishers(List<SubPublisher> subPublishers) {
for(SubPublisher subPublisher : subPublishers){
subPublishers.add(subPublisher);
System.out.println(subPublisher.getName());
}
}
@Transactional
public Publisher createPublisher(Publisher publisher, List<SubPublisher> subPublishers) {
publisher = publisherRepository.save(publisher);
createSubPublisher(publisher, subPublishers);
return publisher;
}
private void createSubPublisher(Publisher publisher, List<SubPublisher> subPublishers) {
populateSubPublishers(subPublishers);
for(SubPublisher subPublisher : subPublishers){
subPublisher.setPublisher(publisher);
subPublisher.setName(subPublisher.getName());
}
}
@Transactional
public Publisher updatePublisher(Publisher publisher, List<SubPublisher> subPublishers) {
publisher = publisherRepository.save(publisher);
createSubPublishers(publisher, subPublishers);
return publisher;
}
private void createSubPublishers(Publisher publisher, List<SubPublisher> subPublishers) {
subPublisherRepository.deleteByPublisher(publisher);
for (SubPublisher sp : subPublishers) {
sp.setPublisher(publisher);
sp = subPublisherRepository.save(sp);
}
}
@Transactional
public void updateStatus(int publisherId) {
Publisher publisher = publisherRepository.findOne(publisherId);
if(publisher != null && publisher.isStatus() != false){
publisher.setStatus(false);
publisherRepository.save(publisher);
}
else if(publisher != null && publisher.isStatus() != true ){
publisher.setStatus(true);
publisherRepository.save(publisher);
}
}
@Transactional
public void deletePublisher(int publisherId) {
Publisher publisher = publisherRepository.findOne(publisherId);
if (publisher != null) {
publisherRepository.delete(publisher);
}
}
public List<SubPublisher> getSubPublishers(Publisher publisher){
return subPublisherRepository.findByPublisher(publisher);
}
}
SubPublisherConverter
@Component
public class SubPublisherConverter implements ResourceConverter<SubPublisher, SubPublisherResource> {
@Override
public SubPublisherResource convert(SubPublisher subPublisher) {
SubPublisherResource resource = new SubPublisherResource();
resource.setName(subPublisher.getName());
return resource;
}
}
错误
java.util.ConcurrentModificationException: null
at java.util.ArrayList$Itr.checkForComodification(Unknown Source)
at java.util.ArrayList$Itr.next(Unknown Source)
at publishers.PublisherService.populateSubPublishers(PublisherService.java:58)
at publishers.PublisherService.createSubPublisher(PublisherService.java:74)
at publishers.PublisherService.createPublisher(PublisherService.java:68)
答案 0 :(得分:0)
所以这是一个例子。您需要将控制器(/test/test
)的映射替换为/publishers/publishers-edit
。控制器:
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import javax.servlet.http.HttpServletRequest;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;
@Controller
@RequestMapping("/test/test")
public class PublisherController {
private PublisherService publisherService;
private PublisherConverter publisherConverter;
private SubPublisherConverter subPublisherConverter;
@Autowired
public PublisherController(PublisherService publisherService, PublisherConverter publisherConverter, SubPublisherConverter subPublisherConverter) {
this.publisherService = publisherService;
this.publisherConverter = publisherConverter;
this.subPublisherConverter = subPublisherConverter;
}
@GetMapping
public String newPublisher(Model model) {
PublisherResource publisher = new PublisherResource();
publisher.setStatus(true);
return showPage(publisher, model);
}
protected String showPage(PublisherResource publisher, Model model) {
model.addAttribute("publisherForm", publisher);
return "test/test";
}
@PostMapping
public String createPublisher(@ModelAttribute("publisherForm") @Validated PublisherResource resource, BindingResult result, Model model) {
if(result.hasErrors()) {
return showPage(resource, model);
}
return savePublisher(resource);
}
@GetMapping("/{id}")
public String editPublisher(@PathVariable("id") Integer id, Model model) {
Publisher publisher = publisherService.getPublisher(id);
PublisherResource res = publisherConverter.convert(publisher);
res.setSubPublishers(publisherService.getSubPublishers(publisher).stream().map(s->subPublisherConverter.convert(s)).collect(Collectors.toList()));
return showPage(res, model);
}
protected String savePublisher(PublisherResource resource) {
Publisher publisher = populatePublisher(resource);
List<SubPublisher> subPublishers = populateSubPublishers(resource);
if(resource.getId() == 0) {
publisherService.createPublisher(publisher, subPublishers);
} else {
publisherService.updatePublisher(publisher, subPublishers);
}
return "redirect:/publishers";
}
protected Publisher populatePublisher(PublisherResource resource) {
Publisher publisher;
if(resource.getId() == 0) {
publisher = new Publisher();
publisher.setTimeAdded(new Date());
} else {
publisher = publisherService.getPublisher(resource.getId());
}
publisher.setPublisherName(resource.getPublisherName());
publisher.setDescription(resource.getDescription());
publisher.setStatus(resource.isStatus());
publisher.setWebsiteURL(resource.getWebsiteURL());
return publisher;
}
protected List<SubPublisher> populateSubPublishers(PublisherResource resource) {
if(resource.getSubPublishers() != null) {
return resource.getSubPublishers().stream().map(s->{
SubPublisher subPublisher = new SubPublisher();
subPublisher.setName(s.getName());
return subPublisher;
}).collect(Collectors.toList());
}
return Collections.emptyList();
}
@PostMapping(params = { "addRow" })
public String addRow(@ModelAttribute("publisherForm") final PublisherResource publisher, Model model) {
publisher.getSubPublishers().add(new SubPublisher());
return showPage(publisher, model);
}
@PostMapping(params = { "removeRow" })
public String removeRow(@ModelAttribute("publisherForm") final PublisherResource publisher, final HttpServletRequest req, Model model) {
final Integer rowId = Integer.valueOf(req.getParameter("removeRow"));
publisher.getSubPublishers().remove(rowId.intValue());
return showPage(publisher, model);
}
}
<强>更新强>
我清理了您的PublisherService并将其拆分为PublisherService和SubPublisherService。那些服务是可能的。可选,但我更喜欢在大多数情况下在存储库和我的程序之间有另一层。
我还清理了PublisherController。 savePublisher
改变了很多。它记录在案。
发布商现在还有一个包含发布服务器的所有SubPublishers的列表。上一页。你是通过代码获取这个。但JPA可以为您做到这一点。
PublisherController:
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.validation.BindingResult;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
@Controller
@RequestMapping("/test/test")
public class PublisherController {
private PublisherService publisherService;
private SubPublisherService subPublisherService;
@Autowired
public PublisherController(PublisherService publisherService, SubPublisherService subPublisherService) {
this.publisherService = publisherService;
this.subPublisherService = subPublisherService;
}
private ModelAndView showPage(PublisherResource publisher) {
final ModelAndView modelAndView = new ModelAndView("test/test");
modelAndView.addObject("publisherForm", publisher);
return modelAndView;
}
@GetMapping
public ModelAndView createPublisher() {
PublisherResource publisher = new PublisherResource();
publisher.setStatus(true);
return showPage(publisher);
}
@GetMapping("/{id}")
public ModelAndView editPublisher(@PathVariable("id") Integer id) {
Publisher publisher = publisherService.getPublisher(id);
return showPage(PublisherConverter.convert(publisher));
}
@PostMapping
public ModelAndView savePublisher(@ModelAttribute("publisherForm") @Validated PublisherResource resource, BindingResult result) {
if(result.hasErrors()) {
return showPage(resource);
}
return savePublisher(resource);
}
private ModelAndView savePublisher(PublisherResource resource) {
// create the publisher
Publisher publisher;
if(resource.getId() == 0) {
publisher = new Publisher();
publisher.setTimeAdded(new Date());
publisher = publisherService.save(publisher);
} else {
publisher = publisherService.getPublisher(resource.getId());
}
/* -- this will update the SubPublishers -- */
final List<SubPublisher> toDelete = publisher.getSubPublishers();
final List<SubPublisher> toSave = new ArrayList<>();
final Publisher forLambda = publisher;
// first we will iterate over all the SubPublishers that where specified by the user (in the form)
resource.getSubPublishers().forEach(name->{
// we will then try to find any existing SubPublisher for the given name and publisher (to avoid duplicated database entries)
final SubPublisher subPublisher = subPublisherService.getOrCreateSubPublisher(forLambda, name);
// we will also save the SubPublisher reference for later
toSave.add(subPublisher);
// and then we will remove the SubPublisher that we just found from the List of SubPublishers from the original Publisher (that was stored in the db)
toDelete.removeIf(s->subPublisher.getId() == s.getId());
});
// effectively it will leave us with a list (toDelete) that will include all SubPublishers that have to be deleted
for(SubPublisher subPublisher : toDelete) {
// and this is what we will to here
subPublisherService.delete(subPublisher);
}
// after we cleaned up all unused references
publisher.getSubPublishers().clear();
// update the subPublisher list to contain all SubPublishers that where specified by the user input (the parsed ones)
publisher.getSubPublishers().addAll(toSave);
/* -- end -- */
// update all remaining fields
publisher.setPublisherName(resource.getPublisherName());
publisher.setDescription(resource.getDescription());
publisher.setStatus(resource.isStatus());
publisher.setWebsiteURL(resource.getWebsiteURL());
publisherService.save(publisher);
return new ModelAndView("redirect:/test/list");
}
@PostMapping(params = { "addRow" })
public ModelAndView addRow(@ModelAttribute("publisherForm") final PublisherResource publisher) {
publisher.getSubPublishers().add("");
return showPage(publisher);
}
@PostMapping(params = { "removeRow" })
public ModelAndView removeRow(@ModelAttribute("publisherForm") final PublisherResource publisher, final HttpServletRequest req) {
final Integer rowId = Integer.valueOf(req.getParameter("removeRow"));
publisher.getSubPublishers().remove(rowId.intValue());
return showPage(publisher);
}
}
出版商:
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
@Entity
@Table
public class Publisher {
private int id;
private String publisherName;
private String description;
private boolean status;
private String websiteURL;
private Date timeAdded;
private List<SubPublisher> subPublishers = new ArrayList<>();
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
@Column
public String getPublisherName() {
return publisherName;
}
public void setPublisherName(String publisherName) {
this.publisherName = publisherName;
}
@Column
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
@Column
public boolean isStatus() {
return status;
}
public void setStatus(boolean status) {
this.status = status;
}
@Column
public String getWebsiteURL() {
return websiteURL;
}
public void setWebsiteURL(String websiteURL) {
this.websiteURL = websiteURL;
}
@Column
public Date getTimeAdded() {
return timeAdded;
}
public void setTimeAdded(Date timeAdded) {
this.timeAdded = timeAdded;
}
@OneToMany(mappedBy = "publisher")
public List<SubPublisher> getSubPublishers() {
return subPublishers;
}
public void setSubPublishers(List<SubPublisher> subPublishers) {
this.subPublishers = subPublishers;
}
@Override
public String toString() {
return "Publisher{" + "id=" + id + ", publisherName='" + publisherName + '\'' + ", description='" + description + '\'' + ", status=" + status + ", websiteURL='" + websiteURL + '\'' + ", timeAdded=" + timeAdded + ", subPublishers=" + subPublishers + '}';
}
}
PublisherResource:
import java.util.ArrayList;
import java.util.List;
public class PublisherResource {
private int id;
private String publisherName;
private String description;
private boolean status;
private String websiteURL;
private List<String> subPublishers = new ArrayList<>();
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getPublisherName() {
return publisherName;
}
public void setPublisherName(String publisherName) {
this.publisherName = publisherName;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public boolean isStatus() {
return status;
}
public void setStatus(boolean status) {
this.status = status;
}
public String getWebsiteURL() {
return websiteURL;
}
public void setWebsiteURL(String websiteURL) {
this.websiteURL = websiteURL;
}
public List<String> getSubPublishers() {
return subPublishers;
}
public void setSubPublishers(List<String> subPublishers) {
this.subPublishers = subPublishers;
}
}
PublisherService:
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class PublisherService {
private PublisherRepository publisherRepository;
@Autowired
public void setPublisherRepository(PublisherRepository publisherRepository) {
this.publisherRepository = publisherRepository;
}
public Publisher save(Publisher toSave) {
return publisherRepository.save(toSave);
}
public void delete(Publisher toDelete) {
publisherRepository.delete(toDelete);
}
public Publisher getPublisher(Integer id) {
return publisherRepository.findOne(id);
}
public Iterable<Publisher> getAll() {
return publisherRepository.findAll();
}
}
PublisherRepository:
import org.springframework.data.repository.CrudRepository;
public interface PublisherRepository extends CrudRepository<Publisher, Integer> {}
PublisherConverter:
import java.util.stream.Collectors;
public class PublisherConverter {
public static PublisherResource convert(Publisher publisher) {
PublisherResource resource = new PublisherResource();
resource.setId(publisher.getId());
resource.setPublisherName(publisher.getPublisherName());
resource.setDescription(publisher.getDescription());
resource.setStatus(publisher.isStatus());
resource.setWebsiteURL(publisher.getWebsiteURL());
resource.getSubPublishers().addAll(publisher.getSubPublishers().stream().map(SubPublisher::getName).collect(Collectors.toList()));
return resource;
}
}
SubPublisher:
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.OneToOne;
import javax.persistence.Table;
@Entity
@Table
public class SubPublisher {
private int id;
private Publisher publisher;
private String name;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
@OneToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "publisherId")
public Publisher getPublisher() {
return publisher;
}
public void setPublisher(Publisher publisher) {
this.publisher = publisher;
}
@Column
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
SubPublisherRepository:
import org.springframework.data.repository.CrudRepository;
public interface SubPublisherRepository extends CrudRepository<SubPublisher, Integer> {
SubPublisher findByPublisherAndAndName(Publisher publisher, String name);
}
SubPublisherService:
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class SubPublisherService {
private SubPublisherRepository subPublisherRepository;
@Autowired
public void setSubPublisherRepository(SubPublisherRepository subPublisherRepository) {
this.subPublisherRepository = subPublisherRepository;
}
public SubPublisher save(SubPublisher toSave) {
return subPublisherRepository.save(toSave);
}
public void delete(SubPublisher toDelete) {
subPublisherRepository.delete(toDelete);
}
/**
* This method will either find any existing SubPublisher by the Name and the Publisher or create one if none existed.
*/
public SubPublisher getOrCreateSubPublisher(Publisher publisher, String name) {
SubPublisher subPublisher = subPublisherRepository.findByPublisherAndAndName(publisher, name);
if(subPublisher == null) {
subPublisher = new SubPublisher();
subPublisher.setPublisher(publisher);
subPublisher.setName(name);
subPublisher = save(subPublisher);
}
return subPublisher;
}
public Iterable<SubPublisher> getAll() {
return subPublisherRepository.findAll();
}
}
在html中,我将<input type="text" class="form-control" th:field="*{subPublishers[__${stat.index}__].name}" />
更改为<input type="text" class="form-control" th:field="*{subPublishers[__${stat.index}__].}" />