Trying to save child entity containing 2 existing parents in the DB ( user and type , the user works fine) , i don't know why it tells me the type is transient while i got it ( populated the dropdown list) from the DB i get :
WARN UnresolvedEntityInsertActions - HHH000437: Attempting to save one or more entities that have a non-nullable association with an unsaved transient entity. The unsaved transient entity must be saved in an operation prior to saving these dependent entities.
Unsaved transient entity: ([jpa.project.model.DemTypeDemande#0])
Dependent entities: ([[jpa.project.model.DemDemande#8950]])
Non-nullable association(s): ([jpa.project.model.DemDemande.demTypeDemande])
Controller :
#RequestMapping(value = "/demandes/manage",method = RequestMethod.GET)
public ModelAndView manageUsers(HttpServletRequest request) throws IOException {
ModelAndView model = new ModelAndView();
//----1.ADD USER
model.addObject("demUser", new DemUser());
//----2.ADD TYPES
List<DemTypeDemande> listTypes = service.getTypeDemandes();
model.addObject("listTypes", listTypes);
//----3.ADD DEMANDE
DemDemande demande = new DemDemande();
model.addObject("DemDemande", demande);
model.setViewName("managedemandes");
return model; }
#RequestMapping(value = "/demandes/actionadddemande", method = RequestMethod.POST)
public String actionadduser(HttpServletRequest request ,#ModelAttribute("demTypeDemande") DemTypeDemande typeDemande,#ModelAttribute ("DemDemande") DemDemande demande , BindingResult result) {
demande.setDemUser(service.getUserByUsername(service.getConnectedUsername(request)));
demande.setDemTypeDemande(typeDemande);
service.addDemande(demande);
return "redirect:/demandes/manage";
}
JSP :
<form:form action="actionadddemande" method="POST" commandName="DemDemande">
<table>
<form:hidden path="idDemande" />
<form:hidden path="demUser" />
<tr>
<td>Types :</td>
<td>
<form:select path="demTypeDemande">
<form:options items="${listTypes}" itemValue="idTypeDemande" itemLabel="libTypeDemande"></form:options>
</form:select></td>
</tr>
<tr>
<td colspan="2" align="center"><input type="submit" value="Save"></td>
</tr>
</table>
</form:form>
Type entity relation :
//bi-directional many-to-one association to DemDemande
#OneToMany(mappedBy="demTypeDemande")
private List<DemDemande> demDemandes;
Demande entity relation :
//bi-directional many-to-one association to DemTypeDemande
#ManyToOne(optional = false)
#JoinColumn(name="ID_TYPE_DEMANDE")
private DemTypeDemande demTypeDemande;
Related
I would like to save the inputs to the Set interface. I have class Client.java:
#Table(name = "client")
public class Client {
#OneToOne(cascade = CascadeType.ALL)
private ShippingAddress shippingAddress;
#OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
private Set<Address> shippingAddresses = new HashSet<>();
}
Class ShippingAddress.java:
#Table(name = "address")
public class ShippingAddress {
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Id
Long id;
String street;
String zip;
}
And it's my create form:
<form th:action="#{/add}" method="post" th:object="${client}">
<tr>
<td><input class="form-control" type="text" th:field="*{shippingAddress.street}"/></td>
<td><input class="form-control" type="text" th:field="*{shippingAddress.zip}"/></td>
</tr>
It works fine, but I can only save one street and one zip. I tried to improve it in this way to be able to save more data:
<form th:action="#{/add}" method="post" th:object="${client}">
<tr>
<td><input class="form-control" type="text" th:field="*{shippingAddress[0].street}"/></td>
<td><input class="form-control" type="text" th:field="*{shippingAddress[0].zip}"/></td>
</tr>
<tr>
<td><input class="form-control" type="text" th:field="*{shippingAddress[1].street}"/></td>
<td><input class="form-control" type="text" th:field="*{shippingAddress[1].zip}"/></td>
</tr>
But I get information:
Invalid property 'shippingAddress[0]' of bean class [model.Client]: Property referenced in indexed property path 'shippingAddress[0]' is neither an array nor a List nor a Set nor a Map; returned value was [ShippingAddress(id=null, street=null, zip=null, state=null, city=null, country=null)]
To add values to Set I should use the add method? But how to implement it with Thymeleaf?
Method in Controller (save data):
#Transactional
#RequestMapping(value = "add", method = RequestMethod.POST)
public String saveClient(#ModelAttribute Client client) {
clientRepository.save(client);
return "redirect:/";
}
Method in Controller (open create form)
#RequestMapping("/create")
public String newClient(Model model) {
model.addAttribute("client", new Client());
return "create";
}
I want to create a bank account register related to a specific Person in a OneToMany relationship.
I have the clas Pessoa (Person):
#Entity
public class Pessoa {
#Id #GeneratedValue(strategy=GenerationType.IDENTITY)
private int idPessoa;
private String nome;
#OneToMany(mappedBy = "pessoa", targetEntity = ContaCorretora.class, fetch = FetchType.EAGER, cascade = CascadeType.ALL)
private List<ContaCorretora> contaCorretora;
...and the class ContaCorretora (Bank account):
#Entity
public class ContaCorretora {
#Id #GeneratedValue(strategy=GenerationType.IDENTITY)
private int idConta;
private TipoConta tipoConta;
private TipoRisco tipoRisco;
private String login;
private String senha;
private BigDecimal valorAtual;
#ManyToOne
#JoinColumn(name="idPessoa")
private Pessoa pessoa;
I'm using this method in Controller for start the process of registration:
#RequestMapping(value = "pessoacorretora/{id}")
public ModelAndView pessoaCorretora(#PathVariable("id") int id, ContaCorretora contaCorretora ) {
Map<String, Object> model = new HashMap<String, Object>();
Pessoa pessoa = pessoaDao.find(id);
model.put("pessoa", pessoa);
model.put("tipoConta", TipoConta.values());
model.put("tipoRisco", TipoRisco.values());
return new ModelAndView("corretora/contacorretora", "model", model);
}
Sumarizining, I have a specific page for recording bank accounts. So, I created this form:
<form:form action="${s:mvcUrl('CC#gravar').build() }" method="post" commandName="contaCorretora" enctype="multipart/form-data" >
<div class="form-group" >
<label>Conta</label>
<select name="tipoConta">
<c:forEach items="${model.tipoConta}" var="tipoConta">
<option value=${tipoConta}>${tipoConta}</option>
</c:forEach>
</select>
</div>
<div class="form-group" >
<label>Risco</label>
<select name="tipoRisco">
<c:forEach items="${model.tipoRisco}" var="tipoRisco">
<option value=${tipoRisco}>${tipoRisco}</option>
</c:forEach>
</select>
</div>
<div class="form-group">
<label>Login</label>
<form:input path="login" cssClass="form-control" />
</div>
<div class="form-group">
<label>Senha</label>
<form:input path="senha" cssClass="form-control" />
</div>
<div class="form-group">
<label>Valor Atual</label>
<form:input path="valorAtual" cssClass="form-control" />
</div>
<form:hidden path="pessoa" cssClass="form-control" value="${pessoa}"/>
<button type="submit" class="btn btn-primary">Cadastrar</button>
</form:form>
When I use the form in this way, I receive the error "description The request sent by the client was syntactically incorrect." I figured out that the problem is in this line, because when I delete, the form post ok:
<form:hidden path="pessoa" cssClass="form-control" value="${pessoa}"/>
Nevertheless, if I delete this line, the program doesn't save the idPessoa as a foreign key, this field is null. I would like to know how to pass an entire object in my JSP form. The post method is:
#RequestMapping(method=RequestMethod.POST)
public ModelAndView gravar(ContaCorretora contaCorretora) {
contaCorretoraDao.gravar(contaCorretora);
return new ModelAndView("pessoa/listageral");
}
all the DAO's methods are okay.
You only need to send the primary key of pessoa to the form.
Change the form attribute
<form:hidden path="pessoa.idPessoa" cssClass="form-control" value="${model.pessoa.idPessoa}"/>
Before persisting the ContaCorretora, make sure you get the Pessoa object from db.
#RequestMapping(method=RequestMethod.POST)
public ModelAndView gravar(ContaCorretora contaCorretora) {
contaCorretora.setPessoa(pessoaDao.find(contaCorretora.getPessoa().getIdPessoa()));
//I escaped null check and not found exceptions, you should apply some logic to take care of that
contaCorretoraDao.gravar(contaCorretora);
return new ModelAndView("pessoa/listageral");
}
Using Entities as form model is not a good approach. Persistance layer should not be on the MVC layer.
In order to pass Java object from your Controller
#RequestMapping(method=RequestMethod.POST)
public ModelAndView gravar(ContaCorretora contaCorretora) {
ModelAndView mav = new ModelAndView("pessoa/listageral");
// retrieve object from DAO
Object myObj = Dao.find(id);
// Put object into model map
mav.addObject("myObj", myObj);
// return model and view
return mav;
}
In JSP you can refer to object using ExpressionLanguage syntax
${myObj}
Right now I have 3 tables in my database - Booking, Restaurant and RestaurantTable. I have a one to many mapping between Restaurant and RestaurantTable (a restaurant can have many tables, but a table can have only one restaurant). I have a file called "newTable.jsp" that inserts new tables to the restaurant. But when I try to do that it gives me the following error:
Request processing failed; nested exception is org.springframework.orm.hibernate4.HibernateOptimisticLockingFailureException: Batch update returned unexpected row count from update [0]; actual row count: 0; expected: 1; nested exception is org.hibernate.StaleStateException: Batch update returned unexpected row count from update [0]; actual row count: 0; expected: 1
I think it's trying to access a RestaurantTable that does not exist yet? But I don't know how to fix that.
Here is my "Restaurant.java" class:
#Entity
#Table(name="restaurant")
public class Restaurant {
#Id
#Column(name="id")
#GeneratedValue(strategy= GenerationType.IDENTITY)
private Long id;
#Column(name="restaurant_name")
private String restaurantName;
#Column(name="address")
private String address;
#OneToMany(mappedBy="restaurant", cascade = CascadeType.ALL, fetch = FetchType.EAGER)
private Set<RestaurantTable> table;
// Getters and setters
My "RestaurantTable.java":
#Entity
#Table(name="restaurant_table")
public class RestaurantTable {
#Id
#Column(name="id")
#GeneratedValue(strategy= GenerationType.IDENTITY)
private Long id;
#Column(name="table_size")
private int tableSize;
#Column(name="table_number")
private int tableNumber;
#ManyToOne
#JoinColumn(name="restaurant_id")
private Restaurant restaurant;
// Getters and setters
My "newTable.jsp"
<body>
<jsp:include page="../fragments/menu.jsp"/>
<div id="body">
<section class="content-wrapper main-content clear-fix">
<h2>Add New Table</h2>
<form:form method="POST" commandName="table" modelAttribute="table">
<table>
<tr>
<td>Table size:</td>
<td><form:input path="tableSize" /></td>
</tr>
<tr>
<td>Table number:</td>
<td><form:input path="tableNumber" /></td>
</tr>
<tr>
<td colspan="3"><input type="submit" />
</td>
</tr>
</table>
</form:form>
</section>
</div>
<jsp:include page="../fragments/footer.jsp"/>
</body>
My RestaurantTableController:
#Controller
public class RestaurantTableController {
#Autowired
private RestaurantService restaurantService;
#Autowired
private RestaurantTableService restaurantTableService;
#RequestMapping(value="restaurant/table/{id}", method = RequestMethod.GET)
public String addRestaurantTable(Model model) {
model.addAttribute("table", new RestaurantTable());
return "newTable";
}
#RequestMapping(value = "restaurant/table/{id}", method = RequestMethod.POST)
public String addRestaurantTable(#PathVariable Long id, #ModelAttribute ("table") RestaurantTable table) {
// Get a Restaurant object and add the table to it.
Restaurant restaurant = restaurantService.getRestaurant(id);
Set<RestaurantTable> tableSet = restaurant.getTable();
tableSet.add(table);
restaurant.setTable(tableSet);
restaurantService.updateRestaurant(restaurant);
return "editRestaurant";
}
}
The {id} in RestaurantTableController is a Restaurant id, it is passed along from "editRestaurant.jsp". Any help is appreciated.
EDIT: My updateRestaurant method:
#Override
public void updateRestaurant(Restaurant restaurant) {
Session session = this.sessionFactory.getCurrentSession();
session.update(restaurant);
logger.info("Restaurant record updated successfully, Restaurant Details=" + restaurant);
}
RestaurantTable entity doesn't have ID at that time, so hibernate throw exception. Try to use merge method instead of update
update
Update the persistent instance with the identifier of the given detached instance. If there is a persistent instance with the same identifier, an exception is thrown.
I am developing Employee Management application using Spring-Hibernate. I have two entities Employee and Department. And Employee entity has a field Department which is mapped to Department entity as #ManyToOne.
#ManyToOne(cascade = {CascadeType.PERSIST})
#JoinColumn(name = "dept")
private Department dept;
And accordingly #OneToMany mapping in Department entity
#OneToMany(mappedBy = "dept")
private List<Employee> employees = new ArrayList<>();
My JSP Spring form is mapped to Employee entity. And it has a form:select element to select department with values as department ids.
<form:form modelAttribute="createEmployee"
action="${pageContext.request.contextPath}/createdemployee"
method="post">
..............
..............
<form:input path="employee.firstName" type="text" width="20px;" />
<form:select>
<form:option value="1001">IT</form:option>
<form:option value="1002">Finance</form:option>
<form:option value="1003">Marketing</form:option>
<form:option value="1004">Sales</form:option>
<form:option value="1005">H.R</form:option>
</form:select>
How can I set Deparment object in Employee entity as per selection made on the form?
Controller
#RequestMapping("/createdemployee")
public String goCreatedEmployee(Model model, Employee employee){
employeeDataServices.addEmployee(employee);
return "created_employee";
}
You can use it like :
<form:select path="employee.department.code">
<form:option value="1001">IT</form:option>
<form:option value="1002">Finance</form:option>
<form:option value="1003">Marketing</form:option>
<form:option value="1004">Sales</form:option>
<form:option value="1005">H.R</form:option>
</form:select>
And from the Controller, get the employee model and get department's name?
Also add the request method in your code - POST/PUT.
#RequestMapping(value = /createdemployee, method = RequestMethod.POST)
public String goCreatedEmployee(Model model, Employee employee){
employeeDataServices.addEmployee(employee);
return "created_employee";
}
Let me know if it works?
Lets say i have 2 entities, Dish and Ingrediƫnt.
As we all know a Dish consists out of multiple Ingredients, so let's say:
Dish.java:
#Entity
public class Dish {
#Id
#GeneratedValue
protected long id;
private String name;
#OneToMany(mappedBy = "dish", cascade = CascadeType.PERSIST)
private Collection<Ingredient> ingredients;
//getters & setters
}
Ingrediƫnt.java :
#Entity
public class Ingredient {
#Id
#GeneratedValue
protected long id;
private String name;
//getters &setters
}
If we then have a DishController.java :
#Controller
public class DishController {
Service service;
public DishController() throws ServiceException {
service = new ShoppingFacade("JPA");
}
#RequestMapping("/showDishOverview")
protected ModelAndView getDishes() throws ServiceException {
Collection<Dish> dishes = service.getAllDishes();
return new ModelAndView("dish/dishOverview", "dishes", dishes);
}
#RequestMapping(value = "/showDishForm", method = RequestMethod.GET)
protected ModelAndView showDishForm(#RequestParam(value = "id") long dishId)throws ServiceException{
Dish dish = shoppingFacade.getDishById(dishId);
return new ModelAndView("dish/dishForm", "dish", dish);
}
#RequestMapping(value = "/editDish", method = RequestMethod.POST)
protected String updateDish(#ModelAttribute("dish") Dish newDish) throws ServiceException{
service.updateDish(newDish);
return "forward:/showDishOverview.htm";
}
}
Now lets say that we select one dish by its id:
${dish.getName()}
Now the showDishForm method in our controller will be called.
which will send us to dishForm.jsp:
<form method="post" action="editDish.htm">
<table>
<tr>
<td><label>Name </label></td>
<td><input type="text" name="name" placeholder="${dish.getName()}" value="${dish.getName()}"/></td>
</tr>
<tr>
<td><label>People</label></td>
<td><input type="text" name="people" placeholder="${dish.getPeople()}" value="${dish.getPeople()}"/></td>
</tr>
<tr>
<td colspan="2">
<input type="hidden" name="ingredients" value="${dish.getIngredient()}" />
<button type="submit" name="id" value="${dish.getId()}">Save</button>
</td>
</tr>
</table>
</form>
How will Spring MVC pass the info from my view to the controller?
Cause I get it working as long as I don't pass any Collections.(comment out <input type="hidden" name="ingredients" value="${dish.getIngredient()}" />
)
If i try to pass a Collection i get the message :
HTTP STATUS 400 - The request sent by the client was syntactically
incorrect
Spring uses Converters, for all standard classes these are already implemented.
For custon classes like this List, you have to write your own converter.