Spring Data 系列(一) 入門

原創作品,允許轉載,轉載時請務必以超鏈接形式標明文章 原始出處 、作者信息和本聲明。否則將追究法律責任。http://dba10g.blog.51cto.com/764602/1791528

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

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

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

主要功能

  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

1
2
3
4
5
CREATE TABLE `Employee` (
  `id` int(11) unsigned NOT NULL,
  `namevarchar(20) DEFAULT NULL,
  `role` varchar(20) DEFAULT NULL,
  PRIMARY KEY (`id`)) ENGINE=InnoDB DEFAULT CHARSET=utf8;

1.2 maven pom.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
<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(隨便找了一個)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
<?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)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
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操作

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
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(原生態方式)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
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方式)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
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 。爲什麼沒有執行提交操作,也會影響數據庫呢?有興趣的可以做實驗確認下,想想爲什麼!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
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集成版

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
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



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章