Java webapp with Stripes, MyBatis, & Derby

In this tutorial, we create a Java web application with Stripes, MyBatis, and Derby. We use NetBeans to build the application. Apache Tomcat is used as the JSP and servlet container. The project sources are available at the author's Github repository.

Stripes is an open source lightweight Java web application framework. The goal of Stripes is to make Servlet/JSP based web development in Java easy, intuitive, and straightforward. Stripes is an action based MVC (Model View Controller) framework. It runs in a JEE web container, uses minimum configuration files, and has a flexible and simple parameter binding.

MyBatis is a Java persistence framework that couples objects with stored procedures or SQL statements using an XML descriptor or annotations. Unlike ORM frameworks, MyBatis does not map Java objects to database tables but Java methods to SQL statements. MyBatis allows to use all database functionality like stored procedures, views, queries of any complexity and vendor proprietary features.

Derby is a relational database management system written in Java. Oracle distributes the same binaries under the name Java DB. Derby has a small footprint around 2MB. The database format used by Derby is portable and platform independent.

Books application

We create a new web application in NetBeans. In the application, we will be able to add new books to the database, select single books by their ID, and select all books in the table. The project needs Stripes, MyBatis, and JSTL libraries. The first three JARs are MyBatis libraries, the next three are Stripes' libraries. We must dowloand them from their project pages. The JSTL JARs are available with NebBeans.

Server and Settings
Figure: Project libraries

In the NetBeans Services tab, we expand the Databases node and right-click on the Java DB node and select Create Database option. The database name will be books, the user and password app and app.

books.sql
CREATE TABLE Books(Id INTEGER NOT NULL PRIMARY KEY GENERATED ALWAYS AS IDENTITY 
    (START WITH 1, INCREMENT BY 1), Author VARCHAR(30), Title VARCHAR(60), 
    Published INTEGER, Remark VARCHAR(150));
INSERT INTO Books(Author, Title, Published, Remark) VALUES ('Leo Tolstoy', 'War and Peace', 1869, 'Napoleonic wars');    
INSERT INTO Books(Author, Title, Published, Remark) VALUES ('Leo Tolstoy', 'Anna Karenina', 1878, 'Greatest book of love');
INSERT INTO Books(Author, Title, Published, Remark) VALUES ('Jeff Prosise', 'Programming Windows with MFC', 1999, 'Classic book about MFC');
INSERT INTO Books(Author, Title, Published, Remark) VALUES ('Tom Marrs', 'JBoss at Work', 2005, 'JBoss practical guide');
INSERT INTO Books(Author, Title, Published, Remark) VALUES ('Debu Panda', 'EJB3 in Action', 2007, 'Introduction to Enterprice Java Beans');

We create a new database connection to the created database and execute this SQL code. We have a Books table with a few books in it.

web.xml
<?xml version="1.0" encoding="UTF-8"?>

<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
         version="3.1">
    
    <filter>
        <display-name>Stripes Filter</display-name>
        <filter-name>StripesFilter</filter-name>
        <filter-class>net.sourceforge.stripes.controller.StripesFilter</filter-class>
        <init-param>
            <param-name>ActionResolver.Packages</param-name>
            <param-value>com.zetcode.action</param-value>
        </init-param>
    </filter>
 
    <filter-mapping>
        <filter-name>StripesFilter</filter-name>
        <url-pattern>*.jsp</url-pattern>
        <dispatcher>REQUEST</dispatcher>
    </filter-mapping>
 
    <filter-mapping>
        <filter-name>StripesFilter</filter-name>
        <servlet-name>StripesDispatcher</servlet-name>
        <dispatcher>REQUEST</dispatcher>
    </filter-mapping>
 
    <servlet>
        <servlet-name>StripesDispatcher</servlet-name>
        <servlet-class>net.sourceforge.stripes.controller.DispatcherServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>
 
    <servlet-mapping>
        <servlet-name>StripesDispatcher</servlet-name>
        <url-pattern>*.action</url-pattern>
    </servlet-mapping>    
    
    <welcome-file-list>
        <welcome-file>index.jsp</welcome-file>
    </welcome-file-list>
    
</web-app>

In the web.xml deployment descriptor, we set up the Stripes framework. The index.jsp file is the default home page file. In the com.zetcode.action we have our ActionBeans.

Resources

In the resources directory, we have three files. The resources directory is created by right-clicking on the project file and selecting Properties. In the sources category, we add a new source package folder.

Resources
Figure: Resources

The BookMapper.xml and mybatis-config.xml are XML files used by MyBatis. The StripesResources.properties is the default resource bundle file for the Stripes framework. It contains error messages and labels for the application. It is available in the lib subdirectory of the Stripes download file.

Presentation layer

The presentation layer consists of six JSP pages. The index.jsp is the default home page of the application. The addBook.jsp is a page to add a new book to the database and the findBook.jsp is a page to find a book by its ID. The bookAdded.jsp shows a message after a book was successfully inserted into the database, the showOneBook.jsp displays the selected book, and the showAllBooks.jsp displays all books from the database.

index.jsp
<%@taglib prefix="stripes" uri="http://stripes.sourceforge.net/stripes.tld"%>
<%@page contentType="text/html" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <title>Welcome page</title>
    </head>
    <body>

        <stripes:link href="addBook.jsp">
            Add a new book
        </stripes:link>      
            
        <stripes:link href="findBook.jsp">
            Find one book
        </stripes:link>                  
            
        <stripes:link beanclass="com.zetcode.action.SelectAllBooksActionBean">
            Show all books
        </stripes:link>    
            
    </body>
</html>

The index.jsp contains Stripes links to two JSP pages to add a new book and find a book and a link to an ActionBean to show all books. The <%@taglib prefix="stripes" uri="http://stripes.sourceforge.net/stripes.tld"%> declares the tags used by Stripes, including <stripes:link>.

findBook.jsp
<%@taglib prefix="stripes" uri="http://stripes.sourceforge.net/stripes.tld"%>
<%@page contentType="text/html" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <title>Find a book</title>
    </head>
    <body>
      <stripes:form beanclass="com.zetcode.action.SelectOneBookActionBean">
            <stripes:errors/>
                Book ID:
                <stripes:text name="bookId"/><br>
                <stripes:submit name="save" value="Submit"/>
        </stripes:form>    
    </body>
</html>

In the findBook.jsp we have a form to find a book by its ID. The form consists of a text field and a Submit button. The inserted value is validated; if the user adds an invalid value, the application returns an error message.

addBook.jsp
<%@taglib prefix="stripes" uri="http://stripes.sourceforge.net/stripes.tld"%>
<%@page contentType="text/html" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <title>Add new book</title>
    </head>
    <body>
        
        <stripes:form beanclass="com.zetcode.action.AddBookActionBean">
            <stripes:errors/>
                Author:
                <stripes:text name="author"/><br>
                
                Title:
                <stripes:text name="title"/><br>                
                
                Year of publishing:
                <stripes:text name="published"/><br>
                
                Remark
                <stripes:text name="remark"/><br>                
                
                <stripes:submit name="save" value="Submit"/>
        </stripes:form>        
        
    </body>
</html>

The addBook.jsp adds a new book to the database. It contains a form with four text fields for the book object. The ID is auto-generated by Derby database.

bookAdded.jsp
<%@page contentType="text/html" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <title>Book added</title>
    </head>
    <body>
        <h3>Book added to database</h3>
    </body>
</html>

When a new book is added to the database, the application returns bookAdded.jsp, which contains a simple message.

showAllBooks.jsp
<%@page contentType="text/html" pageEncoding="UTF-8"%>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html>
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <title>Show all books</title>
    </head>
    <body>
        <h3>All books</h3>
        
        <table>
            <thead>
                <tr>
                    <th>Id</th>
                    <th>Author</th>
                    <th>Title</th>
                    <th>Published</th>
                    <th>Remark</th>
                </tr>
            </thead>
            
            <c:forEach items="${actionBean.books}" var='book'>
                <tr>
                    <td>
                        <c:out value="${book.id}"/>
                    </td>
                    <td>
                        <c:out value="${book.author}"/>
                    </td>
                    <td>
                        <c:out value="${book.title}"/>
                    </td>        
                    <td>
                        <c:out value="${book.published}"/>
                    </td>  
                    <td>
                        <c:out value="${book.remark}"/>
                    </td>                      
                </tr>
            </c:forEach>          

        </table>
    </body>
</html>

The showAllBooks.jsp displays all books retrieved from the database. The <%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> directive declares the JSTL core tags, including <c:forEach> and <c:out>. The returned data can be accessed with the ${actionBean} expression, where actionBean is the action bean that forwarded the view (i.e. this JSP page). In this case, the action bean is SelectAllBooksActionBean.

showOneBook.jsp
<%@page contentType="text/html" pageEncoding="UTF-8"%>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html>
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <title>Show one book</title>
    </head>
    <body>
        <h3>A book</h3>

        <table>
            <thead>
                <tr>
                    <th>Id</th>
                    <th>Author</th>
                    <th>Title</th>
                    <th>Published</th>
                    <th>Remark</th>
                </tr>
            </thead>

            <tr>
                <td>
                    <c:out value="${actionBean.book.id}"/>
                </td>
                <td>
                    <c:out value="${actionBean.book.author}"/>
                </td>
                <td>
                    <c:out value="${actionBean.book.title}"/>
                </td>        
                <td>
                    <c:out value="${actionBean.book.published}"/>
                </td>  
                <td>
                    <c:out value="${actionBean.book.remark}"/>
                </td>                      
            </tr>

        </table>
    </body>
</html>

The showOneBook.jsp displays one book, which we have found by its ID.

The Book bean

The Book bean is a Java class that represents a domain object of our application—a book.

Book.java
package com.zetcode.bean;

public class Book {

    private Long id;

    private String author;
    private String title;
    private int yearPublished;
    private String remark;
    
    public Book() {};

    public Book(String author, String title, int published, 
            String remark) {
        
        this.author = author;
        this.title = title;
        this.yearPublished = published;
        this.remark = remark;
    }

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getAuthor() {
        return author;
    }

    public void setAuthor(String author) {
        this.author = author;
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public int getPublished() {
        return yearPublished;
    }

    public void setPublished(int published) {
        this.yearPublished = published;
    }

    public String getRemark() {
        return remark;
    }

    public void setRemark(String remark) {
        this.remark = remark;
    }
}

The bean has the necessary attributes and getter and setter methods. Note that it is also necessary to add an empty constructor.

Action beans

Stripes' ActionBean is an object that receives data submitted in requests and processes the user's input. It both defines the properties of the form and the processing logic for the form. In the end it returns a view to the user. In our application, we have three action beans: AddBookActionBean, SelectAllBooksActionBean, and SelectOneBookActionBean. Each of them represents some action to be taken in the application.

Action beans
Figure: Action beans

We place the action beans into the com.zetcode.action package.

AddBookActionBean.java
package com.zetcode.action;

import com.zetcode.bean.Book;
import com.zetcode.service.BookService;
import net.sourceforge.stripes.action.ActionBean;
import net.sourceforge.stripes.action.ActionBeanContext;
import net.sourceforge.stripes.action.DefaultHandler;
import net.sourceforge.stripes.action.ForwardResolution;
import net.sourceforge.stripes.action.Resolution;
import net.sourceforge.stripes.validation.Validate;

public class AddBookActionBean implements ActionBean {

    private static final String VIEW = "/bookAdded.jsp";
    private ActionBeanContext context;

    @Validate(required = true)
    private String author;

    @Validate(required = true)
    private String title;

    @Validate(required = true)
    private int yearPublished;

    @Validate(required = true)
    private String remark;

    public String getAuthor() {
        return author;
    }

    public void setAuthor(String author) {
        this.author = author;
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public int getYearPublished() {
        return yearPublished;
    }

    public void setYearPublished(int yearPublished) {
        this.yearPublished = yearPublished;
    }

    public String getRemark() {
        return remark;
    }

    public void setRemark(String remark) {
        this.remark = remark;
    }

    @DefaultHandler
    public Resolution addBook() {

        Book book = new Book(this.author, this.title,
                this.yearPublished, this.remark);
        BookService.saveBook(book);

        return new ForwardResolution(VIEW);
    }

    @Override
    public void setContext(ActionBeanContext context) {

        this.context = context;
    }

    @Override
    public ActionBeanContext getContext() {

        return context;
    }
}

The AddBookActionBean is called after we have filled in the form to add a new book. The action bean automatically binds the request attributes to its own attributes.

private static final String VIEW = "/bookAdded.jsp";

The AddBookActionBean returns bookAdded.jsp page when the book is successfully saved to the database.

@Validate(required=true)
private String author;

@Validate(required=true)
private String title;
...

With the @Validate annotation, we provide validation services to our HTML fields. The fields must not be empty and must match the correct data type.

Validation
Figure: Validation

The Submit action fails if the year of publishing has a non-integer character.

@DefaultHandler
public Resolution addBook() {
    
    Book book = new Book(this.author, this.title, 
            this.yearPublished, this.remark);
    BookService.saveBook(book);

    return new ForwardResolution(VIEW);
}

The @DefaultHandler annotation specifies the default handler method for this action bean. (It is possible to define several handlers.) The handler creates the Book bean, calls the BookService.saveBook() and forwards to the appropriate view.

SelectOneBookActionBean.java
package com.zetcode.action;

import com.zetcode.bean.Book;
import com.zetcode.service.BookService;
import java.io.IOException;
import net.sourceforge.stripes.action.ActionBean;
import net.sourceforge.stripes.action.ActionBeanContext;
import net.sourceforge.stripes.action.DefaultHandler;
import net.sourceforge.stripes.action.ForwardResolution;
import net.sourceforge.stripes.action.Resolution;
import net.sourceforge.stripes.validation.Validate;

public class SelectOneBookActionBean implements ActionBean {
    
    private static final String VIEW = "/showOneBook.jsp";
    private ActionBeanContext context;    
    
    private Book book;
    
    @Validate(required=true)
    private Long bookId;

    public Book getBook() {
        return book;
    }

    public void setBook(Book book) {
        this.book = book;
    }

    public Long getBookId() {
        return bookId;
    }

    public void setBookId(Long bookId) {
        this.bookId = bookId;
    }
    
    @DefaultHandler
    public Resolution showOneBook() throws IOException {
        
        this.book = BookService.getBook(bookId);

        return new ForwardResolution(VIEW);
    }

    @Override
    public void setContext(ActionBeanContext context) {

        this.context = context;
    }

    @Override
    public ActionBeanContext getContext() {
        
        return context;
    }
}

The SelectOneBookActionBean is called after we have clicked on the Submit button in the findBook.jsp.

@DefaultHandler
public Resolution showOneBook() throws IOException {
    
    this.book = BookService.getBook(bookId);

    return new ForwardResolution(VIEW);
}

The default handler calls the BookService.getBook() method and forwards then to the view.

SelectAllBooksActionBean.java
package com.zetcode.action;

import com.zetcode.bean.Book;
import com.zetcode.service.BookService;
import java.util.List;
import net.sourceforge.stripes.action.ActionBean;
import net.sourceforge.stripes.action.ActionBeanContext;
import net.sourceforge.stripes.action.DefaultHandler;
import net.sourceforge.stripes.action.ForwardResolution;
import net.sourceforge.stripes.action.Resolution;


public class SelectAllBooksActionBean implements ActionBean {
    
    private static final String VIEW = "/showAllBooks.jsp";
    private ActionBeanContext context;    
    private List<Book> books;

    public List<Book> getBooks() {
        return books;
    }

    public void setBooks(List<Book> books) {
        this.books = books;
    }

    @DefaultHandler
    public Resolution showAll() {
        
        this.books = BookService.getAllBooks();

        return new ForwardResolution(VIEW);
    }

    @Override
    public void setContext(ActionBeanContext context) {

        this.context = context;
    }

    @Override
    public ActionBeanContext getContext() {
        
        return context;
    }
}

The SelectAllBooksActionBean is responsible for selecting all books from the database.

@DefaultHandler
public Resolution showAll() {
    
    this.books = BookService.getAllBooks();

    return new ForwardResolution(VIEW);
}

The BookService.getAllBooks() is called to do the job.

Services

The BookService contains method to communicate with the database.

BookService.java
package com.zetcode.service;

import com.zetcode.bean.Book;
import com.zetcode.persistence.MyBatisDAO;
import java.util.List;

public class BookService {

    public static void saveBook(Book book) {
        
        MyBatisDAO mbd = new MyBatisDAO();
        mbd.saveBook(book);
    }
    
    public static List<Book> getAllBooks() {
        
        MyBatisDAO mbd = new MyBatisDAO();
        List<Book> books = mbd.findAll();
        
        return books;
    }
    
    public static Book getBook(Long id) {

        MyBatisDAO mbd = new MyBatisDAO();
        Book book = mbd.findBook(id);

        return book;
    }    
}

The DAO pattern is used to make the example more portable.

public static List<Book> getAllBooks() {
    
    MyBatisDAO mbd = new MyBatisDAO();
    List<Book> books = mbd.findAll();
    
    return books;
}

The getAllBooks() method creates the MyBatisDAO and calls its findAll() method. It returns a list of retrieved books.

DAO

The Data Access Object (DAO) pattern is used to separate low level data accessing API or operations from high level business services.

BookDAO.java
package com.zetcode.persistence;

import com.zetcode.bean.Book;
import java.util.List;

public interface BookDAO {

  public void saveBook(Book book);
  public Book findBook(Long id);
  public List<Book> findAll();
}

The methods to access the data are defined in the BookDAO interface. The code is less coupled when we program against this interface.

MyBatisDAO.java
package com.zetcode.persistence;

import com.zetcode.bean.Book;
import com.zetcode.util.ServiceLocator;
import java.util.List;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;

public class MyBatisDAO implements BookDAO {

    @Override
    public void saveBook(Book book) {
        
        SqlSession session = null;
        
        try {
            SqlSessionFactory factory = ServiceLocator.getSessionFactory();
            session = factory.openSession();
            session.insert("insertBook", book);
            session.commit();
            
        } finally {
            
            if (session != null) {
                session.close();
            }
        }        
    }

    @Override
    public Book findBook(Long id) {
        
        SqlSession session = null;
        Book book = null;
        
        try {
            SqlSessionFactory factory = ServiceLocator.getSessionFactory();
            session = factory.openSession();
            book = session.selectOne("selectBook", id);
            
        } finally {
            
            if (session != null) {
                session.close();
            }
        }

        return book;        
    }

    @Override
    public List<Book> findAll() {

        SqlSession session = null;
        List<Book> retrieveList = null;

        try {
            SqlSessionFactory factory = ServiceLocator.getSessionFactory();
            session = factory.openSession();
            retrieveList = session.selectList("selectAllBooks");
            
        } finally {
            
            if (session != null) {
                session.close();
            }
        }

        return retrieveList;
    }
}

The MyBatisDAO is a concrete implementation of the BookDAO interface. If the underlying data source changes, we can easily switch to a new DAO implementation.

@Override
public void saveBook(Book book) {
    
    SqlSession session = null;
    
    try {
        SqlSessionFactory factory = ServiceLocator.getSessionFactory();
        session = factory.openSession();
        session.insert("insertBook", book);
        session.commit();
        
    } finally {
        
        if (session != null) {
            session.close();
        }
    }        
}

The saveBook() method saves a new book into the database. An SqlSessionFactory is created to produce an SqlSession, which is the primary Java interface for working with MyBatis. The creation of the factory is delegated to the ServiceLocator. The session's insert() method executes an insert statement with the given parameter object. The commit() method commits the changes to the database.

SqlSessionFactory factory = ServiceLocator.getSessionFactory();
session = factory.openSession();
book = session.selectOne("selectBook", id);

For the selection of a single book, we pass the id parameter to the session's selectOne() method.

SqlSessionFactory factory = ServiceLocator.getSessionFactory();
session = factory.openSession();
retrieveList = session.selectList("selectAllBooks");

The selectList() method returns a list of book objects.

ServiceLocator.java
package com.zetcode.util;

import java.io.IOException;
import java.io.InputStream;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

public class ServiceLocator {

    public static SqlSessionFactory getSessionFactory() {

        InputStream inputStream = null;
        SqlSessionFactory sqlSessionFactory = null;

        try {
            String resource = "mybatis-config.xml";
            inputStream = Resources.getResourceAsStream(resource);
            sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);

        } catch (IOException ex) {
            Logger.getLogger(ServiceLocator.class.getName()).log(Level.SEVERE, null, ex);
        } finally {
            try {
                if (inputStream != null) {
                    inputStream.close();
                }
            } catch (IOException ex) {
                Logger.getLogger(ServiceLocator.class.getName()).log(Level.WARNING, null, ex);
            }
        }

        return sqlSessionFactory;
    }
}

The ServiceLocator builds the SqlSessionFactory from the supplied configuration file. The factory is later used to produce an SqlSession, which is the primary interface to communicate with MyBatis.

mybatis-config.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration
  PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
  "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
  
    <typeAliases>
        <typeAlias alias="Book" type="com.zetcode.bean.Book"/>  
    </typeAliases>  
     
    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="org.apache.derby.jdbc.ClientDriver"/>
                <property name="url" value="jdbc:derby://localhost:1527/books"/>
                <property name="username" value="app"/>
                <property name="password" value="app"/>
            </dataSource>
        </environment>
    </environments>
    <mappers>
        <mapper resource="BookMapper.xml"/>
    </mappers>
</configuration>

In the mybatis-config.xml file, we create a new book Book type, define the data source for Derby, and specify the mapper file.

BookMapper.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
  PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
  "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
  
<mapper namespace="com.zetcode">
    
    <select id="selectAllBooks" resultType="Book">
        SELECT * FROM Books
    </select>
    
    <select id="selectBook" parameterType="long" resultType="Book">
        SELECT * FROM Books WHERE Id = #{id}
    </select>    
    
    <insert id="insertBook" parameterType="Book" statementType="PREPARED">
        INSERT INTO Books(Author, Title, Published, Remark) VALUES 
        (#{author}, #{title}, #{published}, #{remark})
    </insert>

</mapper>

In the BookMapper.xml we have the SQL commands used in our application. It has two select and one insert commands.

<select id="selectAllBooks" resultType="Book">
    SELECT * FROM Books
</select>

Notice that for the result type, we do not define a collection but the type of the collection items.

Displaying all books
Figure: Displaying all books

The screenshot shows all books selected from a sample database.

In this tutorial, we have created a web application with Stripes, MyBatis, and Derby. We have used a three layer and DAO software patterns. NetBeans was used to build the application. ZetCode has the following related tutorials: Derby tutorial, Java tutorial, Stripes tutorial, and Introduction to EJBs.