Error submitting form with selected field

In my current spring project, my forms are implemented with a structure like this:

<form class="form" id="Pagina" role="form" method="POST" action="/loja/Pagina/cadastra" enctype="multipart/form-data"> ... </form> 

and it is processed on the server by this method:

controller

 @RequestMapping(value="cadastra", method=RequestMethod.POST) @ResponseBody @ResponseStatus(HttpStatus.CREATED) public E cadastra(@ModelAttribute("object") E object, BindingResult result, @RequestParam(value="file", required=false) MultipartFile file, @RequestParam(value="icone", required=false) MultipartFile icone, @RequestParam(value="screenshot", required=false) MultipartFile screenshot[]) throws Exception { E ret = serv.cadastra(object, file, icone, screenshot); if (ret != null) return ret; else throw new Exception(); } 

services

 @PreAuthorize("hasPermission(#user, 'cadastra_'+#this.this.name)") @Transactional public E cadastra(E e, MultipartFile file, MultipartFile icone, MultipartFile[] screenshot) { return dao.persist(e); } 

My problem is that there is such a field in the form:

 <label>pagina</label> <select name="pagina.id" class="form-control select" data-lista="/loja/Pagina/listagem.json"> ... </select> <label>produto</label> <select name="produto.id" class="form-control select" data-lista="/loja/Produto/listagem.json"> ... </select> 

which displays such an attribute in the entiy class:

 @OneToOne(fetch = FetchType.EAGER) @JoinColumn(name="pagina_mae", nullable = true) @Order(value=5) @Select(name="pagina", ordem = 5) @Sidebar private Pagina pagina; @OneToOne(fetch = FetchType.EAGER) @JoinColumn(name="produto_mae", nullable = true) @Order(value=6) @Select(name="produto", ordem = 6) @Sidebar private Produto produto; 

If the parameters inside look like this:

 <option value="">.</option> <option value="...">...</option> 

If I submit the form with the empty parameter selected, I get this error:

 object references an unsaved transient instance - save the transient instance before flushing: com.spring.loja.model.pagina.persistence.model.Pagina; nested exception is org.hibernate.TransientObjectException: object references an unsaved transient instance - save the transient instance before flushing: com.spring.loja.model.pagina.persistence.model.Pagina 

but if, for example, insert the record manually into the database (in my case, using pgAdmin3) and select this element in the element, the form will be submitted without errors.

Can someone tell me how I can fix this to allow me to submit a form with or without selected data from <select> .

UPDATE

for the Pagina class:

 @Entity @Table(name="pagina") @MainForm(grupo = 2, icone = "file") public class Pagina extends ModelEntity { @Id @Column(name = "id") @GeneratedValue(strategy=GenerationType.IDENTITY) private Integer id; @Column(name = "nome", unique = true) @Order(value=1) @Input(type="hidden", name="nome", ordem = 1) private String nome; @Column(name = "titulo", nullable = false) @Order(value=2) @Input(name="titulo", ordem = 2) private String titulo; @Column(name = "descricao", length=65535) @Order(value=4) @Textarea(name="descricao", ordem = 4) private String descricao; @OneToOne(fetch = FetchType.EAGER) @JoinColumn(name="pagina_mae", nullable = true) @Order(value=5) @Select(name="pagina", ordem = 5) @Sidebar private Pagina pagina; @OneToOne(fetch = FetchType.EAGER) @JoinColumn(name="produto_mae", nullable = true) @Order(value=6) @Select(name="produto", ordem = 6) @Sidebar private Produto produto; } 

UPDATE 2

PaginaEditor.java

 @Component public class PaginaEditor extends PropertyEditorSupport { @Inject private PaginaService paginaService; @Override public void setAsText(String text) { if (!text.isEmpty()) { Pagina pagina = paginaService.getObject(text); setValue(pagina); } } } 

added to my controller:

 @InitBinder public void initBinder(WebDataBinder binder) { binder.registerCustomEditor(Pagina.class, new PaginaEditor()); } 
+7
spring spring-mvc orm hibernate
source share
1 answer

Choices are tricky in Spring MVC.

I think your problem is that when your main object moves to the data layer that is stored, the relationship does not exist there.

Try debugging and checking if the statement above is true.

There are two ways to get this sort.

Suppose the company / contact relationship in the contact system. A company has many contacts, and a contact has one company.

Countdown company.

 // package declaration imports and all @Entity @Table(name = "company") public class Company { private String name; @OneToMany(mappedBy = "company") private List<Contact> contacts = new ArrayList<Contact>(); // getter and setters and any extra stuff you fancy putting here } 

Contact fragment

 // package declaration imports and all @Entity @Table(name = "contact") public class Contact { private String name; @ManyToOne private Company company; // getter and setters and any extra stuff you fancy putting here } 

And jsp fragment with highlighted. We assume that there is a β€œcontact” object and a list of customers in the model.

 <form:form modelAttribute="contact"> <form:input path="name" /> <form:select path="customer" items="${customers}" itemValue="id" itemLabel="name" /> </form:form> 

With this code, you can use the PropertyEditor as follows.

 @Component public class CustomerEditor extends PropertyEditorSupport { @Inject private CustomerService customerService; @Override public void setAsText(String text) { if (StringUtils.isNotBlank(text)) { Customer customer = this.customerService.findById(Integer .valueOf(text)); this.setValue(customer); } } } 

and register in a Spring context like this.

 @InitBinder public void initBinder(WebDataBinder binder) { binder.registerCustomEditor(Customer.class, this.customerEditor); } 

What happens is that whenever Spring finds an object of type Customer, it will use the PropertyEditor to convert the identifier (in this case) to the object and the type with which the contact (in this case) gets the data layer (Hibernate), the corresponding Customer object will be there, waiting as happy as Larry.

This is an automatic way to do this.

Another way to do this is to create the / DTO form or whatever you want to call and add fields, including the customerId field (in this case), and transform your self before you save your entity.

Hope I got your problem right, because it took me a few minutes to write this ... :)

+5
source share

All Articles