Spring专题

GWT 2 Spring 3 JPA 2 Hibernate 3.5源码下载

GWT 2 Spring 3 JPA 2 Hibernate 3.5源码下载

展示使用谷歌的Web工具包(GWT)的丰富的客户端结合Spring如何开发一个简单的Web应用程序,主要是CRUD(创建,检索,更新,删除)操作数据库。

  1. Eclipse 下载: here
  2. GWT Plugin for Eclipse 下载: here
  3. Spring 下载: here
  4. Hibernate 下载: here
  5. Hypersonic 下载: here
  6. Apache commons-logging 下载: here
  7. AOP Alliance 下载: here
  8. SLF4J 下载: here
  9. Apache log4j下载: here
  10. download the GWT – Spring “glue” library spring4gwt from here

实体对象代码:

package com.javacodegeeks.gwtspring.shared.dto;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;

@Entity
@Table(name = "EMPLOYEE")
public class EmployeeDTO implements java.io.Serializable {
   
    private static final long serialVersionUID = 7440297955003302414L;

    @Id
    @Column(name="employee_id")
    private long employeeId;
   
    @Column(name="employee_name", nullable = false, length=30)
    private String employeeName;
   
    @Column(name="employee_surname", nullable = false, length=30)
    private String employeeSurname;
   
    @Column(name="job", length=50)
    private String job;
       
    public EmployeeDTO() {
    }

    public EmployeeDTO(int employeeId) {
        this.employeeId = employeeId;       
    }

    public EmployeeDTO(long employeeId, String employeeName, String employeeSurname,
            String job) {
        this.employeeId = employeeId;
        this.employeeName = employeeName;
        this.employeeSurname = employeeSurname;
        this.job = job;
    }

    public long getEmployeeId() {
        return employeeId;
    }

    public void setEmployeeId(long employeeId) {
        this.employeeId = employeeId;
    }

    public String getEmployeeName() {
        return employeeName;
    }

    public void setEmployeeName(String employeeName) {
        this.employeeName = employeeName;
    }

    public String getEmployeeSurname() {
        return employeeSurname;
    }

    public void setEmployeeSurname(String employeeSurname) {
        this.employeeSurname = employeeSurname;
    }

    public String getJob() {
        return job;
    }

    public void setJob(String job) {
        this.job = job;
    }

}

Spring配置:

<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
    xmlns:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context"
    xmlns:jee="http://www.springframework.org/schema/jee" xmlns:tx="http://www.springframework.org/schema/tx"
    xmlns:task="http://www.springframework.org/schema/task"
    xsi:schemaLocation="
            http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
            http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
            http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd
            http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.0.xsd
            http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
            http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-3.0.xsd">

    <context:component-scan base-package="com.javacodegeeks.gwtspring"/>

    <task:annotation-driven executor="myExecutor" scheduler="myScheduler"/>

    <task:executor id="myExecutor" pool-size="5"/>

    <task:scheduler id="myScheduler" pool-size="10"/>

    <tx:annotation-driven/>

    <bean class="org.springframework.orm.jpa.LocalEntityManagerFactoryBean" id="entityManagerFactory">
        <property name="persistenceUnitName" value="MyPersistenceUnit"/>
    </bean>

    <bean class="org.springframework.orm.jpa.JpaTransactionManager" id="transactionManager">
        <property name="entityManagerFactory" ref="entityManagerFactory"/>
    </bean>

</beans>

Hibernate配置 /resources/META-INF/persistence.xml :

<persistence xmlns="http://java.sun.com/xml/ns/persistence"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd"
    version="2.0">

    <persistence-unit name="MyPersistenceUnit" transaction-type="RESOURCE_LOCAL">
        <provider>org.hibernate.ejb.HibernatePersistence</provider>

        <properties>
            <property name="hibernate.hbm2ddl.auto" value="update"/>
            <property name="hibernate.show_sql" value="false"/>
            <property name="hibernate.dialect" value="org.hibernate.dialect.HSQLDialect"/>
            <property name="hibernate.connection.driver_class" value="org.hsqldb.jdbcDriver"/>
            <property name="hibernate.connection.url" value="jdbc:hsqldb:mem:javacodegeeks"/>
            <property name="hibernate.connection.username" value="sa"/>
            <property name="hibernate.connection.password" value=""/>

            <property name="hibernate.c3p0.min_size" value="5"/>
            <property name="hibernate.c3p0.max_size" value="20"/>
            <property name="hibernate.c3p0.timeout" value="300"/>
            <property name="hibernate.c3p0.max_statements" value="50"/>
            <property name="hibernate.c3p0.idle_test_period" value="3000"/>
        </properties>

    </persistence-unit>

</persistence>

 

DAO通用接口:

package com.javacodegeeks.gwtspring.server.dao;

import java.lang.reflect.ParameterizedType;
import java.util.List;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceException;
import javax.persistence.Query;

import org.springframework.orm.jpa.JpaCallback;
import org.springframework.orm.jpa.support.JpaDaoSupport;

public abstract class JpaDAO<K, E> extends JpaDaoSupport {
    protected Class<E> entityClass;

    @SuppressWarnings("unchecked")
    public JpaDAO() {
        ParameterizedType genericSuperclass = (ParameterizedType) getClass()
                .getGenericSuperclass();
        this.entityClass = (Class<E>) genericSuperclass
                .getActualTypeArguments()[1];
    }

    public void persist(E entity) {
        getJpaTemplate().persist(entity);
    }

    public void remove(E entity) {
        getJpaTemplate().remove(entity);
    }
   
    public E merge(E entity) {
        return getJpaTemplate().merge(entity);
    }
   
    public void refresh(E entity) {
        getJpaTemplate().refresh(entity);
    }

    public E findById(K id) {
        return getJpaTemplate().find(entityClass, id);
    }
   
    public E flush(E entity) {
        getJpaTemplate().flush();
        return entity;
    }
   
    @SuppressWarnings("unchecked")
    public List<E> findAll() {
        Object res = getJpaTemplate().execute(new JpaCallback() {

            public Object doInJpa(EntityManager em) throws PersistenceException {
                Query q = em.createQuery("SELECT h FROM " +
                        entityClass.getName() + " h");
                return q.getResultList();
            }
           
        });
       
        return (List<E>) res;
    }

    @SuppressWarnings("unchecked")
    public Integer removeAll() {
        return (Integer) getJpaTemplate().execute(new JpaCallback() {

            public Object doInJpa(EntityManager em) throws PersistenceException {
                Query q = em.createQuery("DELETE FROM " +
                        entityClass.getName() + " h");
                return q.executeUpdate();
            }
           
        });
    }
   
}

服务代码:

package com.javacodegeeks.gwtspring.server.services;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import com.javacodegeeks.gwtspring.server.dao.EmployeeDAO;
import com.javacodegeeks.gwtspring.shared.dto.EmployeeDTO;
import com.javacodegeeks.gwtspring.shared.services.EmployeeService;

@Service("employeeService")
public class EmployeeServiceImpl implements EmployeeService {
   
    @Autowired
    private EmployeeDAO employeeDAO;

    @PostConstruct
    public void init() throws Exception {
    }
   
    @PreDestroy
    public void destroy() {
    }

    public EmployeeDTO findEmployee(long employeeId) {
       
        return employeeDAO.findById(employeeId);
       
    }
   
    @Transactional(propagation=Propagation.REQUIRED, rollbackFor=Exception.class)
    public void saveEmployee(long employeeId, String name, String surname, String jobDescription) throws Exception {
           
        EmployeeDTO employeeDTO = employeeDAO.findById(employeeId);
       
        if(employeeDTO == null) {
            employeeDTO = new EmployeeDTO(employeeId, name,surname, jobDescription);
            employeeDAO.persist(employeeDTO);
        }
       
    }
   
    @Transactional(propagation=Propagation.REQUIRED, rollbackFor=Exception.class)
    public void updateEmployee(long employeeId, String name, String surname, String jobDescription) throws Exception {
       
        EmployeeDTO employeeDTO = employeeDAO.findById(employeeId);
       
        if(employeeDTO != null) {
            employeeDTO.setEmployeeName(name);
            employeeDTO.setEmployeeSurname(surname);
            employeeDTO.setJob(jobDescription);
        }

    }
   
    @Transactional(propagation=Propagation.REQUIRED, rollbackFor=Exception.class)
    public void deleteEmployee(long employeeId) throws Exception {
       
        EmployeeDTO employeeDTO = employeeDAO.findById(employeeId);
       
        if(employeeDTO != null)
            employeeDAO.remove(employeeDTO);

    }
   
    @Transactional(propagation=Propagation.REQUIRED, rollbackFor=Exception.class)
    public void saveOrUpdateEmployee(long employeeId, String name, String surname, String jobDescription) throws Exception {
       
        EmployeeDTO employeeDTO = new EmployeeDTO(employeeId, name,surname, jobDescription);
       
        employeeDAO.merge(employeeDTO);
       
    }

}

下面是GWTSpring 代码:

import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.core.client.GWT;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.dom.client.KeyCodes;
import com.google.gwt.event.dom.client.KeyUpEvent;
import com.google.gwt.event.dom.client.KeyUpHandler;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.DialogBox;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.RootPanel;
import com.google.gwt.user.client.ui.TextBox;
import com.google.gwt.user.client.ui.VerticalPanel;
import com.javacodegeeks.gwtspring.shared.dto.EmployeeDTO;
import com.javacodegeeks.gwtspring.shared.services.EmployeeService;
import com.javacodegeeks.gwtspring.shared.services.EmployeeServiceAsync;

/**
 * Entry point classes define <code>onModuleLoad()</code>.
 */
public class GWTSpring implements EntryPoint {
    /**
     * The message displayed to the user when the server cannot be reached or
     * returns an error.
     */
    private static final String SERVER_ERROR = "An error occurred while "
            + "attempting to contact the server. Please check your network "
            + "connection and try again. The error is : ";
   
    /**
     * Create a remote service proxy to talk to the server-side Employee service.
     */
    private final EmployeeServiceAsync employeeService = GWT
            .create(EmployeeService.class);

    /**
     * This is the entry point method.
     */
    public void onModuleLoad() {
        final Button saveOrUpdateButton = new Button("SaveOrUpdate");
        final Button retrieveButton = new Button("Retrieve");
        final TextBox employeeInfoField = new TextBox();
        employeeInfoField.setText("Employee Info");
        final TextBox employeeIdField = new TextBox();
        final Label errorLabel = new Label();

        // We can add style names to widgets
        saveOrUpdateButton.addStyleName("sendButton");
        retrieveButton.addStyleName("sendButton");

        // Add the nameField and sendButton to the RootPanel
        // Use RootPanel.get() to get the entire body element
        RootPanel.get("employeeInfoFieldContainer").add(employeeInfoField);
        RootPanel.get("updateEmployeeButtonContainer").add(saveOrUpdateButton);
        RootPanel.get("employeeIdFieldContainer").add(employeeIdField);
        RootPanel.get("retrieveEmployeeButtonContainer").add(retrieveButton);
        RootPanel.get("errorLabelContainer").add(errorLabel);

        // Focus the cursor on the name field when the app loads
        employeeInfoField.setFocus(true);
        employeeInfoField.selectAll();

        // Create the popup dialog box
        final DialogBox dialogBox = new DialogBox();
        dialogBox.setText("Remote Procedure Call");
        dialogBox.setAnimationEnabled(true);
        final Button closeButton = new Button("Close");
        // We can set the id of a widget by accessing its Element
        closeButton.getElement().setId("closeButton");
        final Label textToServerLabel = new Label();
        final HTML serverResponseLabel = new HTML();
        VerticalPanel dialogVPanel = new VerticalPanel();
        dialogVPanel.addStyleName("dialogVPanel");
        dialogVPanel.add(new HTML("<b>Sending request to the server:</b>"));
        dialogVPanel.add(textToServerLabel);
        dialogVPanel.add(new HTML("
<b>Server replies:</b>"));
        dialogVPanel.add(serverResponseLabel);
        dialogVPanel.setHorizontalAlignment(VerticalPanel.ALIGN_RIGHT);
        dialogVPanel.add(closeButton);
        dialogBox.setWidget(dialogVPanel);

        // Add a handler to close the DialogBox
        closeButton.addClickHandler(new ClickHandler() {
            public void onClick(ClickEvent event) {
                dialogBox.hide();
                saveOrUpdateButton.setEnabled(true);
                saveOrUpdateButton.setFocus(true);
                retrieveButton.setEnabled(true);
            }
        });

        // Create a handler for the saveOrUpdateButton and employeeInfoField
        class SaveOrUpdateEmployeeHandler implements ClickHandler, KeyUpHandler {
            /**
             * Fired when the user clicks on the saveOrUpdateButton.
             */
            public void onClick(ClickEvent event) {
                sendEmployeeInfoToServer();
            }

            /**
             * Fired when the user types in the employeeInfoField.
             */
            public void onKeyUp(KeyUpEvent event) {
                if (event.getNativeKeyCode() == KeyCodes.KEY_ENTER) {
                    sendEmployeeInfoToServer();
                }
            }

            /**
             * Send the employee info from the employeeInfoField to the server and wait for a response.
             */
            private void sendEmployeeInfoToServer() {
                // First, we validate the input.
                errorLabel.setText("");
                String textToServer = employeeInfoField.getText();

                // Then, we send the input to the server.
                saveOrUpdateButton.setEnabled(false);
                textToServerLabel.setText(textToServer);
                serverResponseLabel.setText("");

                String[] employeeInfo = textToServer.split(" ");
               
                long employeeId = Long.parseLong(employeeInfo[0]);
                String employeeName = employeeInfo[1];
                String employeeSurname = employeeInfo[2];
                String employeeJobTitle = employeeInfo[3];
               
                employeeService.saveOrUpdateEmployee(employeeId, employeeName, employeeSurname, employeeJobTitle,
                        new AsyncCallback<Void>() {
                            public void onFailure(Throwable caught) {
                                // Show the RPC error message to the user
                                dialogBox
                                        .setText("Remote Procedure Call - Failure");
                                serverResponseLabel
                                        .addStyleName("serverResponseLabelError");
                                serverResponseLabel.setHTML(SERVER_ERROR + caught.toString());
                                dialogBox.center();
                                closeButton.setFocus(true);
                            }

                            public void onSuccess(Void noAnswer) {
                                dialogBox.setText("Remote Procedure Call");
                                serverResponseLabel
                                        .removeStyleName("serverResponseLabelError");
                                serverResponseLabel.setHTML("OK");
                                dialogBox.center();
                                closeButton.setFocus(true);
                            }
                        });
            }
        }
       
        // Create a handler for the retrieveButton and employeeIdField
        class RetrieveEmployeeHandler implements ClickHandler, KeyUpHandler {
            /**
             * Fired when the user clicks on the retrieveButton.
             */
            public void onClick(ClickEvent event) {
                sendEmployeeIdToServer();
            }

            /**
             * Fired when the user types in the employeeIdField.
             */
            public void onKeyUp(KeyUpEvent event) {
                if (event.getNativeKeyCode() == KeyCodes.KEY_ENTER) {
                    sendEmployeeIdToServer();
                }
            }

            /**
             * Send the id from the employeeIdField to the server and wait for a response.
             */
            private void sendEmployeeIdToServer() {
                // First, we validate the input.
                errorLabel.setText("");
                String textToServer = employeeIdField.getText();

                // Then, we send the input to the server.
                retrieveButton.setEnabled(false);
                textToServerLabel.setText(textToServer);
                serverResponseLabel.setText("");

                employeeService.findEmployee(Long.parseLong(textToServer), 
                        new AsyncCallback<EmployeeDTO>() {
                            public void onFailure(Throwable caught) {
                                // Show the RPC error message to the user
                                dialogBox
                                        .setText("Remote Procedure Call - Failure");
                                serverResponseLabel
                                        .addStyleName("serverResponseLabelError");
                                serverResponseLabel.setHTML(SERVER_ERROR + caught.toString());
                                dialogBox.center();
                                closeButton.setFocus(true);
                            }

                            public void onSuccess(EmployeeDTO employeeDTO) {
                                dialogBox.setText("Remote Procedure Call");
                                serverResponseLabel
                                        .removeStyleName("serverResponseLabelError");
                                if(employeeDTO != null)
                                    serverResponseLabel.setHTML("Employee Information Id : " + employeeDTO.getEmployeeId() + " Name : " + employeeDTO.getEmployeeName() + " Surname : " + employeeDTO.getEmployeeSurname() + " Job Title : " + employeeDTO.getJob());
                                else
                                    serverResponseLabel.setHTML("No employee with the specified id found");
                                dialogBox.center();
                                closeButton.setFocus(true);
                            }
                        });
            }
        }

        // Add a handler to send the employee info to the server
        SaveOrUpdateEmployeeHandler saveOrUpdateEmployeehandler = new SaveOrUpdateEmployeeHandler();
        saveOrUpdateButton.addClickHandler(saveOrUpdateEmployeehandler);
        employeeInfoField.addKeyUpHandler(saveOrUpdateEmployeehandler);
       
        // Add a handler to send the employee id to the server
        RetrieveEmployeeHandler retrieveEmployeehandler = new RetrieveEmployeeHandler();
        retrieveButton.addClickHandler(retrieveEmployeehandler);
        employeeIdField.addKeyUpHandler(retrieveEmployeehandler);
    }
}

相应的Html:

<!doctype html>
<!-- The DOCTYPE declaration above will set the    -->
<!-- browser's rendering engine into               -->
<!-- "Standards Mode". Replacing this declaration  -->
<!-- with a "Quirks Mode" doctype may lead to some -->
<!-- differences in layout.                        -->

<html>
  <head>
    <meta http-equiv="content-type" content="text/html; charset=UTF-8">

    <!--                                                               -->
    <!-- Consider inlining CSS to reduce the number of requested files -->
    <!--                                                               -->
    <link type="text/css" rel="stylesheet" href="GWTSpring.css">

    <!--                                           -->
    <!-- Any title is fine                         -->
    <!--                                           -->
    <title>Spring GWT Web Application Starter Project</title>
   
    <!--                                           -->
    <!-- This script loads your compiled module.   -->
    <!-- If you add any GWT meta tags, they must   -->
    <!-- be added before this line.                -->
    <!--                                           -->
    <script type="text/javascript" language="javascript" src="gwtspring/gwtspring.nocache.js"></script>
  </head>

  <!--                                           -->
  <!-- The body can have arbitrary html, or      -->
  <!-- you can leave the body empty if you want  -->
  <!-- to create a completely dynamic UI.        -->
  <!--                                           -->
  <body>

    <!-- OPTIONAL: include this if you want history support -->
    <iframe src="javascript:''" id="__gwt_historyFrame" tabIndex='-1' style="position:absolute;width:0;height:0;border:0"></iframe>
   
    <!-- RECOMMENDED if your web app will not function without JavaScript enabled -->
    <noscript>
      <div style="width: 22em; position: absolute; left: 50%; margin-left: -11em; color: red; background-color: white; border: 1px solid red; padding: 4px; font-family: sans-serif">
        Your web browser must have JavaScript enabled
        in order for this application to display correctly.
      </div>
    </noscript>

    <h1>Spring GWT Web Application Starter Project</h1>

    <table align="center">
      <tr>
        <td colspan="2" style="font-weight:bold;">Please enter employee info (id name surname job):</td>       
      </tr>
      <tr>
        <td id="employeeInfoFieldContainer"></td>
        <td id="updateEmployeeButtonContainer"></td>
      </tr>
      <tr>
      <tr>
        <td colspan="2" style="font-weight:bold;">Please enter employee id:</td>       
      </tr>
      <tr>
        <td id="employeeIdFieldContainer"></td>
        <td id="retrieveEmployeeButtonContainer"></td>
      </tr>
      <tr>
        <td colspan="2" style="color:red;" id="errorLabelContainer"></td>
      </tr>
    </table>
  </body>
</html>

部署访问:

http://localhost:8080/GWTSpring/