我們在進行事務處理往往需要和資料庫進行互動,這其中有關係型資料庫(MySql,Sql Server,Oracle)或者是非關係型資料庫(Redis,Hadhoop),常見的操縱資料庫的方式就有JDBC和Spring JdbcTemplate,而這兩種處理方式其實很繁瑣而且程式碼複用率也比較低。另外使用這這種方式進行實際開發時效率也比較低,今天我們使用Spring Data進行開發。在進行開發之前我們首先介紹一下什麼是Spring-Data,以及如何使用JDBC和Spring JDBCTemplate方式進行常用的CRUD功能的開發。
SpringData相關概念:
SpringData是Spring基於ORM框架、JPA規範封裝的一套JPA應用框架,它提供了包括增刪改查在內的常用功能,且易於擴充套件,可使開發者用極簡的程式碼實現對資料庫的訪問和操作。
什麼是JPA呢?
JPA全稱Java Persistence API,是sun提出的一個物件持久化規範,各JavaEE應用伺服器自主選擇具體實現。JPA僅僅只是一個規範,而不是產品;使用JPA本身是不能做到持久化的。所以,JPA只是一系列定義好的持久化操作的介面,在系統中使用時,需要真正的實現者。
JPA的設計者是Hibernate框架的作者,因此Hibernate EntityManager作為Jboss伺服器中JPA的預設實現;Oracle的Weblogic使用EclipseLink(以前叫TopLink)作為預設的JPA實現;IBM的Websphere和Sun的Glassfish預設使用OpenJPA(Apache的一個開源專案)作為其預設的JPA實現。
JPA的底層實現是一些流行的開源ORM(物件關係對映)框架,因此JPA其實也就是java實體物件和關係型資料庫建立起對映關係,通過物件導向程式設計的思想操作關係型資料庫的規範。
什麼是ORM呢?
ORM,即Object-Relational Mapping(物件關係對映),它的作用是在關係型資料庫和業務實體物件之間作一個對映,這樣,我們在具體的操作業務物件的時候,就不需要再去和複雜的SQL語句打交道,只需簡單的操作物件的屬性和方法。只要提供了持久化類與表的對映關係,ORM框架在執行時就能參照對映檔案的資訊,把物件持久化到資料庫中。當前ORM框架主要有三種:Hibernate,iBATIS,EclipseLink。
SpringData提供的程式設計介面:
【1】Repository:最頂層介面,是一個空介面,目的是為了統一所有的Repository的型別,且能讓元件掃描的時候自動識別;
【2】CrudRepository:提供基礎的增刪改查操作;
【3】PagingAndSortingRepository:提供分頁和排序的操作;
【4】JpaRepository:增加了批量操作的功能;
【5】JpaSpecificationExecutor :組合查詢條件,提供原生SQL查詢。
使用JDBC進行開發:
首先說明例子所設計的資料庫,如下圖:
![圖片描述][1]
1.JDBC工具類
public class JDBCUtil {
/*
* 獲取connection
* @return 所獲得的JDBC的Connection
*/
public static Connection getConnection() throws ClassNotFoundException, SQLException, IOException
{
/*String url = "jdbc:mysql://localhost:3306/spring_data";
String user = "root";
String password = "123456";
String driverClass = "com.mysql.jdbc.Driver";*/
/*
* 通過讀取配置檔案獲取資料庫連線所需引數
*/
InputStream inputStream = JDBCUtil.class.getClassLoader().getResourceAsStream("database.properties");
Properties properties = new Properties();
properties.load(inputStream);
String url = properties.getProperty("jdbc.url");
String user = properties.getProperty("jdbc.user");
String password = properties.getProperty("jdbc.password");
String driverClass = properties.getProperty("jdbc.driverClass");
Class.forName(driverClass);
Connection connection = DriverManager.getConnection(url, user, password);
return connection;
}
/*
* 釋放資源
*/
public static void release(ResultSet resultSet,Statement statement,Connection connection)
{
/*
* 釋放resultset
*/
if(resultSet!=null)
{
try {
resultSet.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if(resultSet!=null)
{
try {
resultSet.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
/*
* 釋放statement
*/
if(statement!=null)
{
try {
statement.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
/*
* 釋放connection
*/
if(connection!=null)
{
try {
connection.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
附: JDBC資料來源配置檔案:
jdbc.url = jdbc:mysql://localhost:3306/spring_data
jdbc.user = root
jdbc.password = 123456
jdbc.driverClass =com.mysql.jdbc.Driver
2.定義專案中設計的實體類
/**
* @author 熊濤
*Student Entity Class
*/
public class Student {
private int id;
private String name;
private int age;
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 int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
3.Dao層介面的實現
public interface StudentDAO {
/*
* 查詢所有學生
* @return所有學生
*/
public List<Student> query();
/*
* 新增學生介面
*/
public void save(Student student);
}
4.Dao層介面的實現類
/**
* @author 熊濤
*StudentDAO介面的實現類,通過最原始的JDBC的方式操作
*/
public class StudetnDAOImpl implements StudentDAO {
public List<Student> query() {
List<Student> students = new ArrayList<Student>();
Connection connection = null;
PreparedStatement preparedStatement = null;
ResultSet resultSet = null;
String sql = "select id,name,age from student";
try {
connection = JDBCUtil.getConnection();
preparedStatement=connection.prepareStatement(sql);
resultSet = preparedStatement.executeQuery();
Student student = null;
while(resultSet.next()){
int id = resultSet.getInt("id");
String name = resultSet.getString("name");
int age = resultSet.getInt("age");
student = new Student();
student.setId(id);
student.setName(name);
student.setAge(age);
students.add(student);
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally{
JDBCUtil.release(resultSet, preparedStatement, connection);
}
return students;
}
public void save(Student student) {
Connection connection = null;
PreparedStatement preparedStatement = null;
ResultSet resultSet = null;
String sql = "insert into student(name,age) values(?,?)";
try {
connection = JDBCUtil.getConnection();
preparedStatement=connection.prepareStatement(sql);
preparedStatement.setString(1, student.getName());
preparedStatement.setInt(2, student.getAge());
preparedStatement.executeUpdate();
}catch(Exception e){
e.printStackTrace();
}finally{
JDBCUtil.release(resultSet, preparedStatement, connection);
}
}
}
2.使用Spring JDBCTemplate進行開發
1.建立使用Spring-JDBCTemplate所需的配置檔案beans.xml目的是將datasource和JDBCTemplate注入進來
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<property name="username" value="root"/>
<property name="password" value="123456"/>
<property name="url" value="jdbc:mysql://localhost:3306/spring_data"/>
</bean>
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource"/>
</bean>
<bean id="studentDAO" class="com.imooc.dao.StudentDAOSpringJdbcImpl">
<property name="jdbcTemplate" ref="jdbcTemplate"/>
</bean>
</beans>
2.在Dao層實現類中實現JDBCTemplate
/**
* @author 熊濤
*StudentDAo介面的實現類,通過Spring-JDBC的方式操作
*/
public class StudentDAOSpringJdbcImpl implements StudentDAO {
//通過set方法注入JdbcTemplate
private JdbcTemplate jdbcTemplate;
public List<Student> query() {
final List<Student> students = new ArrayList<Student>();
String sql = "select id,name,age from student";
jdbcTemplate.query(sql,new RowCallbackHandler(){
public void processRow(ResultSet rs) throws SQLException {
int id = rs.getInt("id");
String name = rs.getString("name");
int age = rs.getInt("age");
Student student = new Student();
student.setId(id);
student.setName(name);
student.setAge(age);
students.add(student);
}
});
return students;
}
public void save(Student student) {
String sql = "insert into student(name,age) values(?,?)";
jdbcTemplate.update(sql,new Object[]{student.getName(),student.getAge()});
}
public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
this.jdbcTemplate = jdbcTemplate;
}
}
3.使用Spring-Data方式進行開發
【1】建立使用Spring-Data所需的Spring配置檔案
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:jpa="http://www.springframework.org/schema/data/jpa"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa-1.3.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd">
<!--1 配置資料來源-->
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<property name="username" value="root"/>
<property name="password" value="123456"/>
<property name="url" value="jdbc:mysql://localhost:3306/spring_data"/>
</bean>
<!--2 配置EntityManagerFactory-->
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"/>
</property>
<property name="packagesToScan" value="com.imooc"/>
<property name="jpaProperties">
<props>
<prop key="hibernate.ejb.naming_strategy">org.hibernate.cfg.ImprovedNamingStrategy</prop>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQL5InnoDBDialect</prop>
<prop key="hibernate.show_sql">true</prop>
<prop key="hibernate.format_sql">true</prop>
<prop key="hibernate.hbm2ddl.auto">update</prop>
</props>
</property>
</bean>
<!--3 配置事務管理器-->
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory"/>
</bean>
<!--4 配置支援註解的事務-->
<tx:annotation-driven transaction-manager="transactionManager"/>
<!--5 配置spring data-->
<jpa:repositories base-package="com.imooc" entity-manager-factory-ref="entityManagerFactory"/>
<context:component-scan base-package="com.imooc"/>
</beans>
【2】建立專案中所涉及到的實體類
/**
* @author 熊濤
*僱員實體類
*先開發實體類,然後生成對應的資料表
*/
@Entity
@Table(name="test_employee")
public class Employee {
private Integer id;
private String name;
private Integer age;
@GeneratedValue
@Id
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
@Column(length=20)
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
@Override
public String toString() {
return "Employee [id=" + id + ", name=" + name + ", age=" + age + "]";
}
}
【3】建立專案中設計的介面類
public interface EmployeeRepository extends Repository<Employee,Integer>{
public Employee findByName(String name);
public List<Employee> findByNameStartingWithAndAgeLessThan(String name,Integer age);
public List<Employee> findByNameEndingWithAndAgeLessThan(String name,Integer age);
public List<Employee> findByNameInOrAgeLessThan(List<String> names,Integer age);
public List<Employee> findByNameInAndAgeLessThan(List<String> names,Integer age);
@Query("select o from Employee o where id=(select max(id) from Employee t1)")
public Employee getEmployeeByMaxId();
@Query("select o from Employee o where o.name=?1 and o.age=?2")
public List<Employee> queryParams1(String name,Integer age);
@Query("select o from Employee o where o.name=:name and o.age=:age")
public List<Employee> queryParams2(@Param("name")String name,@Param("age")Integer age);
@Query("select o from Employee o where o.name like %?1%")
public List<Employee> queryLike1(String name);
@Query("select o from Employee o where o.name like %:name%")
public List<Employee> queryLike2(@Param("name")String name);
@Query(nativeQuery = true,value = "select count(1) from employee")
public long getCount();
@Modifying
@Query("update Employee o set o.age = :age where o.id = :id")
public void update(@Param("id")Integer id,@Param("age")Integer age);
}
最後附上例子原始碼,原始碼中還有對於以上程式碼功能的測試,測試程式碼均位於test包下。
專案原始碼:
連結:https://pan.baidu.com/s/1pLcGCUR 密碼:welh