Spring Data 系列(一) 入門

認識一個框架的用途和做用,其實很簡單。反其道而行之,若是不用某框架,咱們的開發工做會怎麼樣?咱們必需要作那些額外的工做。java

爲了保證系列的完整性,也專門寫一篇文章,做爲本系列的引子。mysql

考慮到簡單性和專注性,本文準備的例子,弱到幾點。web

主要功能spring

  1. 經過比對,瞭解spring JdbcTemplate的功能,做爲Spring Data的入門。
    sql

  2. 搭建一個實驗的例子,做爲未來學習Spring Data的基礎。數據庫

  3. 暫時不考慮事務(事務能夠很簡單經過AOP方式切入進來)
    apache


1.準備
api

JDK:1.7app

spring:4.0.2(無所謂 spring3也能夠)框架

database(mysql 5.5)

代碼片斷片斷:http://www.journaldev.com/2593/spring-jdbc-example

1.1Database Setup

CREATE TABLE `Employee` (
  `id` int(11) unsigned NOT NULL,
  `name` varchar(20) DEFAULT NULL,
  `role` varchar(20) DEFAULT NULL,
  PRIMARY KEY (`id`)) ENGINE=InnoDB DEFAULT CHARSET=utf8;

1.2 maven pom.xml

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>org.springframework.samples</groupId>
  <artifactId>SpringJDBCExample</artifactId>
  <version>0.0.1-SNAPSHOT</version>

  <properties>
    <!-- Generic properties -->
    <java.version>1.7</java.version>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
    <!-- Spring -->
    <spring-framework.version>4.0.2.RELEASE</spring-framework.version>
    <!-- Logging -->
    <logback.version>1.0.13</logback.version>
    <slf4j.version>1.7.5</slf4j.version>
  </properties>
<build>

  <resources>
    <resource>
      <directory>src/main/resources</directory>
      <filtering>true</filtering>
      <includes>
          <include>**/*.xml</include>
          <include>**/*</include>
      </includes>
    </resource>
  </resources>

  <plugins>
    <plugin>
      <groupId>org.apache.maven.plugins</groupId>
      <artifactId>maven-compiler-plugin</artifactId>
      <version>2.3.2</version>
      <configuration>
        <source>1.7</source>
        <target>1.7</target>
        <showWarnings>true</showWarnings>
        <encoding>utf-8</encoding>
      </configuration>
    </plugin>
  </plugins>
</build>
  <dependencies>
    <!-- Spring and Transactions -->
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-context</artifactId>
      <version>${spring-framework.version}</version>
    </dependency>

    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-tx</artifactId>
      <version>${spring-framework.version}</version>
    </dependency>

    <!-- Spring JDBC Support -->
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-jdbc</artifactId>
      <version>${spring-framework.version}</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-test</artifactId>
      <version>${spring-framework.version}</version>
    </dependency>

    <!-- MySQL Driver -->
    <dependency>
      <groupId>mysql</groupId>
      <artifactId>mysql-connector-java</artifactId>
      <version>5.0.5</version>
    </dependency>

    <!-- Logging with SLF4J & LogBack -->
    <dependency>
      <groupId>log4j</groupId>
      <artifactId>log4j</artifactId>
      <version>1.2.17</version>
    </dependency>
    <dependency>
      <groupId>org.slf4j</groupId>
      <artifactId>slf4j-api</artifactId>
      <version>${slf4j.version}</version>
      <scope>compile</scope>
    </dependency>
    <dependency>
      <groupId>ch.qos.logback</groupId>
      <artifactId>logback-classic</artifactId>
      <version>${logback.version}</version>
      <scope>runtime</scope>
    </dependency>

    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.10</version>
    </dependency>
  </dependencies>
</project>

log4j.xml(隨便找了一個)

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE log4j:configuration PUBLIC "-//LOGGER" "log4j.dtd">
<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">

   <!-- Appenders -->
   <appender name="console" class="org.apache.log4j.ConsoleAppender">
      <param name="Target" value="System.out" />
      <layout class="org.apache.log4j.PatternLayout">
         <param name="ConversionPattern" value="%-5p: %c - %m%n" />
      </layout>
   </appender>

   <!-- 3rdparty Loggers -->
   <logger name="org.springframework.core">
      <level value="info" />
   </logger>

   <logger name="org.springframework.beans">
      <level value="info" />
   </logger>
   
   <logger name="org.springframework.context">
      <level value="info" />
   </logger>

   <logger name="org.springframework.web">
      <level value="info" />
   </logger>

   <!-- Root Logger -->
   <root>
      <priority value="warn" />
      <appender-ref ref="console" />
   </root>
   
</log4j:configuration>


總體項目結構

wKioL1dpTrfA7vpTAAA9epC3aCg710.png

2.業務對象(Model Class)

package com.journaldev.spring.jdbc.model;
public class Employee {

	private int id;
	private String name;
	private String role;
	
	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public String getRole() {
		return role;
	}
	public void setRole(String role) {
		this.role = role;
	}
	
	@Override
	public String toString(){
		return "{ID="+id+",Name="+name+",Role="+role+"}";
	}}


3.DAO Interface

包含基本的CRUD操做

package com.journaldev.spring.jdbc.dao;

import java.util.List;

import com.journaldev.spring.jdbc.model.Employee;

//CRUD operations
public interface EmployeeDAO {
   
   //Create
   public void save(Employee employee);
   //Read
   public Employee getById(int id);
   //Update
   public void update(Employee employee);
   //Delete
   public void deleteById(int id);
   //Get All
   public List<Employee> getAll();
}

4.DAO Interface實現

4.1(原生態方式)

package com.journaldev.spring.jdbc.dao;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

import javax.sql.DataSource;

import com.journaldev.spring.jdbc.model.Employee;

public class EmployeeDAOImpl implements EmployeeDAO {

   private DataSource dataSource;

   public void setDataSource(DataSource dataSource) {
      this.dataSource = dataSource;
   }

   @Override
   public void save(Employee employee) {
      String query = "insert into Employee (id, name, role) values (?,?,?)";
      Connection con = null;
      PreparedStatement ps = null;
      try{
         con = dataSource.getConnection();
         ps = con.prepareStatement(query);
         ps.setInt(1, employee.getId());
         ps.setString(2, employee.getName());
         ps.setString(3, employee.getRole());
         int out = ps.executeUpdate();
         if(out !=0){
            System.out.println("Employee saved with id="+employee.getId());
         }else System.out.println("Employee save failed with id="+employee.getId());
      }catch(SQLException e){
         e.printStackTrace();
      }finally{
         try {
            ps.close();
            con.close();
         } catch (SQLException e) {
            e.printStackTrace();
         }
      }
   }

   @Override
   public Employee getById(int id) {
      String query = "select name, role from Employee where id = ?";
      Employee emp = null;
      Connection con = null;
      PreparedStatement ps = null;
      ResultSet rs = null;
      try{
         con = dataSource.getConnection();
         ps = con.prepareStatement(query);
         ps.setInt(1, id);
         rs = ps.executeQuery();
         if(rs.next()){
            emp = new Employee();
            emp.setId(id);
            emp.setName(rs.getString("name"));
            emp.setRole(rs.getString("role"));
            System.out.println("Employee Found::"+emp);
         }else{
            System.out.println("No Employee found with id="+id);
         }
      }catch(SQLException e){
         e.printStackTrace();
      }finally{
         try {
            rs.close();
            ps.close();
            con.close();
         } catch (SQLException e) {
            e.printStackTrace();
         }
      }
      return emp;
   }

   @Override
   public void update(Employee employee) {
      String query = "update Employee set name=?, role=? where id=?";
      Connection con = null;
      PreparedStatement ps = null;
      try{
         con = dataSource.getConnection();
         ps = con.prepareStatement(query);
         ps.setString(1, employee.getName());
         ps.setString(2, employee.getRole());
         ps.setInt(3, employee.getId());
         int out = ps.executeUpdate();
         if(out !=0){
            System.out.println("Employee updated with id="+employee.getId());
         }else System.out.println("No Employee found with id="+employee.getId());
      }catch(SQLException e){
         e.printStackTrace();
      }finally{
         try {
            ps.close();
            con.close();
         } catch (SQLException e) {
            e.printStackTrace();
         }
      }
   }

   @Override
   public void deleteById(int id) {
      String query = "delete from Employee where id=?";
      Connection con = null;
      PreparedStatement ps = null;
      try{
         con = dataSource.getConnection();
         ps = con.prepareStatement(query);
         ps.setInt(1, id);
         int out = ps.executeUpdate();
         if(out !=0){
            System.out.println("Employee deleted with id="+id);
         }else System.out.println("No Employee found with id="+id);
      }catch(SQLException e){
         e.printStackTrace();
      }finally{
         try {
            ps.close();
            con.close();
         } catch (SQLException e) {
            e.printStackTrace();
         }
      }
   }

   @Override
   public List<Employee> getAll() {
      String query = "select id, name, role from Employee";
      List<Employee> empList = new ArrayList<Employee>();
      Connection con = null;
      PreparedStatement ps = null;
      ResultSet rs = null;
      try{
         con = dataSource.getConnection();
         ps = con.prepareStatement(query);
         rs = ps.executeQuery();
         while(rs.next()){
            Employee emp = new Employee();
            emp.setId(rs.getInt("id"));
            emp.setName(rs.getString("name"));
            emp.setRole(rs.getString("role"));
            empList.add(emp);
         }
      }catch(SQLException e){
         e.printStackTrace();
      }finally{
         try {
            rs.close();
            ps.close();
            con.close();
         } catch (SQLException e) {
            e.printStackTrace();
         }
      }
      return empList;
   }

}

4.2(JdbcTemplate方式)

package com.journaldev.spring.jdbc.dao;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import javax.sql.DataSource;

import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;

import com.journaldev.spring.jdbc.model.Employee;

public class EmployeeDAOJDBCTemplateImpl implements EmployeeDAO {

    private DataSource dataSource;

    public void setDataSource(DataSource dataSource) {
        this.dataSource = dataSource;
    }
    
    @Override
    public void save(Employee employee) {
        String query = "insert into Employee (id, name, role) values (?,?,?)";
        
        JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
        
        Object[] args = new Object[] {employee.getId(), employee.getName(), employee.getRole()};
        
        int out = jdbcTemplate.update(query, args);
        
        if(out !=0){
            System.out.println("Employee saved with id="+employee.getId());
        }else {
            System.out.println("Employee save failed with id="+employee.getId());
        }
    }

    @Override
    public Employee getById(int id) {
        String query = "select id, name, role from Employee where id = ?";
        JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
        
        //using RowMapper anonymous class, we can create a separate RowMapper for reuse
        Employee emp = jdbcTemplate.queryForObject(query, new Object[]{id}, new RowMapper<Employee>(){

            @Override
            public Employee mapRow(ResultSet rs, int rowNum)
                    throws SQLException {
                Employee emp = new Employee();
                emp.setId(rs.getInt("id"));
                emp.setName(rs.getString("name"));
                emp.setRole(rs.getString("role"));
                return emp;
            }});
        
        return emp;
    }

    @Override
    public void update(Employee employee) {
        String query = "update Employee set name=?, role=? where id=?";
        JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
        Object[] args = new Object[] {employee.getName(), employee.getRole(), employee.getId()};
        
        int out = jdbcTemplate.update(query, args);
        if(out !=0){
            System.out.println("Employee updated with id="+employee.getId());
        }else{
            System.out.println("No Employee found with id="+employee.getId());
        }
    }

    @Override
    public void deleteById(int id) {

        String query = "delete from Employee where id=?";
        JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
        
        int out = jdbcTemplate.update(query, id);
        if(out !=0){
            System.out.println("Employee deleted with id="+id);
        }else {
            System.out.println("No Employee found with id="+id);
        }
    }

    @Override
    public List<Employee> getAll() {
        String query = "select id, name, role from Employee";
        JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
        List<Employee> empList = new ArrayList<Employee>();

        List<Map<String,Object>> empRows = jdbcTemplate.queryForList(query);
        
        for(Map<String,Object> empRow : empRows){
            Employee emp = new Employee();
            emp.setId(Integer.parseInt(String.valueOf(empRow.get("id"))));
            emp.setName(String.valueOf(empRow.get("name")));
            emp.setRole(String.valueOf(empRow.get("role")));
            empList.add(emp);
        }
        return empList;
    }

}


兩個實現類,實現的功能是同樣的。但經過對比,能夠很容易發現。使用了JdbcTemplate ,能夠幫助咱們屏蔽底層的PreparedStatement ,ResultSet等對象的操做,簡化了一些無聊的底層操做。

須要說明的是:mysql 默認的隔離級別是REPEATABLE-READ 。爲何沒有執行提交操做,也會影響數據庫呢?有興趣的能夠作實驗確認下,想一想爲何!

mysql> select @@tx_isolation ;
+-----------------+
| @@tx_isolation  |
+-----------------+
| mysql> select @@tx_isolation
    -> ;
+-----------------+
| @@tx_isolation  |
+-----------------+
| REPEATABLE-READ |
+-----------------+
1 row in set |
+-----------------+
1 row in set

5.測試例子

5.1 Main

package com.journaldev.spring.jdbc;
import java.util.List;
import java.util.Random;

import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.journaldev.spring.jdbc.dao.EmployeeDAO;
import com.journaldev.spring.jdbc.model.Employee;

public class SpringMain {

    public static void main(String[] args) {
        //Get the Spring Context
        ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("spring.xml");

        //Get the EmployeeDAO Bean
        EmployeeDAO employeeDAO = ctx.getBean("employeeDAO", EmployeeDAO.class);

        //Run some tests for JDBC CRUD operations
        Employee emp = new Employee();
        int rand = new Random().nextInt(1000);
        emp.setId(rand);
        emp.setName("Pankaj");
        emp.setRole("Java Developer");

        //Create
        employeeDAO.save(emp);

        //Read
        Employee emp1 = employeeDAO.getById(rand);
        System.out.println("Employee Retrieved::"+emp1);

        //Update
        emp.setRole("CEO");
        employeeDAO.update(emp);

        //Get All
        List<Employee> empList = employeeDAO.getAll();
        System.out.println(empList);

        //Delete
        employeeDAO.deleteById(rand);

        //Close Spring Context
        ctx.close();

        System.out.println("DONE");
    }

}

5.2 spring junit集成版

import com.journaldev.spring.jdbc.dao.EmployeeDAO;
import com.journaldev.spring.jdbc.model.Employee;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4Cla***unner;
import javax.annotation.Resource;
import java.util.Random;

/**
 * Created by Administrator on 2016/6/21.
 */
@RunWith(SpringJUnit4Cla***unner.class)
@ContextConfiguration(locations = "classpath:spring.xml")
public class SpringDaoTest {
    @Resource
    private EmployeeDAO employeeTemplateDAO;
    @Resource
    private EmployeeDAO employeeDAO;

    @Test
    public void testSave(){
        Employee emp = new Employee();
        int rand = new Random().nextInt(1000);
        emp.setId(rand);
        emp.setName("Pankaj");
        emp.setRole("Java Developer");
        employeeDAO.save(emp);
    }

    @Test
    public void testSave2(){
        Employee emp = new Employee();
        int rand = new Random().nextInt(1000);
        emp.setId(rand);
        emp.setName("Pankaj-2");
        emp.setRole("Java Developer-2");
        employeeTemplateDAO.save(emp);
    }
}


經過2個測試代碼的比較,相信很容易發現二者優缺點

版本 優勢
缺點
Main 簡單上手,隨時隨地
編寫代碼多,沒辦法自動化
spring junit

方便測試

管理資源對象方便
自動化

配置環境稍微有點麻煩)

接下來,即將進入Spring Data的內容了。

附件爲源碼包

相關文章
相關標籤/搜索