Cannot show mysql data using jpa and thymeleaf - spring

I'm very new to Spring. I'm trying to build an user management web app.
Here is the controller
#Controller
#RequestMapping("/index")
public class UserManagementController {
#Autowired
private UserManagementRepository userManagementRepository;
#RequestMapping(method= RequestMethod.GET)
public ModelAndView index(Model model){
ArrayList<Staff> staffList = (ArrayList<Staff>) userManagementRepository.findAll();
ModelAndView modelAndView = new ModelAndView();
modelAndView.setViewName("index");
modelAndView.addObject("staffList", staffList);
return modelAndView;
}
}
The model
#Entity
#Table(name="staff")
#Data
public class Staff {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private int id;
private String name;
private int age;
private String department;
private String sex;
private String status;
}
html file
<tbody>
<tr th:each="staff, state : ${staffList}">
<td th.text="${staff.id}"></td>
<td th.text="${staff.name}"></td>
<td th.text="${staff.age}"></td>
<td th.text="${staff.department}"></td>
<td th.text="${staff.department}"></td>
<td th.text="${staff.status}"></td>
</tr>
and finally the application.properties
spring.datasource.url=jdbc:mysql://localhost:3306/user_management
spring.datasource.username=root
spring.datasource.password=
When i run the project, the table only shows the header and the body is totally blank.

I am not 100% sure but can you try to make all attributes in model public or generate getters and then change your code like:
<td th.text="${staff.getId()}"></td>

Do this:
<tr th:each="staff : ${staffList}">
That will solve your problem If not then comment below and tell whats the problem.

This should work :
<tr th:each="staff : ${staffList}">
<td th:text="${staff.id}"></td>
...
</tr>
If it doesn't, look with a debugger if the value staffList in your controller is not empty or null. If it is, then you have an issue with your database connection or request.

Related

Haw can i show the details of each with using many to many relationship using spring and thymeleaf

I want to display the details of each user here is my class entity
#Entity
#Table(name="user")
public class User implements Serializable{
#Id #GeneratedValue
private Long id;
private String nom ;
#ManyToMany(cascade = {CascadeType.ALL})
#JoinTable(name="user_user_detail",joinColumns={
#JoinColumn(name="id")},
inverseJoinColumns={#JoinColumn(name="UserId")})
private Collection<UserDetail>userDetail ;
classe user detail
#Entity
#Table(name="userDetail")
public class UserDetail implements Serializable{
#Id #GeneratedValue
private Long UserId;
private String adresse ;
My controller
#RequestMapping(name="/vue", method = RequestMethod.GET)
public String vue(Model model){
User u=new User();
List<User>p=new ArrayList<User>();
p.add(u);
p=ur.findAll();
model.addAttribute("us",p);
return "user" ;
}
My view thymeleaf
<table border="1">
<tr>
<td>Nom</td>
<td>adresse</td>
</tr>
<tr th:each="t:${us}">
<td th:text="${t.Id}"></td>
<td th:text="${t.nom}"></td>
<td th:text="${t.getUserDetail()}"></td>
</tr>
</table>
i would to show the userdetail with
${t.getUserDetail()}">
but the result of details like this [org.sid.entity.UserDetail#1469f77e, org.sid.entity.UserDetail#78a81727]
please answer me quickly
thank's in advance

How to display an object that contains another object in thymeleaf

Hi I struggling to build a proper view in case, when I want to display the product entity, which is in a many-to-many relation with the category. The problem starts with the nested category. I have an error: Exception evaluating SpringEL expression: "category.name" (productList: 31) I will be very grateful for your help in solving this problem
View:
<tbody>
<tr data-th-each="product : ${products}">
<!--<td><input hidden="hidden" name="id" th:value="${product.id}" /></td>-->
<td th:text="${product.name}"></td>
<td th:text="${product.price}"></td>
<td th:each="category : ${product.categories}"></td>
<td th:text="${category.name}"></td>
<td th:text="${product.description}"></td>
<td th:text="${product.shippingWeight}"></td>
<td th:text="${product.quantity}"></td>
<td>delete</td>
</tr>
</tbody>
Entities:
#NoArgsConstructor
#AllArgsConstructor
#Getter
#Setter
#Entity
#Table(name = "products")
public class Product {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "product_id")
private Long id;
private String name;
private BigDecimal price;
#ManyToMany(cascade = CascadeType.ALL,mappedBy = "products")
private List<Category> categories=new ArrayList<>();
private double shippingWeight;
private boolean isAvailable;
private String description;
private int quantity;
#Transient
private MultipartFile image;
Category:
#AllArgsConstructor
#NoArgsConstructor
#Getter
#Setter
#Entity
#Table(name = "categories")
public class Category {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "category_id")
private Long id;
private String name;
private String description;
#ManyToMany(cascade = CascadeType.ALL)
#JoinTable(name = "join_category_product", joinColumns = {#JoinColumn(name = "category_id", referencedColumnName = "category_id")},
inverseJoinColumns = {#JoinColumn(name = "product_id", referencedColumnName = "product_id")})
private List<Product> products=new ArrayList<>();
#Transient
private MultipartFile image;
Controller:
#GetMapping("/productList")
public String productList(Model model) {
List<Product> product = productService.getProducts();
model.addAttribute("products",product);
return "productList";
You need to make sure that the Thymeleaf can understand the scope of your variables. In your post, you have category.name outside of the for loop. If categories is a property of product, you can do something like:
<tr th:each="product : ${products}">
<td th:text="${product.name}"></td>
<td th:text="${product.price}"></td>
<td>
<th:block th:each="category : ${product.categories}">
<th:block th:text="${category.name}">[category name]</th:block>
<br>
</th:block>
</td>
<td th:text="${product.description}"></td>
<td th:text="${product.shippingWeight}"></td>
<td th:text="${product.quantity}"></td>
<td>delete</td>
</tr>
If a product doesn't have a category, note that the above will still create a <td>. This is likely what you want.
Aside: it would also make sense to supply default values between your tags. This way, you can open up the file directly in a browser (without a container) and still see how it would lay out. This is a huge reason to use Thymeleaf. I included this with [category name] example above.
Otherwise, you can do the shorter version:
<td>[[${product.name}]]</td>

Object null in View layer

i have this problem:
O pedido:
#Entity
#Table(name="wp_posts")
public class Pedido implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue
private Long id;
#Column(name="post_status")
private String status;
#Column(name="post_type")
private String tipo;
#OneToMany(mappedBy = "pedido", cascade=CascadeType.ALL, orphanRemoval = true)
private List<PedidoMeta> pedidoMeta;
#OneToMany(mappedBy = "pedido", cascade=CascadeType.ALL, orphanRemoval = true)
private List<PedidoItem> itens;
#Column(name="post_date")
private Date data;
#Transient
private Usuario cliente;
O Controller:
#GetMapping(value = "/detalhePedido/{id}")
public ModelAndView detalhePedido( #PathVariable(value = "id", required = false) String pedidoid) {
pedido = pedidoRepository.findOne(new Long(pedidoid));
pedido = pedidoService.findCliente(pedido);
ModelAndView modelAndView = new ModelAndView("DetalhePedido");
modelAndView.addObject("pedido",pedido);
return modelAndView;
}
a View:
<tbody>
<tr th:object="${pedido}">
<td th:text="*{pedido.id}"></td>
<td th:text="*{pedido.cliente.nome}"></td>
<td th:text="*{#dates.format(pedido.data, 'dd-MM-yyyy')}"></td>
</tr>
</tbody>
O erro:
org.springframework.expression.spel.SpelEvaluationException: EL1008E:
Property or field 'pedido' cannot be found on object of type 'com.ledolate.sys.model.Pedido' - maybe not public?
When debugging, the request is correct, with all the information, but when receiving in the visual layer it presents this error.
Welcome to SO.
The issue is in your HTML. You may want simply:
<tbody>
<tr>
<td th:text="${pedido.id}"></td>
<td th:text="${pedido.cliente.nome}"></td>
<td th:text="${#dates.format(pedido.data, 'dd-MM-yyyy')}"></td>
</tr>
</tbody>
Or, if you are using th:object, then you're telling Thymeleaf that you are selecting the pedido variable and therefore shouldn't specify it again (unless pedido has a property also called pedido):
<tbody th:object="${pedido}">
<tr>
<td th:text="*{id}"></td>
<td th:text="*{cliente.nome}"></td>
<td th:text="*{#dates.format(data, 'dd-MM-yyyy')}"></td>
</tr>
</tbody>
The error message states exactly this.
See the docs for examples.

java spring mvc many to many

I'm trying to make a many-to-many example app with spring mvc and hibernate.
I have 2 classes, book and author. I've mapped these 2 class created all relations, but the problem is I can't add values to my join table.
Where's the problem?
CREATE TABLE author
(
author_id serial NOT NULL,
author_name character(100),
CONSTRAINT author_pkey PRIMARY KEY (author_id)
)
CREATE TABLE book
(
book_id serial NOT NULL,
book_name character(50) NOT NULL,
price integer NOT NULL,
CONSTRAINT book_pkey PRIMARY KEY (book_id)
)
CREATE TABLE book_author
(
book_id integer NOT NULL,
author_id integer NOT NULL,
CONSTRAINT book_author_pkey PRIMARY KEY (book_id, author_id),
CONSTRAINT book_author_author_id_fkey FOREIGN KEY (author_id)
REFERENCES author (author_id) MATCH SIMPLE
ON UPDATE NO ACTION ON DELETE NO ACTION,
CONSTRAINT book_author_book_id_fkey FOREIGN KEY (book_id)
REFERENCES book (book_id) MATCH SIMPLE
ON UPDATE NO ACTION ON DELETE NO ACTION
)
and my java files
#Entity
#Table(name = "book")
public class Book {
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
private int book_id;
#Column
private String book_name;
#Column
private int price;
#ManyToMany(fetch = FetchType.LAZY)
#JoinTable(
name = "book_author",
joinColumns = { #JoinColumn(name = "book_id")},
inverseJoinColumns = { #JoinColumn(name = "author_id") }
)
private Set<Author> authors = new HashSet<Author>();
//geters and setters
}
Author.java
#Entity
#Table(name="author")
public class Author {
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
#Column(name="author_id")
private int author_id;
#Column
private String author_name;
#ManyToMany(mappedBy = "authors")
private Set<Book> books = new HashSet<Book>();
//getters and setters
}
BookDAOImpl.java
#Repository
public class BookDAOImpl implements BookDAO{
#Autowired
private SessionFactory sessionFactory;
public void addBook(Book book) {
sessionFactory.getCurrentSession().saveOrUpdate(book);
}
}
BookServiceImpl.java
#Service
#Transactional
public class BookServiceImpl implements BookService{
#Autowired
private BookDAO bookDAO;
#Override
public void addBook(Book book) {
bookDAO.addBook(book);
}
}
BookController.java
#Controller
#SessionAttributes("authors")
public class BookController {
#Autowired
private BookService bookService;
#Autowired
private AuthorService authorService;
#RequestMapping(value = "/newBook", method = RequestMethod.GET)
public ModelAndView newBook(ModelAndView model) {
Book book = new Book();
model.addObject("book", book);
model.setViewName("bookForm");
return model;
}
#RequestMapping(value = "/saveBook", method = RequestMethod.POST)
public ModelAndView saveBook(#ModelAttribute Book book,BindingResult result)
{
if (book.getBook_id() == 0) {
// if employee id is 0 then creating the
// employee other updating the employee
bookService.addBook(book);
} else {
bookService.updateBook(book);
}
return new ModelAndView("redirect:/newBook");
}
#ModelAttribute("authors")
public List<Author> getAuthors(){
return authorService.getAuthors();
}
}
and finally here is bookForm.jsp file
<body>
<div align="center">
<h1>New/Edit Book</h1>
<form:form action="saveBook" method="post" modelAttribute="book">
<table>
<form:input type="hidden" path="book_id"/>
<tr>
<td>Name:</td>
<td><form:input path="book_name" /></td>
</tr>
<tr>
<td>Price:</td>
<td><form:input path="price" /></td>
</tr>
<tr>
<td>Author:</td>
<td><form:select path="authors" items="${authors}" itemValue="author_id" itemLabel="author_name"/></td>
</tr>
<tr>
<td colspan="2" align="center"><input type="submit" value="Save"></td>
</tr>
</table>
</form:form>
</div>
</body>
After the page opens, I enter some book name and price and choose an author and click the Save button. It saves book but not saves the join table book_author.
As you can see I can send author_id from uipng
And I can insert book object to database

Hibernate OneToOne using Spring and JSP

I have a question to ask:
I have to tables user and user_login joined OneToOne by user.id -> user_login.user_id.
The issue is when I do .updateObject(user) I get 2 queries executed:
Hibernate: insert into User (created, modified, email, first_name,
last_name) values (?, ?, ?, ?, ?) Hibernate: insert into user_login
(created, modified, password, user_id) values (?, ?, ?, ?) [2012-08-15
12:15:04,192] [ERROR] [http-bio-8080-exec-1] SqlExceptionHelper [144]:
Column 'user_id' cannot be null
and looks like there is no reference between 2 objects. If into the Entity User, method setUserLogin I add line
userLogin.setUser(this); its working but I dont find this way elegant honestly. Is there anything I missed in entity configuration
maybe that does not do that automatically ?
Thank you
Here are my Entities
#Entity
#NamedQueries({ #NamedQuery(name = "user.list", query = "select u from User u") })
public class User implements java.io.Serializable {
#Column(name = "first_name", nullable = true)
private String firstName;
#OneToOne(mappedBy = "user", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
#JoinColumn(name="user_id", nullable=false)
private UserLogin userLogin;
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public UserLogin getUserLogin() {
return userLogin;
}
public void setUserLogin(UserLogin userLogin) {
this.userLogin = userLogin;
//userLogin.setUser(this); THIS IS THE LINE THAT FIXES IT, BUT I DONT FIND THIS WAY ELEGANT
}
}
#Entity
#Table(name="user_login")
public class UserLogin implements java.io.Serializable {
#Column(name = "password", nullable = false)
private String password;
#OneToOne(optional = false, fetch = FetchType.LAZY)
private User user;
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
}
JSP File:
<%# taglib uri="http://www.springframework.org/tags/form" prefix="form"%>
<%# taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<%# taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="fn"%>
<html>
<head>
<title>Registration Page</title>
</head>
<body>
<form:form action="/test" commandName="user">
<tr>
<td>User Name :</td>
<td><form:input path="firstName" /></td>
</tr>
<tr>
<td>Password :</td>
<td><form:input path="userLogin.password" /></td>
</tr>
<tr>
<td colspan="2"><input type="submit" value="Register"></td>
</tr>
</table>
</form:form>
</body>
</html>
Spring Controller:
#Controller(value = "/")
public class Test {
#Autowired
UserServiceImpl userServiceImpl;
#RequestMapping(method = RequestMethod.GET, value = "/test")
public void test(ModelMap model) {
model.addAttribute("user", new User());
}
#RequestMapping(method = RequestMethod.POST, value = "/test")
public void test(User user) {
userServiceImpl.update(user);
}
}
As usual, bidirectional relationships do have owning side. Owning side of relationship is attribute that is referenced by mappedBy. In your case attribute user in UserLogin entity is the owning side.
When relationship is persisted to the database, only owning side is consulted. This means, that you have to set value for user attribute to be able to persist. To keep also entity graph in memory consistent both sides of the relationship should be set.
In JPA 2.0 specification this is told with following words:
Bidirectional relationships between managed entities will be persisted
based on references held by the owning side of the relationship. It is
the developer’s responsibility to keep the in-memory references held
on the owning side and those held on the inverse side consistent with
each other when they change.

Resources