您的位置:首页 > 编程语言 > Java开发

Spring Data 系列(一) 入门

2016-06-21 22:45 471 查看
认识一个框架的用途和作用,其实很简单。反其道而行之,如果不用某框架,我们的开发工作会怎么样?我们必须要做那些额外的工作。
为了保证系列的完整性,也专门写一篇文章,作为本系列的引子。
考虑到简单性和专一性,本文准备的例子,弱到几点。
主要功能
通过比对,了解spring JdbcTemplate的功能,作为Spring Data的入门。

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

暂时不考虑事务(事务可以很简单通过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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: