1

I have 2 tables - Food and Lvl. On every Lvl can be stored a lot of Food.

Lvl class

@SequenceGenerator(name = "lvl_seq", sequenceName = "lvl_seq")
@Entity
@Table(name = "Lvl")
public class Lvl {
    @Id
    @GeneratedValue(generator = "lvl_seq")
    @Column(name = "lvl_id")
    private int lvl_id;
    @Column(name = "dimension")
    private String dimension;
    @Column(name = "title")
    private String title;
    @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "lvl_id")
    private List<Food> foodList;
    //getset
    public int getLvl_id() { return lvl_id; }
    public void setLvl_id(int lvl_id) { this.lvl_id = lvl_id; }
    public String getDimension() { return dimension; }
    public void setDimension(String dimension) { this.dimension = dimension; }
    public String getTitle() { return title; }
    public void setTitle(String title) { this.title = title; }
    public List<Food> getFoodList() { return foodList; }
    public void setFoodList(List<Food> foodList) { this.foodList = foodList; }

}

Food class

@SequenceGenerator(name = "food_seq", sequenceName = "food_seq")
@Entity
@Table(name = "Food")
public class Food {
    @Id
    @GeneratedValue(generator = "food_seq")
    @Column(name = "food_id")
    private int food_id;
    @Column(name = "location")
    private String location;
    @ManyToOne
    @JoinColumn(name = "lvl_id")
    private Lvl lvl_id;
    //getset
    public int getFood_id() { return food_id; }
    public void setFood_id(int food_id) { this.food_id = food_id; }
    public String getLocation() { return location; }
    public void setLocation(String location) { this.location = location; }
    public Lvl getLvl_id() { return lvl_id; }
    public void setLvl_id(Lvl lvl_id) { this.lvl_id = lvl_id; }
}

FoodController

@Controller
public class FoodController 
{
    @Autowired
    private LvlService lvlService;
    @Autowired
    private FoodService foodService;
    @RequestMapping("/food")
    public String listFood(Map<String, Object> map) 
    {
        List<Integer> lvl = new ArrayList<>();
        map.put("food", new Food());
        map.put("foodList", foodService.getAll());
        for(Lvl o : lvlService.getAll())
        { 
            lvl.add(o.getLvl_id());
        }
        map.put("lvlList", lvl);

        return "food";
    }
    @RequestMapping(value = "/addFood", method = RequestMethod.POST)
    public String addFood(@ModelAttribute("food") Food food, BindingResult result) 
    {
        foodService.addFood(food);
        return "redirect:/food";
    }
    @RequestMapping("/deleteFood/{foodId}")
    public String deleteFood(@PathVariable("foodId") int id) 
    {
        foodService.removeFood(id);
        return "redirect:/food";
    }  
}

And JSP view:

<%@ page language="java" contentType="text/html; charset=utf8"
    pageEncoding="utf8"%>
<%@taglib uri="http://www.springframework.org/tags" prefix="spring"%>
<%@taglib uri="http://www.springframework.org/tags/form" prefix="form"%>
<%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>


<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf8">
    <title><spring:message code="label.bookmark" /></title>
</head>
<body>

<a href="<c:url value="/index" />">
    <spring:message code="label.menu" />
</a>

<h3><spring:message code="label.foods" /></h3>

<form:form method="post" action="addFood" commandName="food">
    <table> 
        <tr>
            <td>
            <form:label path="location">
                <spring:message code="label.location" />
            </form:label>
            </td>
            <td>
            <form:input path="location" />
            </td>
        </tr>
        <tr>
            <td>
            <form:label path="lvl_id">
                <spring:message code="label.lvl_id" />
            </form:label>
            </td>
            <td>
            <form:select path="lvl_id" items="${lvlList}">
            </form:select>
            </td>
        </tr>
        <tr>
            <td colspan="2">
            <input type="submit" value="<spring:message code="label.addfood"/>" />
            </td>
        </tr>
    </table>
</form:form>
</body>
</html>

So the problem is - when Im trying to add Food using JSP - Foreign Key (lvl_id) is always null. Tried to change input type in JSP, cascade type in class, replace mappedby with @JoinColumn - no results. Can somebody help me? Thanks.

K. Anton
  • 11
  • 2

2 Answers2

0
@JoinColumn(name = "lvl_id", nullable = false)
private Lvl lvl_id;

and check in the debugger on exist and notnull in object Food.lvl_id .

Try this variant method in controller:

@RequestMapping(value = "/addFood", method = RequestMethod.POST)
public String addFood(@ModelAttribute Food food, Model model) {
    foodService.addFood(food);
    return "redirect:/food";
}

Also in java you need use camel style in naming variables.

lvl_id --> lvlId ;)

Anton Nikanorov
  • 341
  • 3
  • 4
  • Now it throws an error: Request processing failed; nested exception is org.springframework.validation.BindException: org.springframework.validation.BeanPropertyBindingResult: 1 errors description The server encountered an internal error that prevented it from fulfilling this request. – K. Anton Apr 22 '16 at 09:12
  • and more: org.springframework.web.util.NestedServletException: Request processing failed; nested exception is org.springframework.validation.BindException: org.springframework.validation.BeanPropertyBindingResult: 1 errors Field error in object 'food' on field 'lvl_id': rejected value [1]; codes [typeMismatch.food.lvl_id,typeMismatch.lvl_id,typeMismatch.net.day7.gamebase.domain.Lvl,typeMismatch]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [food.lvl_id,lvl_id]; arguments []; default message [lvl_id]]; default message – K. Anton Apr 22 '16 at 09:14
  • [Failed to convert property value of type 'java.lang.String' to required type 'net.day7.gamebase.domain.Lvl' for property 'lvl_id'; nested exception is java.lang.IllegalStateException: Cannot convert value of type [java.lang.String] to required type [net.day7.gamebase.domain.Lvl] for property 'lvl_id': no matching editors or conversion strategy found] – K. Anton Apr 22 '16 at 09:14
0

Lvl Class:

@Entity
@Table(name = "Lvl")
public class Lvl implements Serializable {

private static final long serialVersionUID = 1L;

    @Id
    @GeneratedValue(generator = "lvl_seq", strategy = GenerationType.SEQUENCE)
    @SequenceGenerator(name = "lvl_seq", sequenceName = "lvl_seq", allocationSize = 1)
    @Column(name = "lvl_id")
    private int lvl_id;

    @Column(name = "dimension")
    private String dimension;

    @Column(name = "title")
    private String title;

    @OneToMany(cascade = CascadeType.ALL)
    @JoinColumns({ @JoinColumn(name = "lvl_id", referencedColumnName = "lvl_id", nullable = false) })
    @org.hibernate.annotations.Cascade({ org.hibernate.annotations.CascadeType.ALL })
    private List<Food> foodList;

    //getters and setters
}

Food Class:

@Entity
@Table(name = "Food")
public class Food implements Serializable {

    private static final long serialVersionUID = 1L;

    @Id
    @GeneratedValue(generator = "food_seq", strategy = GenerationType.SEQUENCE)
    @SequenceGenerator(name = "food_seq", sequenceName = "food_seq", allocationSize = 1)
    @Column(name = "food_id")
    private int food_id;

    @Column(name = "location")
    private String location;

    @ManyToOne(optional = false)
    @JoinColumns({ @JoinColumn(name = "lvl_id", referencedColumnName = "lvl_id", insertable = false, updatable = false) })
    private Lvl lvl_id;

}

Try above classes. It should work.

Mohit
  • 126
  • 1
  • 9
  • Done, but now error comes: ERROR: org.springframework.web.context.ContextLoader - Context initialization failed org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'foodDAOImpl': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private org.hibernate.SessionFactory net.day7.gamebase.dao.FoodDAOImpl.sessionFactory; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'sessionFactory' defined in – K. Anton Apr 22 '16 at 10:22
  • ServletContext resource [/WEB-INF/spring/data.xml]: Invocation of init method failed; nested exception is org.hibernate.MappingException: Unable to find column with logical name: food_id in org.hibernate.mapping.Table(Lvl) and its related supertables and secondary tables – K. Anton Apr 22 '16 at 10:22
  • And: -Could not autowire field: -Error creating bean with name 'sessionFactory' defined in ServletContext resource -Unable to find column with logical name: food_id in org.hibernate.mapping.Table(Lvl) and its related supertables and secondary tables – K. Anton Apr 22 '16 at 10:23
  • And why we set for @JoinColumns insertable=false? – K. Anton Apr 22 '16 at 10:25
  • use this [link](http://stackoverflow.com/questions/3805584/please-explain-about-insertable-false-updatable-false) to understand why we use `insertable=false` – Mohit Apr 25 '16 at 05:23