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的内容了。

附件为源码包

时间: 2024-10-08 11:13:44

Spring Data 系列(一) 入门的相关文章

Spring Data 系列(二) Spring+JPA入门

通过[Spring Data 系列(一) 入门]的介绍,通过对比的方式认识到Spring提供的JdbcTemplate的强大功能.通过使用JdbcTemplate,操作数据库,不需要手动处理Connection,Statement等底层SQL对象.可是,Spring对数据库的操作还远远没有结束.本章主要介绍Spring 对JPA的支持. 主要内容 简单介绍JPA Spring Hibernate JPA整合 1.JPA简介 Java Persistence API (JPA),为开发人员提供了一

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

本章是Spring Data系列的第三篇.系列文章,重点不是讲解JPA语法,所以跑开了JPA的很多语法等,重点放在环境搭建,通过对比方式,快速体会Spring 对JPA的强大功能. 准备代码过程中,保持了每个例子的独立性,和简单性,准备的源码包,下载即可使用.如果,对JPA语法想深入研究的话,直接下载在此基础上进行测试. 前言 Spring Data 系列(一) 入门:简单介绍了原生态的SQL使用,以及JdbcTemplate的使用,在这里写SQL的活还需要自己准备. Spring Data 系

《Spring Data JPA从入门到精通》内容简介、前言

内容简介 本书以Spring Boot为技术基础,从入门到精通,由浅入深地介绍Spring Data JPA的使用.有语法,有实践,有原理剖析. 本书分为12章,内容包括整体认识JPA.JPA基础查询方法.定义查询方法.注解式查询方法.@Entity实例里面常用注解详解.JpaRepository扩展详解.JPA的MVC扩展REST支持.DataSource的配置.乐观锁.SpEL表达式在Spring Data里面的应用.Spring Data Redis实现cacheable的实践.Intel

(转) Spring Data 系列之JPA

转自:https://my.oschina.net/ztlyde/blog/68513 引入: Spring Data是SpringSource基金会下的一个用于简化数据库访问,并支持云服务的开源框架.其主要目标是使得数据库的访问变得方便快捷,并支持map-reduce框架和云计算数据服务.对于拥有海量数据的项目,可以用Spring Data来简化项目的开发. 然而针对不同的数据储存访问使用相对的类库来操作访问.Spring Data中已经为我们提供了很多业务中常用的一些接口和实现类来帮我们快速

Spring Data Redis —— 快速入门

环境要求:Redis 2.6及以上,javase 8.0及以上: 一.Spring Data Redis 介绍 Spring-data-redis是spring的一部分,提供了在srping应用中通过简单的配置访问redis服务,对reids底层开发包(Jedis, JRedis, and RJC)进行了高度封装,RedisTemplate提供了redis各种操作.异常处理及序列化,支持发布订阅,并对spring 3.1 cache进行了实现.spring-data-redis针对jedis提供

Spring Data系列之Jpa(一)

1.Spring Data的由来 Spring Data是SpringSource基金会创下的一个简化数据库访问.支持云服务的开源框架.其主要目的是让数据库访问变的方便快捷,可以用Spring Data框架简化项目的开发. 2.什么是JPA??? JPA全称Java Persistence API.JPA通过JDK 5.0注解或XML描述对象-------关系表的映射关系,并将运行期的实体对象持久化(对象持久化是指将内存中的对象保存到可永久保存的存储设备中(如磁盘)的一种技术.)到数据库中. 3

整合Spring Data JPA与Spring MVC: 分页和排序

之前我们学习了如何使用Jpa访问关系型数据库.比较完整Spring MVC和JPA教程请见Spring Data JPA实战入门,Spring MVC实战入门. 通过Jpa大大简化了我们对数据库的开发工作.但是,之前的例子中我们只提到了最简单的CRUD(增删改查)操作.实际上,Spring Data Jpa对于分页以及排序的查询也有着完美的支持,接下来,我们来学习如何通过Pageable来对数据库进行分页查询. 添加maven依赖 首先我们需要引入Jpa,数据库直接使用hsqldb内存数据库就可

【Spring Data 系列学习】Spring Data JPA 自定义查询,分页,排序,条件查询

Spring Boot Jpa 默认提供 CURD 的方法等方法,在日常中往往时无法满足我们业务的要求,本章节通过自定义简单查询案例进行讲解. 快速上手 项目中的pom.xml.application.properties与 Chapter1 相同 实体类映射数据库表 user 实体类 @Entity public class User implements Serializable { private static final long serialVersionUID = -39076354

spring boot系列(五)spring boot 配置spring data jpa (查询方法)

接着上面spring boot系列(四)spring boot 配置spring data jpa 保存修改方法继续做查询的测试: 1 创建UserInfo实体类,代码和https://www.cnblogs.com/kxm87/p/9273555.html中的一样. 2 创建数据库操作类相当于dao层,主要创建一个接口UserRepository,继承JpaRepository接口即可.本代码中主要都是自定义方法. 使用findXX 或者countXX(这两个不用编写sql,jpa会自动生成)