JavaRush /Java Blog /Random EN /Introduction to Maven, Spring, MySQL, Hibernate and the f...
Макс
Level 41

Introduction to Maven, Spring, MySQL, Hibernate and the first CRUD application (part 4)

Published in the Random EN group
Good afternoon. In this article I would like to share my first encounter with things like Maven, Spring, Hibernate, MySQL and Tomcat in the process of creating a simple CRUD application. This is the final part. The article is intended primarily for those who have already completed 30-40 levels here, but have not yet ventured beyond pure Java and are just beginning (or are about to begin) to enter the open world with all these technologies, frameworks and other unfamiliar words. This is the final fourth part of the article “Introduction to Maven, Spring, MySQL, Hibernate and the first CRUD application.” Previous parts can be seen by following the links:

Content:

Design and web resources

Our application works, but you can’t look at it without tears, boring inscriptions, ugly links, empty white background. We need to fix this and add different beauties. How do we do this? Well, first of all, you can just play around with the pages and do all sorts of things using the capabilities of HTML . But if you try to change backgrounds, colors, sizes, arrangement of elements, etc. using HTML alone. and so on. then in the end you can make such a mess out of the page that you can’t make out anything there later. And besides, HTML's design options are quite limited. It is better to use CSS (Cascading Style Sheets) for this . Then everything related to the design can be collected in one place, and then applied to the desired element of the page. CSS code can be written directly on the JSP page in a special tag, but it is much more convenient to put it in a separate file, and then simply apply it to the necessary pages. To place files with styles and other static web resources, we will create a separate directory inside webapp . In order not to confuse web resources with regular resources (where we have db.properties ), let's just call this directory res and place all CSS files, images, etc. there:
Introduction to Maven, Spring, MySQL, Hibernate and the first CRUD application (part 4) - 1
To use these files we need to specify their location in the configuration. Let's go to our class WebConfig. Previously, we used the annotation @EnableWebMvcto not configure anything, but simply use the default configuration. But now there is a need to configure something. To do this, we use the interface WebMvcConfigurer, which allows you to override configuration methods. That. we can use the default configuration, but at the same time customize some aspects for ourselves. In this case addResourceHandlers, we need a method with which we indicate the location of static web resources. Just in case, the entire class ends up looking like this:
package testgroup.filmography.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.ViewResolver;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.servlet.view.InternalResourceViewResolver;

@Configuration
@EnableWebMvc
@ComponentScan(basePackages = "testgroup.filmography")
public class WebConfig implements WebMvcConfigurer {

    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/res/**").addResourceLocations("/res/");
    }

    @Bean
    ViewResolver viewResolver() {
        InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
        viewResolver.setPrefix("/WEB-INF/pages/");
        viewResolver.setSuffix(".jsp");
        return viewResolver;
    }
}
Now to use our CSS on the page you need to link to it inside the tag head:
<head>
    <link href="<c:url value="/res/style.css"/>" rel="stylesheet" type="text/css"/>
</head>
Just add this line and make, for example, this simple CSS file:
table {
    border-spacing: 0 10px;
    font:  bold 100% Georgia, serif;
    margin: 40px auto;
    text-shadow: 5px 5px 5px #3F3F7F;
    background: #B1B9D9;
    text-align: center;
    vertical-align: middle;
    width: 50%;
    border: 10px solid blue;
}
And this will completely change our table (it looks stupid, of course, but it’s like this, for example): Introduction to Maven, Spring, MySQL, Hibernate and the first CRUD application (part 4) - 2Well, I think there’s no need to talk in detail about CSS, everything is quite simple. On the Internet you can find a lot of ready-made options for designing tables and forms. But it’s better, of course, to do the design yourself, you don’t need to be a designer, after all, this is not some kind of complicated site. Even a few hours after the first acquaintance will be enough to create a fairly beautiful and neat design for such a simple page. In addition, the Internet is full of all sorts of lessons, examples, there are special sites where you can simultaneously edit HTML, CSS on one screen and immediately see what it all looks like. With a little practice you can create real art. True, you shouldn’t get too carried away here either (unless, of course, you have plans to become a designer), otherwise design is such a thing, you can get stuck here for a very long time. When I first started to understand CSS, I got stuck. I wanted to try everything, every property, twisted something, tinkered with it, experimented, took pages of some sites and remade them beyond recognition. I probably had fun with this toy for a week, doing nothing else, until it let me go :) Well, in general, of course, you shouldn’t overdo it and make an incomprehensible colorful miracle, you need to do it simply and tastefully. The only thing worth noting. You need to understand that CSS is a description of design , and HTML is markup . You shouldn’t try to do absolutely everything through CSS; some aspects will be very difficult to do, and some are simply impossible, when in HTML this is done with a couple of extra lines, or even just one attribute in a tag. You need to combine them, make all sorts of colors, backgrounds, fonts in CSS, and if, for example, you need to combine a couple of table cells, it’s easier to use HTML tools. Well, for example, here’s what I was able to do with the pages in a couple of hours of fiddling with CSS and HTML (I won’t go into detail here about the mess I made to achieve this, at the end there will be a link to the GitHub of this project where you can look): Introduction to Maven, Spring, MySQL, Hibernate and the first CRUD application (part 4) - 3Of course, I don’t know how competently I did everything there, but considering that I first saw CSS a week before, I think it turned out quite well.

Pagination

Now everything works, it looks good, but there are only a few records in the table so far. What if there are a hundred films in it, or a thousand? It’s not very convenient to scroll through such a long list. It is much more convenient when the list is displayed in pages of 10 entries, for example. Therefore, now we will try to implement splitting the list into pages (sometimes this is also called “paging” or “pagination” ( English pagination )). This can be done in different ways. For example, you can transfer the full list to a jsp page and create a table there for the required number of records. Or, for example, you can pull out the required records from the general list in the service, and then send this mini-list to a jsp page for display. But it is best, of course, to do this at the database level. The idea is not to take a complete list from the database and then break it into pieces, but to initially get the required piece from the database without touching everything else. After all, why do we need to pull out all hundreds or thousands of records from the database at once, if the one we need is in the top ten, it’s better to pull out only this one ten. Let's go to DAO and add allFilmsa parameter to the method int page, which will be responsible for the page number (in the service, of course, we do the same). And let’s change the implementation of this method a little; if earlier we pulled out the entire list, now we’ll pull out only a part. setFirstResultThe methods (which row of the table to start with) and setMaxResults(how many records to display) will help us with this :
@SuppressWarnings("unchecked")
public List<Film> allFilms(int page) {
    Session session = sessionFactory.getCurrentSession();
    return session.createQuery("from Film").setFirstResult(10 * (page - 1)).setMaxResults(10).list();
}
Those. if this is the 1st page, we display a maximum of 10 records, starting from the 0th; if this is the 5th page, then 10 records starting from the 40th (do not forget that the numbering in the database starts from 0). We will also additionally create a method that will return the number of records in the table. We will need this in order to know the number of all pages and create links for them on our jsp page:
public int filmsCount() {
     Session session = sessionFactory.getCurrentSession();
     return session.createQuery("select count(*) from Film", Number.class).getSingleResult().intValue();
 }
Using such a query, we will get the number of all records in the table (as inta value) without pulling out the records themselves. Now let's go to the controller and work on the method that returns the main page with a list of movies:
@RequestMapping(value = "/", method = RequestMethod.GET)
public ModelAndView allFilms(@RequestParam(defaultValue = "1") int page) {
    List&ltFilm> films = filmService.allFilms(page);
    int filmsCount = filmService.filmsCount();
    int pagesCount = (filmsCount + 9)/10;
    ModelAndView modelAndView = new ModelAndView();
    modelAndView.setViewName("films");
    modelAndView.addObject("page", page);
    modelAndView.addObject("filmsList", films);
    modelAndView.addObject("filmsCount", filmsCount);
    modelAndView.addObject("pagesCount", pagesCount);
    return modelAndView;
}
A new annotation has appeared here @RequestParam, which indicates that we are getting this value from a request parameter. Now, if we go to an address with a parameter, for example http://localhost:8080/ ?page=4 , we will get, accordingly, the 4th page. We set the default value to " 1 " so that when the application starts, when we go to an address without the http://localhost:8080/ parameter , we get the first page. In the method we get the number of all records, then in this simple way we calculate the number of pages. Those. if we have 10 records, this is 1 page, and if there are 11, then this is already 2. Well, we transfer this whole thing to the model. You need to know the number of pages in order to create links for them all in a cycle, and let the number of films be there just in case, for example, if you want to display this information somewhere on the page. Now all that remains is to go to films.jsp and add links to each page using this construct:
<c:forEach begin="1" end="${pagesCount}" step="1" varStatus="i">
    <c:url value="/" var="url">
        <c:param name="page" value="${i.index}"/>
    </c:url>
    <a href="${url}">${i.index}</a>
</c:forEach>
We create links by counter 1, 2, 3, ... and set the parameter by the index value.

By the way, in the same way as with pagination, you can add other features, such as sorting, filtering, and searching. We simply pass various parameters to the DAO method and use them to form an appropriate query to the database in order to pull out the required records in the required order.

Let's add one more small touch. We return to the controller. In the add, edit and delete methods, after the operation is completed, we redirect to the main page "redirect:/" . That. if we are somewhere on the 50th page and click edit entry, then after execution we will go to the address " / ", i.e. Let's go back to page 1. This is not very convenient; I would like to return to where we came from. Let's solve this very simply. FilmControllerLet's create an instance variable in the classint page
private int page;
Inside the method allFilmswe will assign the value of the parameter to this variable page:
this.page = page;
That. Every time this method is executed (i.e. when we navigate through pages), the value of the current page will be written to the variable. And then we use this value in our methods to redirect back to the same page.
modelAndView.setViewName("redirect:/?page=" + this.page);

Conclusion

We'll probably end here. The result is a full-fledged CRUD application. It is certainly far from ideal (very far), but it can be optimized and improved, bugs fixed and functionality added. You can use built-in methods for crud operations; add filtering, searching, sorting; add other related tables; implement support for different users with authorization and authentication, etc. and so on. The scope for imagination is limitless, so go for it. Link to github of this project . Thank you for your attention. PS This is my first attempt in my life to write an article, so don’t judge strictly :). I apologize for not adding any different links to useful resources; unfortunately, I still can’t develop the habit of saving links to the sources from which I get information. And, of course, I apologize for the many letters, brevity is not my talent, I hope someone can handle this. Links to all parts
Comments
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION