This webapp is made with spring boot connected to MariaDB .I would like to view the items in each category, I can see the category attributes and can see the item in the view as such [Item [id=1, title=test, description=11, status=Used, zipcode=1231, price=111.0, category=Category [id=3, type=Services]]]
heres my controller
#RequestMapping(value="/item-by-category/{id}",method= RequestMethod.GET)
public String itemByCategory(#PathVariable("id") Long categoryid, Model model){
//model.addAttribute("items",irepository.findByCategory(categoryid));
model.addAttribute("categorys",crepository.findOne(categoryid));
//model.addAttribute("item",irepository.findByCategory(categoryid));
return "/item-by-category";
}
Im using CRUD repositories so I tried to use the itemRepository method to filter the items by category but I get an error on the type of attribute passed even if its of type Long as stated in the class initiation.
Repositories:
public interface ItemRepository extends CrudRepository<Item, Long> {
List<Item> findByTitle(String title);
List<Item> findByCategory(Long categoryid);
}
public interface CategoryRepository extends CrudRepository<Category, Long> {
//find by cat type
List<Category> findByType(String type);
//List<Category>findByItem(String item);
//Item findByCategory(String type);
//show the items in the categories
//List<Item>items(String type);
//List<Category>findByItem(String item);
}
classes :
#Entity
#Table(name="category")
public class Category {
//#id creates an ID column for the table
#Id
//Generates automatically a unique PK for every new entity object
#GeneratedValue(strategy=GenerationType.AUTO)
#Column(name="categoryid")
private Long id;
#Column(name="type")
private String type;
// 1 Category can have * Items
#OneToMany(cascade = CascadeType.ALL, mappedBy = "category")
private List<Item> item;
//constructor
public Category() {}
public Category(String type) {
super();
this.type = type;
}
//getters n setters
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
//getters n setters for relationship
public List<Item> getItems() {
return item;
}
public void setItems(List<Item> item) {
this.item = item;
}
#Override
public String toString() {
return "Category [id=" + id + ", type=" + type + "]";
}
}
#Entity
#Table(name="item")
public class Item {
//generated ID column
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name="itemid")
private Long id;
#Column(name="title")
private String title;
#Column(name="description")
private String description;
#Column(name="status")
private String status;
#Column(name="zipcode",length=5)
private Integer zipcode;
#Column(name="price")
private Double price;
//create relationship or * to 1 between items to user
/*
#ManyToOne
#JsonIgnore
#JoinColumn(name = "userid")
private User user;
*/
//Many items can have 1 category * to 1
#ManyToOne
/*entity relationship will
cause endless loop (First item is serialized and it contains
category which is then serialized which contains students which
are then serialized
*/
#JsonIgnore
#JoinColumn(name = "categoryid")
private Category category;
//working ^^
//JPA constructor
public Item(){
}
public Item(Long id, String title, String description, String status, Integer zipcode, Double price,
Category category) {
super();
this.id = id;
this.title = title;
this.description = description;
this.status = status;
this.zipcode = zipcode;
this.price = price;
this.category = category;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
public Integer getZipcode() {
return zipcode;
}
public void setZipcode(Integer zipcode) {
this.zipcode = zipcode;
}
public Double getPrice() {
return price;
}
public void setPrice(Double price) {
this.price = price;
}
public Category getCategory() {
return category;
}
public void setCategory(Category category) {
this.category = category;
}
#Override
public String toString() {
return "Item [id=" + id + ", title=" + title + ", description=" + description + ", status=" + status
+ ", zipcode=" + zipcode + ", price=" + price + ", category=" + category + "]";
}
}
so tried taking the category and got it working so far like this:
<table class="table table-striped">
<tr th:each ="category : ${categorys}">
<td th:text="${category.id}" ></td>
<td th:text="${category.items}" ></td>
//shows the size of the array
<td th:text="${category.items.size()}" ></td>
</tr>
<!-- this is what I want as the result, I would like to know how to loop with the TH attribute
<tr>
<td th:text="${category.items[0].title}"></td>
<td th:text="${category.items[0].category.type}"></td>
<td th:text="${category.items[0].description}"></td>
<td th:text="${category.items[0].status}"></td>
<td th:text="${category.items[0].zipcode}"></td>
<td th:text="${category.items[0].price}"></td>
</tr>
-->
This is my first web app using Spring mvc, at this point I am a bit stuck and would appreciate it if someone pointed me towards the right path thank you :D
To achieve a nested loop in Thymeleaf, simply do the following:
<th:block th:each="category : ${categorys}">
<tr th:each="item : ${category.items}">
<td th:text="${category.item.title}"></td>
<td th:text="${category.item.category.type}"></td>
<td th:text="${category.item.description}"></td>
<td th:text="${category.item.status}"></td>
<td th:text="${category.item.zipcode}"></td>
<td th:text="${category.item.price}"></td>
</tr>
</th:block>
I was able to achieve the result asked without the nested loops. by changing the parameter type to Category which is the attribute type in the entity class.
Repository:
List<Item> findByCategory(Category categoryid);
Controller :
#RequestMapping(value="/item-by-category/{id}",method= RequestMethod.GET)
public String itemByCategory(#PathVariable("id") Category categoryid, Model model){
model.addAttribute("items",irepository.findByCategory(categoryid));
return "/itemlist";
}
Related
I'm wondering how I can receive the object from frontend(Thymeleaf) using #ModelAttribute. Main purpose of this is to edit object in the new view(html) where the fields are filled updated object therefore the invoice object is passed to model for further editing.
I tried to do that.
Model
public class Invoice {
private Long id;
private BigDecimal price;
#DateTimeFormat(pattern = "yyyy-MM-dd")
private LocalDate date;
private String name;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public BigDecimal getPrice() {
return price;
}
public void setPrice(BigDecimal price) {
this.price = price;
}
public LocalDate getDate() {
return date;
}
public void setDate(LocalDate date) {
this.date = date;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
#GetMapping("/edit")
public String editInvoice(Model model, #ModelAttribute Invoice invoice){
model.addAttribute("updatedInvoice", invoice);
return "edit";
}
<tr th:each="invoice:${allInvoices}">
<td th:text="${invoice.id}"></td>
<td th:text="${invoice.price}"></td>
<td th:text="${invoice.date}"></td>
<td th:text="${invoice.name}"></td>
<td><a th:href="#{/delete(id=${invoice.id})}" class="btn btn-danger">DELETE</a></td>
<td><a th:href="#{/edit(invoice=${invoice})}" class="btn btn-primary">EDIT</a></td>
</tr>
Finally I see that the invoice object has allocated memory but it is empty(I mean its variables)
When I printout the invoice object I get this: main.domain.model.Invoice#37567a3b it is not null but object has empty variables.
Thank you in advance for support and help.
Main purpose of this is to edit object in the new view(html) where the fields are filled updated object therefore the invoice object is passed to model for further editing.
I have table employee and table employee_detail, I can add data to non related table(employee), controller work fine, everything is okey, but I cant implement code so I can store data to related table employee_detail
Employee:
#Entity
#Table(name="employee")
public class Employee {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "employeeId")
private int id;
#Column(name = "first_name")
private String firstName;
#Column(name = "last_name")
private String lastName;
#Column(name = "email")
private String email;
#OneToOne(mappedBy = "employee")
private EmployeeDetail employeeDetail;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public EmployeeDetail getEmployeeDetail() {
return employeeDetail;
}
public void setEmployeeDetail(EmployeeDetail employeeDetail) {
this.employeeDetail = employeeDetail;
}
}
EmployeeDetail:
#Entity
#Table(name = "employee_detail")
public class EmployeeDetail {
#Id
#GeneratedValue(strategy= GenerationType.AUTO)
#Column(name="employee_detail_id")
private int id;
#Column(name="work_experience")
private int workExperience;
#Column(name="hobby")
private String hobby;
#Column(name="nationality")
private String nationality;
#OneToOne
#JoinColumn(name="employeeId")
private Employee employee;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public int getWorkExperience() {
return workExperience;
}
public void setWorkExperience(int workExperience) {
this.workExperience = workExperience;
}
public String getHobby() {
return hobby;
}
public void setHobby(String hobby) {
this.hobby = hobby;
}
public String getNationality() {
return nationality;
}
public void setNationality(String nationality) {
this.nationality = nationality;
}
public Employee getEmployee() {
return employee;
}
public void setEmployee(Employee employee) {
this.employee = employee;
}
}
This is how I store data to employee table:
`EmployeeController:`
#Controller
#RequestMapping("/employee")
public class EmployeeController {
#Autowired
private EmployeeService employeeService;
#GetMapping("/list")
public String listEmployee(Model theModel) {
// get customers from the service
List<Employee> theEmployee = employeeService.listEmployee();
// add the customers to the model
theModel.addAttribute("employees", theEmployee);
return "list-employee";
}
#GetMapping("/showFormForAdd")
public String showFormForAdd(Model theModel) {
// create model attribute to bind form data
Employee theEmployee = new Employee();
theModel.addAttribute("employee", theEmployee);
return "addNewEmployeeForm";
}
#PostMapping("/addNewEmployee")
public String addNewEmployee(#ModelAttribute("employee") Employee theEmployee) {
// save the customer using our service
employeeService.addNewEmployee(theEmployee);
return "redirect:/employee/list";
}
}
And form addNewEmployeeForm:
<form:form action="addNewEmployee" modelAttribute="employee" method="POST">
<table>
<tbody>
<tr>
<td><label>First name:</label></td>
<td><form:input path="firstName" /></td>
</tr>
<tr>
<td><label>Last name:</label></td>
<td><form:input path="lastName" /></td>
</tr>
<tr>
<td><label>Email:</label></td>
<td><form:input path="email" /></td>
</tr>
<tr>
<td><label></label></td>
<td><input type="submit" value="Save" class="save" /></td>
</tr>
</tbody>
</table>
How to store data into table from related table? What m I missing?
I tried like this but doesnt work:
#Controller
#RequestMapping("/employeeDetail")
public class EmployeeDetailController {
#Autowired
private EmployeeDetailService employeeDetailService;
#GetMapping("/listEmployeeDetail")
public String listEmployeeDetail(Model theModel) {
// get customers from the service
List<EmployeeDetail> theEmployeeDetail = employeeDetailService.listEmployeeDetail();
// add the customers to the model
theModel.addAttribute("employeeDetails", theEmployeeDetail);
return "list-employeeDetail";
}
#GetMapping("/showFormForAddEmployeeDetail")
public String showFormForAddEmployeeDetail(Model theModel) {
// create model attribute to bind form data
EmployeeDetail theEmployeeDetail = new EmployeeDetail();
theModel.addAttribute("employeeDetail", theEmployeeDetail);
return "addNewEmployeeDetailForm";
}
#PostMapping("/addNewEmployeeDetail")
public String addNewEmployeeDetail(#ModelAttribute("employeeDetail") EmployeeDetail theEmployeeDetail) {
// save the customer using our service
employeeDetailService.addNewEmployeeDetail(theEmployeeDetail);
return "redirect:/employeeDetail/listEmployeeDetail";
}
}
Requested code:
#Override
#Transactional
public void addNewEmployeeDetail(EmployeeDetail theEmployeeDetail) {
employeeDetailDAO.addNewEmployeeDetail(theEmployeeDetail);
}
Assuming your are not actively saving the EmployeeDetail entities on your own and only saving Employee, then configure cascade attribute on #OneToOne relationship on Employee side as follows:
#OneToOne(mappedBy = "employee", cascade = CascadeType.ALL)
private EmployeeDetail employeeDetail;
With this, you are telling your EntityManager to propagate (cascade) all operations (PERSIST, REMOVE, REFRESH, MERGE, DETACH) to the relating entities.
In addition to the change above, I would also recommend you moving to JPA instead of handling Hibernate Sessions on your own.
Include the Spring Boot JPA dependency in your pom.xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
Create two repositories, one for each entity and inject them into the corresponding Service (just like you are doing with your DAOs):
public interface EmployeeDAO extends JpaRepository<Employee, Integer> {
}
public interface EmployeeDetailDAO extends JpaRepository<EmployeeDetail, Integer> {
}
Now in your Services, you can call a couple of default methods on these Repositories such as findAll() or save(). In your case you would do something like the following:
#Override
#Transactional
public void addNewEmployee(Employee theEmployee) {
employeeDAO.save(theEmployee);
}
You can check more details at https://www.baeldung.com/the-persistence-layer-with-spring-and-jpa and https://www.baeldung.com/spring-data-repositories.
Keep in mind that you will have a hard time saving EmployeeDetail directly as you receive it from your form. The reason being that you need to set Employee attribute, otherwise the foreign key in the column employeeId would be set and thus you will get a SQL error.
I am working on a simple CRUD project using Spring, Hibernate & JPA.
It's a basic coupon system, Coupon object has parameters, one of them is Coupon Type. When typing in the vales in the jsp which is bound to the server:
<h1> Create Coupon </h1>
<form:form action="company/create" method="POST" modelAttribute="theCoupon">
<input name="title"/>
<input name="startDate"/>
<input name="endDate"/>
<input name="amount"/>
<input name="message"/>
<input name="price"/>
<input name="image"/>
<select name="couponType">
<option>SPORTS</option>
<option>GAMING</option>
</select>
<input type="submit" value="submit">
</form:form>
this is the controller :
#PostMapping("/add")
public String newCoupon(Model theModel) {
List<CouponType> couponType = new ArrayList<CouponType>( Arrays.asList(CouponType.values()));
System.out.println(couponType);
theModel.addAttribute("couponType", couponType);
theModel.addAttribute("theCoupon", new Coupon());
return "add";
}
#RequestMapping("/create")
public String add(#ModelAttribute("theCoupon") Coupon theCoupon) {
theCoupon.setId(0);
System.out.println(theCoupon);
couponService.save(theCoupon);
return "savedCoupon";
}
I am getting this error:
java.sql.SQLSyntaxErrorException: Unknown column 'coupon0_.coupon_type' in 'field list'
Here is a screenshot of the database structure, the names are the same I have no idea whats the problem.
Also, here is the Coupon pojo:
#Entity
#Table(name = "coupon")
public class Coupon {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id")
private long id;
#Column(name = "title")
private String title;
#Column(name = "startDate")
private String startDate;
#Column(name = "endDate")
private String endDate;
#Column(name = "amount")
private int amount; // decrease amount on every customer purchase
#Column(name = "couponType")
private String couponType;
#Column(name = "message")
private String message;
#Column(name = "price")
private double price;
#Column(name = "image")
private String image;
public Coupon(long id, String title, String startDate, String endDate, int amount, String couponType,
String message, double price, String image) {
super();
this.id = id;
this.title = title;
this.startDate = startDate;
this.endDate = endDate;
this.amount = amount;
this.couponType = couponType;
this.message = message;
this.price = price;
this.image = image;
}
public Coupon() {
super();
}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getStartDate() {
return startDate;
}
public void setStartDate(String startDate) {
this.startDate = startDate;
}
public String getEndDate() {
return endDate;
}
public void setEndDate(String endDate) {
this.endDate = endDate;
}
public int getAmount() {
return amount;
}
public void setAmount(int amount) {
this.amount = amount;
}
public String getCouponType() {
return couponType;
}
public void setCouponType(String couponType) {
this.couponType = couponType;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
public String getImage() {
return image;
}
public void setImage(String image) {
this.image = image;
}
#Override
public String toString() {
return "Coupon [id=" + id + ", title=" + title + ", startDate=" + startDate + ", endDate=" + endDate
+ ", amount=" + amount + ", couponType=" + couponType + ", message=" + message + ", price=" + price
+ ", image=" + image + "]";
}
}
Hope anyone of you could spot the problem, any help would be appreciated!
[SOLVED]
The problem was that I was using two words in my var, like couponType, would be coupon_type on the data base.
changed it to type only, the pojo & the database & now it works fine!
hope this helps to anyone that had this problem.
I keep getting 400 Bad Request error whenever im trying to pass an entire object through form:select.
HTTP Status 400 – Bad Request
Type Status Report
Description The server cannot or will not process the request due to something that is perceived to be a client error (e.g., malformed request syntax, invalid request message framing, or deceptive request routing).
This is my select form:
<html>
<head>
<title>Dodaj produkt do aukcji</title>
</head>
<body>
<form:form action="saveProduct${auction.id}" modelAttribute="newProduct" method="POST">
<label>Nazwa:</label> <form:input path="name"/><br>
<label>Cena:</label> <form:input path="price"/><br>
<label>Kategoria:</label>
<form:select path="productCategory">
<form:options items="${productCategories}" itemLabel="name"/>
</form:select><br>
<input type="submit" value="Dodaj" class="save"/><br>
</form:form>
</body>
</html>
Controller:
#GetMapping("/addProductPage")
public String addProductPage(#RequestParam("auctionId") int id,Model theModel) {
Collection <ProductCategory> pCategories = productCategoryService.getProductCategories();
Auction auction = auctionService.getAuction(id);
Product product = new Product();
ProductCategory pCategory = new ProductCategory();
theModel.addAttribute("auction", auction);
theModel.addAttribute("newProduct", product);
theModel.addAttribute("productCategories", pCategories);
return "add-product";
}
#PostMapping("/saveProduct{someId}")
public String saveProduct(#ModelAttribute("newProduct") Product product, #PathVariable(value="someId") String someId) {
Auction auction = auctionService.getAuction(Integer.parseInt(someId));
Collection<Product> products = auction.getProducts();
products.add(product);
auction.setProducts(products);
product.setAuction(auction);
auctionService.saveAuction(auction);
productService.saveProduct(product);
return "redirect:/showMyAuctions";
}
Product entity:
#Entity
#Table(name="product")
public class Product {
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
#Column(name="product_id")
private int id;
#Column(name="name")
private String name;
#Column(name="price")
private float price;
#ManyToOne
#JoinColumn(name="category_id")
private ProductCategory productCategory;
#ManyToOne
#JoinColumn(name="auction_id")
private Auction auction;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public float getPrice() {
return price;
}
public void setPrice(float price) {
this.price = price;
}
public ProductCategory getProductCategory() {
return productCategory;
}
public void setProductCategory(ProductCategory productCategory) {
this.productCategory = productCategory;
}
public Auction getAuction() {
return auction;
}
public void setAuction(Auction auction) {
this.auction = auction;
}
#Override
public String toString() {
return "Product [id=" + id + ", name=" + name + ", price=" + price + ", productCategory=" + productCategory
+ "]";
}
}
Product category entity:
#Entity
#Table(name="product_category")
public class ProductCategory {
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
#Column(name="category_id")
private int id;
#Column(name="name")
private String name;
#OneToMany(mappedBy="productCategory", cascade=CascadeType.ALL, fetch=FetchType.EAGER)
Collection<Product> products;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Collection<Product> getProducts() {
return products;
}
public void setProducts(Collection<Product> products) {
this.products = products;
}
#Override
public String toString() {
return "ProductCategory [id=" + id + ", name=" + name + "]";
}
}
What i want is the chosen product category to be added to the product.
Spring expect productCategory to be an object but it's name of productCategory as specified in tag.
you need to try something like:
<form:select path="productCategory.name">
<form:options items="${productCategories}" itemLabel="name" itemValue= "name"/>
</form:select>
I've been dealing with a problem which I require your help.
#Controller
public class JokeController {
#Autowired
JokeRepository jokeRepository;
CategoryRepository categoryRepository;
public Category dark_humor = new Category("Dark Humor");
public Category sports_and_athletes = new Category("Sports And Athletes");
#GetMapping("/new")
public String jokeForm(Model model) {
model.addAttribute("joke", new Joke());
return "jokeForm"; // jokeForm.html
}
#PostMapping("/new")
public String jokeSubmit(#ModelAttribute Joke joke) {
//joke.setCategory(dark_humor);
jokeRepository.save(joke);
return "redirect:/new";
//return "resultJoke"; // resultCategory.html
}
}
My entities:
Relationship is that Category can have many Jokes, but Joke can only belong to one Category.
Category
#Entity
public class Category {
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
private int id;
#Column(name = "name")
private String name;
public Category() {
}
public Category(String name) {
this.name = name;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
#Override
public String toString() {
return "Category{" +
"id=" + id +
", name='" + name + '\'' +
'}';
}
}
Joke
#Entity
public class Joke {
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
private int joke_id;
#Column(name = "likes")
#Value("${some.key:0}")
private int likes;
#Column(name = "dislikes")
#Value("${some.key:0}")
private int dislikes;
#Column(name = "content")
#NotNull
private String content;
#ManyToOne(fetch = FetchType.EAGER, cascade=CascadeType.ALL)
#NotNull
#JoinColumn(name = "category_id")
private Category category;
public Joke() {
}
public Joke(#NotNull String content, #NotNull Category category) {
this.content = content;
this.category = category;
}
public int getJoke_id() {
return joke_id;
}
public void setJoke_id(int joke_id) {
this.joke_id = joke_id;
}
public int getLikes() {
return likes;
}
public void setLikes(int likes) {
this.likes = likes;
}
public int getDislikes() {
return dislikes;
}
public void setDislikes(int dislikes) {
this.dislikes = dislikes;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
public Category getCategory() {
return category;
}
public void setCategory(Category category) {
this.category = category;
}
#Override
public String toString() {
return "Joke{" +
"joke_id=" + joke_id +
", likes=" + likes +
", dislikes=" + dislikes +
", content='" + content + '\'' +
", category=" + category +
'}';
}
}
My thymeleaf:
<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<title>Getting Started: Handling Form Submission</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
</head>
<body>
<h1>Form</h1>
<form action="#" th:action="#{/new}" th:object="${joke}" method="post">
<p>Content: <input type="text" th:field="*{content}" /></p>
<p>Category: <input type="text" th:field="*{category}" /></p>
<p><input type="submit" value="Submit" /> <input type="reset" value="Reset" /></p>
</form>
</body>
</html>
*Specifically in this section:*
#PostMapping("/new")
public String jokeSubmit(#ModelAttribute Joke joke) {
//joke.setCategory(dark_humor);
jokeRepository.save(joke);
return "redirect:/new";
//return "resultJoke"; // resultCategory.html
}
I would like Hibernate to save new Joke with existing category. But I am not sure how I can in my form load all the existing categories and how to use it in my Post method to send the joke with category that I have picked explicitly in my form. I think I am missing some important aspect that I haven't picked up upon yet.
The first step is to hard code setting the category in the controller to ensure that it saves correctly. I would also reduce your cascade, in the joke class, as I would not have thought saving a joke should be able to modify properties of the category.
Once you are confidant that you can save a joke with a hard coded category, we can look to select the category in the ui. Now you won't easily be able to set the category straight into the joke object, you will find it much easier to pass a value to the controller and use that to select the category on the back end.
If you try something along the lines of
<p>Category: <input type="text" name="categoryid" /></p>
And
jokeSubmit(#ModelAttribute Joke joke, #Requestparam("categoryid") String categoryid) {
Now this should work, although could be cleaner, you are implementing one of my little frustrations: you are using your db objects in your ui layer, ideally ORM objects should not be used as form objects, although that is it of scope for the question I would happily discuss separation of code concepts with you.