Spring Data 系列 入门

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Spring Data 系列 入门相关的知识,希望对你有一定的参考价值。

认识一个框架的用途和作用,其实很简单。反其道而行之,如果不用某框架,我们的开发工作会怎么样?我们必须要做那些额外的工作。

为了保证系列的完整性,也专门写一篇文章,作为本系列的引子。

考虑到简单性和专一性,本文准备的例子,弱到几点。

主要功能

  1. 通过比对,了解spring JdbcTemplate的功能,作为Spring Data的入门。

  2. 搭建一个实验的例子,作为将来学习Spring Data的基础。

  3. 暂时不考虑事务(事务可以很简单通过AOP方式切入进来)


1.准备

JDK:1.7

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>


整体项目结构

技术分享

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.SpringJUnit4ClassRunner;
import javax.annotation.Resource;
import java.util.Random;

/**
 * Created by Administrator on 2016/6/21.
 */
@RunWith(SpringJUnit4ClassRunner.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的内容了。

附件为源码包

本文出自 “简单” 博客,请务必保留此出处http://dba10g.blog.51cto.com/764602/1791528

以上是关于Spring Data 系列 入门的主要内容,如果未能解决你的问题,请参考以下文章

Spring Data 系列 Spring+JPA(spring-data-commons)

spring data jpa详解

纯干货,Spring-data-jpa详解(转)

Spring-data-jpa详解,全方位介绍。

Spring-data-jpa详解,全方位介绍。

纯干货,Spring-data-jpa详解,全方位介绍