I have a list in Java from a query of a stored procedure, what I want to do is pass the values of the list, to the inputs of the thymeleaf form, but I want to know how to pass that list in the controller and iterate it in the view, It is a Boostrap Modal, I would like help if I could do it with Ajax or with the th: fragment of thymeleaf.
Model function
public List getTypePlan(int id){
List type = new ArrayList<>();
try {
Connection conn = AppConnection.getConnection();
CallableStatement cstmt = conn.prepareCall("{call SP_LEER_PFI_TIPOS_PLANES(?)}");
cstmt.setInt(1, id);
ResultSet results = cstmt.executeQuery();
while (results.next()) {
int cod_plan = results.getInt("cod_plan");
String des_plan = results.getString("des_plan");
int can_dias_plazo = results.getInt("can_dias_plazo");
type.add(cod_plan);
type.add(des_plan);
type.add(can_dias_plazo);
}
conn.close();
} catch (SQLException ex) {
}
return type;
}
Output example: [1,General,3]
Controller
#RequestMapping(value="/typePlan/{id}", method = RequestMethod.GET)
public String typePlan(#PathVariable("id") int id, Model m){
Users_Access model = new Users_Access();
m.addAttribute("type", model.getTypePlan(id));
return "home :: type";
}
}
Boostrap Modal form
<div class="modal fade" data-keyboard="false" data-backdrop="static" id="TiposPlanes" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel" aria-hidden="true">
<div class="modal-dialog modal-dialog-centered" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">TIPOS DE PLANES</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
<div class="modal-bodyh">
<h6 class="modal-subtitle"><i class="fas fa-pencil-alt"></i> MODIFICAR TIPOS DE PLANES</h6>
<h6 class="modal-subtitle">Presione click en el boton Modificar para grabar los cambios</h6>
</div>
<div class="modal-form" th:fragment="type">
<form class="form" th:method="post">
<div class="form-group">
<label class="col-form-label">Codigo:</label>
<input type="text" class="form-control" id="codigo" name="codigo">
</div>
<div class="form-group">
<label class="col-form-label">Descripcion:</label>
<input type="text" class="form-control" id="descripcion" name="descripcion">
</div>
<div class="form-group">
<label class="col-form-label">Diaz plazo:</label>
<input type="text" class="form-control" id="dias" name="dias">
</div>
<div class="form-group">
<button type="button" class="btn btn-primary" value="save">Modificar</button>
<button type="button" class="btn btn-primary" data-dismiss="modal">Cancelar</button>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
Sure, here is an example of how you could achieve this. First of all your getTypePlan method could look something like this (I used CustomObject as a custom model object for this, so you'll have to adjust to the name that fits your purpose):
public List<CustomObject> getTypePlan(int id) throws Exception {
List<CustomObject> type = new ArrayList<>();
try {
Connection conn = AppConnection.getConnection();
CallableStatement cstmt = conn.prepareCall("{call SP_LEER_PFI_TIPOS_PLANES(?)}");
cstmt.setInt(1, id);
ResultSet results = cstmt.executeQuery();
while (results.next()) {
int cod_plan = results.getInt("cod_plan");
String des_plan = results.getString("des_plan");
int can_dias_plazo = results.getInt("can_dias_plazo");
CustomObject listObject = new CustomObject();
listObject.setCodPlan(cod_plan);
listObject.setDesPlan(des_plan);
listObject.setCanDiasPlazo(can_dias_plazo);
type.add(listObject);
}
conn.close();
} catch (SQLException ex) {
ex.printStackTrace();
}
return type;
}
The model class in my case looks like this (I tried to keep it as close as possible to your example):
public class CustomObject {
private int codPlan;
private String desPlan;
private int canDiasPlazo;
public int getCodPlan() {
return codPlan;
}
public void setCodPlan(int codPlan) {
this.codPlan = codPlan;
}
public String getDesPlan() {
return desPlan;
}
public void setDesPlan(String desPlan) {
this.desPlan = desPlan;
}
public int getCanDiasPlazo() {
return canDiasPlazo;
}
public void setCanDiasPlazo(int canDiasPlazo) {
this.canDiasPlazo = canDiasPlazo;
}
}
Your controller method would be adjusted to:
#RequestMapping(value="/typePlan/{id}", method = RequestMethod.GET)
public String typePlan(#PathVariable("id") int id, Model m){
Users_Access model = new Users_Access();
m.addAttribute("type", model.getTypePlan(id));
return "home";
}
}
And in your view could do the following to render the values of each object of type (which is returned by your getTypePlan method):
<div class="modal fade" data-keyboard="false" data-backdrop="static" id="TiposPlanes" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel" aria-hidden="true">
<div class="modal-dialog modal-dialog-centered" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">TIPOS DE PLANES</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
<div class="modal-body">
<h6 class="modal-subtitle"><i class="fas fa-pencil-alt"></i> MODIFICAR TIPOS DE PLANES</h6>
<h6 class="modal-subtitle">Presione click en el boton Modificar para grabar los cambios</h6>
</div>
<div class="modal-form">
<!-- the customObject in the th:each is the iteratee and type is the list passed into the Model in the controller method -->
<form class="form" th:method="post" th:each="customObject : ${type}">
<div class="form-group">
<label class="col-form-label">Codigo:</label>
<input type="text" class="form-control" th:id="${customObject.getCodPlan()}" th:name="${customObject.getCodPlan()}" th:value="${customObject.getCodPlan()}">
</div>
<div class="form-group">
<label class="col-form-label">Descripcion:</label>
<input type="text" class="form-control" th:id="${customObject.getDesPlan()}" th:name="${customObject.getDesPlan()}" th:value="${customObject.getDesPlan()}">
</div>
<div class="form-group">
<label class="col-form-label">Diaz plazo:</label>
<input type="text" class="form-control" th:id="${customObject.getCanDiasPlazo()}" th:name="${customObject.getCanDiasPlazo()}" th:value="${customObject.getCanDiasPlazo()}">
</div>
<div class="form-group">
<button type="button" class="btn btn-primary" value="save">Modificar</button>
<button type="button" class="btn btn-primary" data-dismiss="modal">Cancelar</button>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
Please bear in mind that this example works as expected with 1 object being added to the type list in the getTypePlan method, just like in your example. If you would have more results extracted from the database and added to the type list, then you would get multiple HTML forms rendered, which might not be the expected behavior.
So if you are going to expect multiple results (which you probably should expect), then you should think about organizing this a little bit different, but I'll leave that up to you as it's up to you how you would like to have that rendered. This example should help you to get on the right track.
I think you should your list into an Object
Try to follow this : Thymeleaf List
Related
I'm making a simple blog using springframework. I'm trying to make Categories for my posts/articles. When I create articles, I have the option to choose a Category and it works fine. However, when I try to edit an Article, the drop-down menu for choosing a Category is not working. It's just and empty field with a 'down arrow' sidebad and nothing happens when I click on it
//ARTICLE EDIT--------------------------------------------------
#GetMapping("/article/edit/{id}")
#PreAuthorize("isAuthenticated()")
public String edit(#PathVariable Integer id, Model model)
{
if(!this.articleRepository.exists(id))
{
return "redirect:/";
}
Article article = this.articleRepository.findOne(id);
if(!isUserAuthorOrAdmin(article))
{
return "redirect:/article/"+id;
}
List<Category> categories = this.categoryRepository.findAll();
String tagString = article.getTags().stream().map(Tag::getName).collect(Collectors.joining(", "));
model.addAttribute("view", "article/edit");
model.addAttribute("article", article);
model.addAttribute("category", categories);
model.addAttribute("tags", tagString);
return "base-layout";
}
#PostMapping("/article/edit/{id}")
#PreAuthorize("isAuthenticated()")
public String editProcess(#PathVariable Integer id, ArticleBindingModel articleBindingModel)
{
if(!this.articleRepository.exists(id))
{
return "redirect:/";
}
Article article = this.articleRepository.findOne(id);
Category category = this.categoryRepository.findOne(articleBindingModel.getCategoryId());
HashSet<Tag> tags = this.findTagsFromString(articleBindingModel.getTagString());
if(!isUserAuthorOrAdmin(article))
{
return "redirect:/article/"+id;
}
article.setContent(articleBindingModel.getContent());
article.setTitle(articleBindingModel.getTitle());
article.setCategory(category);
article.setTags(tags);
this.articleRepository.saveAndFlush(article);
return "redirect:/article/" + article.getId();
}
The html file is:
<main>
<div class="container body-content span=8 offset=2">
<div class="well">
<form class="form-horizontal" th:action="#{/article/edit/{id}(id=${article.id})}" method="POST">
<fieldset>
<legend>Edit Post</legend>
<div class="form-group">
<label class="col-sm-4 control-label" for="article_title">Post Title</label>
<div class="col-sm-4 ">
<input type="text" class="form-control" id="article_title" placeholder="Post Title" name="title" th:value="${article.title}"/>
</div>
</div>
<div class="form-group">
<label class="col-sm-4 control-label" for="article_content">Content</label>
<div class="col-sm-6">
<textarea class="form-control" rows="6" id="article_content" name="content" th:field="${article.content}"></textarea>
</div>
</div>
<div class="form-group">
<label class="col-sm-4 control-label" for="article_tags">Tags</label>
<div class="col-sm-6">
<input type="text" class="form-control" id="article_tags" placeholder="Tags" name="tagString" th:value="${tags}"/>
</div>
</div>
<div class="form-group">
<label class="col-sm-4 control-label" for="article_category">Category</label>
<div class="col-sm-6">
<select class="form-control" id="article_category" name="categoryId">
<option th:each="category : ${categories}" th:value="${category.id}" th:text="${category.name}" th:selected="${category.id == article.category.id}">
</option>
</select>
</div>
</div>
<div class="form-group">
<div class="col-sm-4 col-sm-offset-4">
<a class="btn btn-default" th:href="#{/article/{id}(id = ${article.id})}">Cancel</a>
<input type="submit" class="btn btn-success" value="Edit"/>
</div>
</div>
</fieldset>
</form>
</div>
</div>
You should use model attributes' names inside ${}. There is a mismatch between model.addAttribute("category", categories); and th:each="category : ${categories}".
Change model attribute name to "categories" and it should be fine
model.addAttribute("categories", categories);
#PostMapping(value=("/addMessage"))
public String addMessagePostPicture(#RequestParam("picture") MultipartFile picture, Map<String, Object> model, HttpServletRequest request, #ModelAttribute MessageForm message) {
String[] contacts = request.getParameterValues("contacts");
if(message.getContacts() == null){
System.out.println("yes");
message.setContact(contacts);
}
public class MessageForm {
private String[] contacts;
public String[] getContacts() {
return contacts;
}
public void setContact(String[] contacts) {
this.contacts = contacts;
}
}
Why is message.getContacts value null? Request parameter with name contacts excisting.
addMessage.html code part where is getting that contacts parameter value
<form id="addMessageForm" class="form-horizontal" method="post" action="addMessage" enctype="multipart/form-data">
<div class="form-group ">
<label class="control-label col-sm-3 requiredField" for="contacts"> Kontaktid
<span class="asteriskField">* </span>
</label>
<button type="button" class="btn btn-primary" data-toggle="modal" data-target="#addContactModal">Lisa kontakt</button>
<div class="col-sm-9">
<select id="contacts" name="contacts" multiple="multiple">
options added here by javascript
</select>
</div>
</div>
<div class="form-group">
<div class="col-sm-9 col-sm-offset-3">
<button class="btn btn-primary " name="submit" type="submit" th:text="#{save}"> Salvesta</button>
</div>
</div>
</form>
example with javascript generated code
<select id="contacts" name="contacts" multiple="multiple">
<option value="2">test#mail.ee</option>
<option value="3">mail#mail.ee</option>
<option value="4">isik#mail.ee</option>
</select>
I want to insert the photoPath URL that the servlet gets from the form into my table however, it is not working.
protected void processRequest(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html;charset=UTF-8");
String name = request.getParameter("name");
String number = request.getParameter("contactNumber");
String position = request.getParameter("position");
String email = request.getParameter("email");
String photoPath = request.getParameter("myImage");
MySqlHandler.registerEmployee(name, number, position, email, photoPath);
}
If I do
try (PrintWriter out = response.getWriter()) {
out.println(photoPath);
}
the url is displayed as 150x150.png (which is the name of my img) so I know the string is stored there. But when I pass it into my registerEmployee function, it stops all data from getting inserted into my table. If I set photoPath to some static string, everything gets inserted properly. What could be wrong? I think maybe the string I get from
request.getParameter("myImage");
contains some weird characters that can't be inserted into mysql table?
public static void registerEmployee(String name, String number, String position, String email, String photoPath) {
initConnection();
try {
String query = " insert into employee_registry (name, number, position, email, photo_path)"
+ " values (?, ?, ?, ?, ?)";
PreparedStatement preparedStatement = connection.prepareStatement(query);
preparedStatement.setString(1, name);
preparedStatement.setString(2, number);
preparedStatement.setString(3, position);
preparedStatement.setString(4, email);
preparedStatement.setString(5, photoPath);
preparedStatement.execute();
} catch (Exception e) {
e.printStackTrace();
System.err.println("Exception" + e.getMessage());
}
closeConnection();
}
Form
<form action="" id="registerForm" method="post">
<div class="col-md-12">
<h3> Register Now</h3>
</div>
<div class="row">
<div class="col-md-4">
<label>Full Name: </label>
</div>
<div class="col-md-4">
<input name="name" type="text"/>
</div>
<div class="col-md-4">
<div class="error-wrapper">
<div class="hideError"> Field is blank </div>
</div>
</div>
</div>
<div class="row">
<div class="col-md-4">
<label>Position: </label>
</div>
<div class="col-md-4">
<input name="position" type="text"/>
</div>
<div class="col-md-4">
<div class="error-wrapper">
<div class="hideError"> Field is blank </div>
</div>
</div>
</div>
<div class="row">
<div class="col-md-4">
<label>Email: </label>
</div>
<div class="col-md-4">
<input name="email" type="text"/>
</div>
<div class="col-md-4">
<div class="error-wrapper">
<div class="hideError"> Field is blank </div>
</div>
</div>
</div>
<div class="row">
<div class="col-md-4">
<label>Contact Number: </label>
</div>
<div class="col-md-4">
<input name="contactNumber" type="text"/>
</div>
<div class="col-md-4">
<div class="error-wrapper">
<div class="hideError"> Field is blank </div>
</div>
</div>
</div>
<div class="row">
<div class="col-md-4">
<label>Photos: </label>
</div>
<div class="col-md-4">
<div class="photo-wrapper">
<input type="file" name="myImage" accept="image/*" />
</div>
</div>
<div class="col-md-4">
<div class="error-wrapper">
<div class="hideError"> Field is blank </div>
</div>
</div>
</div>
<div class="row">
<div class="col-md-12">
<input id="submitBtn" type="submit" value="Submit"/>
</div>
</div>
</form>
I need to bind an object with a list of objects as an attribute. It is a static list and it is created and partially filled in the Controller. It is displayed correctly in the view, however the value in the input field is not set when the form is sent to the controller. I did some research and found several similar questions, however none of the proposed solutions worked for me.
edit.jsp
<c:forEach items="${priceConfigurationForm.priceList}" var="price" varStatus="priceStatus">
<tr>
<td>
<spring:bind path="priceConfigurationForm.priceList[${priceStatus.index}].country">
${price.country}
<input type="hidden" name="<c:out value="${status.expression}"/>"
id="<c:out value="${status.expression}"/>"
value="<c:out value="${status.value}"/>"/>
</spring:bind>
</td>
<td>
<spring:bind path="priceConfigurationForm.priceList[${priceStatus.index}].amount">
<input type="text" name="price" value="${price.amount}"/>
<input type="hidden"
name="<c:out value="${status.expression}"/>"
id="<c:out value="${status.expression}"/>"
value="<c:out value="${status.value}"/>"/>
</spring:bind>
</td>
<td>
<spring:bind path="priceConfigurationForm.priceList[${priceStatus.index}].currency">
${price.currency}
<input type="hidden" name="<c:out value="${status.expression}"/>"
id="<c:out value="${status.expression}"/>"
value="<c:out value="${status.value}"/>"/>
</spring:bind>
</td>
</tr>
</c:forEach>
Abstract from Controller populating the list:
#RequestMapping(value = "/price/create", method = RequestMethod.GET)
public String toCreatePriceConfiguratioView(Model model) {
log.info("::createPriceConfiguration: {}");
final PriceConfigurationForm priceConfigurationForm = new PriceConfigurationForm();
final List<PriceConfigurationForm.Price> prices = new ArrayList<>();
for (Country country : Country.values()) {
PriceConfigurationForm.Price price = new PriceConfigurationForm.Price();
price.setAmount(100);
price.setCountry(country.getCountryCode());
price.setCurrency(country.getCurrency());
prices.add(price);
}
priceConfigurationForm.setPriceList(prices);
model.addAttribute("priceConfigurationForm", priceConfigurationForm);
return "/secured/sources/onboarding/price/edit";
}
Abstract from Controller for storing the list:
#RequestMapping(value = "/price/create", method = RequestMethod.POST)
public String createPriceConfiguration(Model model, #ModelAttribute("priceConfigurationForm") #Valid PriceConfigurationForm priceConfigurationForm, BindingResult bindingResult, RedirectAttributes attributes) {
log.info("::createPriceConfiguration {}", priceConfigurationForm);
// TODO: Validate, before create
/* transform form to domain object */
PriceConfiguration configuration = PriceConfigurationForm.toPriceConfiguration(priceConfigurationForm);
onboardingApi.createPriceConfiguration(configuration);
attributes.addFlashAttribute("message", success("price configuration saved", priceConfigurationForm.getName()));
return "/secured/sources/onboarding/price/index";
}
Object:
#Data
public class PriceConfigurationForm {
private String name;
private String description;
private List<Price> priceList;
private Map<String, Long> countryToPriceMap;
public static PriceConfiguration toPriceConfiguration(PriceConfigurationForm form) {
final PriceConfiguration pc = new PriceConfiguration();
pc.setName(form.getName());
pc.setDescription(form.getDescription());
final Map<String, Long> prices = form.getPriceList().stream().collect(toMap(Price::getCountry, Price::getAmount));
pc.setCountryToPriceMap(prices);
return pc;
}
#Data
public static class Price {
private String country;
private long amount;
private String currency;
}
}
This is example of how I sucessfully parsed nested objects in one project :
<c:forEach var="block" items="${newplaceform.blocks}" varStatus="counter">
<fieldset data-block-order="${counter.index}" data-block-index="${counter.index}">
<c:if test='${block.type=="quizSingleAnswer"}'>
<legend><s:message code='blocks.type.quizSingleAnswer'/> <a class="glyphicon glyphicon-move move-block pull-right" href="#"></a><a data-remove="block" class="glyphicon glyphicon-remove pull-right" href="#"></a><a data-reordering="up" class="glyphicon glyphicon-chevron-up pull-right" href="#"></a><a data-reordering="down" class="glyphicon glyphicon-chevron-down pull-right" href="#"></a></legend>
<div class="form-group production-hide">
<label class="col-sm-3 control-label">id:</label>
<div class="col-sm-9"><input type="text" name="blocks[${counter.index}].id" value="${block.id}" data-row="blockId" data-disabled class="form-control"/></div>
</div>
<div class="form-group production-hide">
<label class="col-sm-3 control-label">type:</label>
<div class="col-sm-9"><input type="text" name="blocks[${counter.index}].type" value="${block.type}" data-disabled class="form-control"/></div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label"><s:message code='blocks.description'/>:</label>
<div class="col-sm-9"><textarea class="form-control" name="blocks[${counter.index}].description" data-description rows="3">${block.description}</textarea></div>
</div>
<div class="row">
<div class="col-sm-6">
<div class="col-sm-6 control-label">
<label class="inner-header"><s:message code='blocks.answers'/>:</label>
</div>
<div class="col-sm-6">
<div class="btn-group m-t-9">
<a class="btn btn-primary btn-xs" href="#" data-add-answer data-add-answer-block-index="${counter.index}"><i class="glyphicon glyphicon-plus"></i> <s:message code="blocks.add-answer" /></a>
</div>
</div>
</div>
</div>
<div class="row quiz-answers" data-count-answer="${block.answers.size()}">
<c:forEach var="answer" items="${block.answers}" varStatus="counterInner">
<div class="col-sm-6">
<fieldset>
<legend>
<div class="bootstrap-center">
<span><s:message code="blocks.answerNo"/> ${counterInner.index+1}</span>
<a data-remove="answer" class="glyphicon glyphicon-remove pull-right" href="#"></a>
</div>
</legend>
<div class="form-group production-hide">
<label class="col-sm-6 control-label">id:</label>
<div class="col-sm-6"><input type="text" name="blocks[${counter.index}].answers[${counterInner.index}].id" value="${answer.id}" data-row="answerId" data-disabled class="form-control"/></div>
</div>
<div class="form-group">
<label class="col-sm-6 control-label"><s:message code="blocks.answer"/>:</label>
<div class="col-sm-6"><input type="text" name="blocks[${counter.index}].answers[${counterInner.index}].text" value="${answer.text}" class="form-control"/></div>
</div>
<div class="form-group">
<div class="col-sm-6 col-sm-offset-6">
<div class="checkbox">
<label>
<input type="checkbox" name="blocks[${counter.index}].answers[${counterInner.index}].right" value="true" ${answer.checked()}/>
<s:message code="blocks.right"/>
</label>
</div>
</div>
</div>
</fieldset>
</div>
</c:forEach>
</div>
Here is my code.When I check checkbox and click the edit button the value is fetched correctly.But edited value is not updated in mysql database as well as table.I'm using jdbc template for this example."location" field is select option value.
controller get the checkbox value and fetch data from database.after that the updated value is not shown in the table.
HomeController.java
#RequestMapping("/edit")
public String update(Model model,#RequestParam Map<String,String> req){
updateValue = new Integer(req.get("checkId"));
List<Users> users = userdao.getUpdateRecord(updateValue);
model.addAttribute("result",users);
return "formedit";
}
#RequestMapping("/saveUpdate")
public String saveUpdate(Model model,#RequestParam Map<String,String> req){
String name,storage,location,address;
name = req.get("name");
storage=req.get("storage");
location=req.get("location");
address = req.get("address");
int row = userdao.updateRecord(updateValue,name,storage,location,address);
String message = row+ "updated";
model.addAttribute("message", message);
result(model);
return "home";
}
UsersDAO doesn't get the update value from formedit page.
UsersDAO.java
public List<Users> getUpdateRecord(int updateValue){
System.out.println("update value"+updateValue);
String sql="select id,name,storage,location,address from customer where id="+updateValue;
return jdbc.query(sql,new UsersMapper());
}
public int updateRecord(int id,String name,String storage,String location,String address){
return jdbc.update("update customer set name = ?,storage = ?,location = ?,address=? where id = ?",id,name,storage,location,address);
formedit.jsp
<form role="form" action="saveUpdate" method="post" class="form-horizontal">
<c:forEach var="row" items="${result}">
<div class="row">
<div class="col-md-6">
<div class="form-group">
<label class="control-label col-xs-4 text">Customer Name</label>
<div class="col-xs-8">
<input type="text" class="form-control" name="name" value=${row.name }>
</div>
</div>
<div class="form-group">
<label class="control-label col-xs-4 text">Storage Location*</label>
<div class="col-xs-8">
<input type="text" class="form-control" name="storage" value=${row.storage }>
</div>
</div>
</div>
<div class="col-md-6">
<div class="form-group">
<label class="control-label col-xs-4 text">Location</label>
<div class="col-xs-8">
<input type="text" class="form-control" name="location" value=${row.location }>
</div>
</div>
<div class="form-group">
<label class="control-label col-xs-4 text">Customer Address</label>
<div class="col-xs-8">
<textarea class="form-control" name="address">${row.address }</textarea>
</div>
</div>
</div>
<input type="submit" class="btn btn-success btn-md col-md-offset-6" value="Update">
</div>
</c:forEach>
</form>
}
Because this is wrong:
return jdbc.update("update customer set name = ?,storage = ?,location = ?,address=? where id = ?",id,name,storage,location,address);
The parameters order is incorrect, it doesnt find id with value address.