-
Notifications
You must be signed in to change notification settings - Fork 8
03 A Simple Library App
In this tutorial we will create a simple library application with the following functionality:
- Users can borrow books and and return them.
- Admins can add new books.
There is really just one class we need for this, a class to represent books. Before we create this class however, let's create a package for it. Currently, we have two packages:
edu.asu.diging.springaction.config
edu.asu.diging.springaction.web
Let's add a third one:
-
edu.asu.diging.springaction.core
This package will contain our core functionality like domain class and services. If you work on a DigInG project, this is the package structure for most of the newer projects.
In the core
package, let's create three more packages: data
, model.impl
and service.impl
. You know should have these packages:
edu.asu.diging.springaction.config
edu.asu.diging.springaction.core.data
edu.asu.diging.springaction.core.model.impl
edu.asu.diging.springaction.core.service.impl
edu.asu.diging.springaction.web
In edu.asu.diging.springaction.core.model.impl
add the following class:
package edu.asu.diging.springaction.core.model.impl;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
@Entity
public class BookImpl {
@Id
@GeneratedValue
private Long id;
private String title;
private String author;
private boolean available;
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 getAuthor() {
return author;
}
public void setAuthor(String author) {
this.author = author;
}
public boolean isAvailable() {
return available;
}
public void setAvailable(boolean available) {
this.available = available;
}
}
This class should be self-explanatory. The only thing that might be unfamiliar are the three annotations: @Entity
, @Id
, and @GeneratedValue
.
-
@Entity
: this tells Spring Data should objects of this class should be persistable to the database. -
@Id
: this tells Spring Data that the id (primary key) for an object should be stored in this property. -
@GeneratedValue
: we want ids to be automatically generated. You can read about the different strategies that can be specified here.
Now, create an interface for the class (called Book
) and move it into the parent package (edu.asu.diging.springaction.core.model
). Programming against interfaces lets you exchange specific implementations as required later on.
Since we're using Spring Data and Hibernate in the project, CRUD operations on the database are very easy implement. Simply add the following interface into edu.asu.diging.springaction.core.data
:
package edu.asu.diging.springaction.core.data;
import org.springframework.data.repository.PagingAndSortingRepository;
import edu.asu.diging.springaction.core.model.impl.BookImpl;
public interface BookRepository extends PagingAndSortingRepository<BookImpl, Long> {
}
Spring Data will automatically create an implementation for this interface that has default CRUD methods. You configure where Spring Data looks for repository interfaces to implement in our Spring Data configuration class (edu.asu.diging.springaction.config.PersistenceConfig
) in the annotation @EnableJpaRepositories
.
Now, all we need is a service class to handle any business logic we might need. Let's create a class BookManagerImpl
in edu.asu.diging.springaction.core.service.impl
.
package edu.asu.diging.springaction.core.service.impl;
import java.util.List;
import java.util.stream.Collectors;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.util.Streamable;
import org.springframework.stereotype.Service;
import edu.asu.diging.springaction.core.data.BookRepository;
import edu.asu.diging.springaction.core.model.Book;
@Service
public class BookManagerImpl {
@Autowired
private BookRepository bookRepo;
public List<Book> all() {
return Streamable.of(bookRepo.findAll()).stream().collect(Collectors.toList());
}
public Book store(String author, String title) {
Book book = new BookImpl();
book.setAuthor(author);
book.setTitle(title);
book.setAvailable(true);
return bookRepo.save((BookImpl)book);
}
}
This class has two annotation worth mentioning: @Service
and @Autowired
.
-
@Service
: this annotation tells Spring that it should manage this class. Spring will take care of instantiating it and managing its life cycle. -
@Autowired
: this annotation tells Spring that you want an instance of a managed class. In our case, Spring will give us an instance ofBookRepository
, which we can use to retrieve and store objects in the database. The code in theall
method simply retrieves all book objects and puts them in a list. This is necessary sincefindAll
returns anIterable<BookImpl>
, which we can't be sure will always be a list.
Similar to be before, extract an interface BookManager
and put it in the parent folder.
Eclipse makes it very easy to create interfaces for existing class. Just right-click on a class in the editor, then select "Refactor -> Extract interface...". Give the interface a name and select all method that should be part of the interface.
Digital Innovation Group @ ASU - DigInG Spring Training - © 2022