詳談hibernate,jpa與spring?data?jpa三者之間的關(guān)系
前提
其實(shí)很多框架都是對(duì)另一個(gè)框架的封裝,我們?cè)趯W(xué)習(xí)類(lèi)似的框架的時(shí)候,難免會(huì)進(jìn)入誤區(qū),所以我們就應(yīng)該對(duì)其進(jìn)行總結(jié)歸納,對(duì)比。本文就是對(duì)hibernate,jpa,spring data jpa三者之間進(jìn)行文字對(duì)比,以及對(duì)其三者分別進(jìn)行CRUD操作。
文字說(shuō)明
Hibernate
Hibernate是一個(gè)開(kāi)放源代碼的對(duì)象關(guān)系映射框架,它對(duì)JDBC進(jìn)行了非常輕量級(jí)的對(duì)象封裝,它將POJO與數(shù)據(jù)庫(kù)表建立映射關(guān)系,是一個(gè)全自動(dòng)的orm框架,hibernate可以自動(dòng)生成SQL語(yǔ)句,自動(dòng)執(zhí)行,使得Java程序員可以隨心所欲的使用對(duì)象編程思維來(lái)操縱數(shù)據(jù)庫(kù)。
JPA
JPA全稱(chēng)是Java Persistence API,即java持久化API,是sun公司推出的一套基于ORM的規(guī)范,內(nèi)部由一系列的接口和抽象類(lèi)構(gòu)成。
JPA與Hibetnate的關(guān)系
JPA和Hibernate的關(guān)系就像JDBC和JDBC驅(qū)動(dòng)的關(guān)系,JPA是規(guī)范,Hibernate除了作為ORM框架之外,它也是一種JPA實(shí)現(xiàn)。JPA怎么取代Hibernate呢?JDBC規(guī)范可以驅(qū)動(dòng)底層數(shù)據(jù)庫(kù)嗎?答案是否定的,也就是說(shuō),如果使用JPA規(guī)范進(jìn)行數(shù)據(jù)庫(kù)操作,底層需要hibernate作為其實(shí)現(xiàn)類(lèi)完成數(shù)據(jù)持久化工作。
Spring Data jpa
Spring Data JPA 讓我們解脫了DAO層的操作,基本上所有CRUD都可以依賴(lài)于它來(lái)實(shí)現(xiàn),在實(shí)際的工作工程中,推薦使用Spring Data JPA + ORM(如:hibernate)完成操作,這樣在切換不同的ORM框架時(shí)提供了極大的方便,同時(shí)也使數(shù)據(jù)庫(kù)層操作更加簡(jiǎn)單,方便解耦
Hibernate、JPA與Spring Data JPA之間的關(guān)系
JPA是一套規(guī)范,內(nèi)部是有接口和抽象類(lèi)組成的。hibernate是一套成熟的ORM框架,而且Hibernate實(shí)現(xiàn)了JPA規(guī)范,所以也可以稱(chēng)hibernate為JPA的一種實(shí)現(xiàn)方式,我們使用JPA的API編程,意味著站在更高的角度上看待問(wèn)題(面向接口編程)Spring Data JPA是Spring提供的一套對(duì)JPA操作更加高級(jí)的封裝,是在JPA規(guī)范下的專(zhuān)門(mén)用來(lái)進(jìn)行數(shù)據(jù)持久化的解決方案。以上就是對(duì)hibernate、JPA與Spring Data JPA三者之間的關(guān)系說(shuō)明。
總結(jié):
JPA是一種規(guī)范,Hibernate實(shí)現(xiàn)了JPA規(guī)范,即Hibernate為JPA的一種實(shí)現(xiàn);而Spring Data JPA是對(duì)JPA進(jìn)行更高級(jí)的封裝,讓其dao編碼變得更簡(jiǎn)單。
CRUD操作
hibernate的crud操作
首先創(chuàng)建數(shù)據(jù)庫(kù)表

創(chuàng)建hibernate核心配置文件hibernate.cfg.xml
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd"> <hibernate-configuration> <session-factory> <property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property> <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property> <property name="hibernate.connection.url">jdbc:mysql:///hibernate</property> <property name="hibernate.connection.username">root</property> <property name="hibernate.connection.password">root</property> <property name="hibernate.connection.provider_class">org.hibernate.connection.C3P0ConnectionProvider</property> <property name="hibernate.show_sql">true</property> <property name="hibernate.format_sql">true</property> <property name="hibernate.hbm2ddl.auto">update</property> <!-- 配置和當(dāng)前線(xiàn)程綁定的session進(jìn)行開(kāi)啟配置 --> <property name="hibernate.current_session_context_class">thread</property> <!-- 引入映射文件 --> <mapping resource="cn/itcast/domain/Customer.hbm.xml" /> </session-factory> </hibernate-configuratio
創(chuàng)建實(shí)體類(lèi)Customer(和數(shù)據(jù)庫(kù)表映射的類(lèi))
package cn.itcast.domain;
public class Customer
{
private Long cust_id;// '客戶(hù)編號(hào)(主鍵)',
private String cust_name;// '客戶(hù)名稱(chēng)(公司名稱(chēng))',
private String cust_source;// '客戶(hù)信息來(lái)源',
private String cust_industry;//'客戶(hù)所屬行業(yè)',
private String cust_level;// '客戶(hù)級(jí)別',
private String cust_address;// '客戶(hù)聯(lián)系地址',
private String cust_phone;// '客戶(hù)聯(lián)系電話(huà)',
public Long getCust_id() {
return cust_id;
}
public void setCust_id(Long cust_id) {
this.cust_id = cust_id;
}
public String getCust_name() {
return cust_name;
}
public void setCust_name(String cust_name) {
this.cust_name = cust_name;
}
public String getCust_source() {
return cust_source;
}
public void setCust_source(String cust_source) {
this.cust_source = cust_source;
}
public String getCust_industry() {
return cust_industry;
}
public void setCust_industry(String cust_industry) {
this.cust_industry = cust_industry;
}
public String getCust_level() {
return cust_level;
}
public void setCust_level(String cust_level) {
this.cust_level = cust_level;
}
public String getCust_address() {
return cust_address;
}
public void setCust_address(String cust_address) {
this.cust_address = cust_address;
}
public String getCust_phone() {
return cust_phone;
}
public void setCust_phone(String cust_phone) {
this.cust_phone = cust_phone;
}
}
創(chuàng)建Hibernate映射文件Customer.hbm.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<!-- 做類(lèi)(Customer)和表(cst_customer)的映射關(guān)系 -->
<hibernate-mapping>
<!--
class標(biāo)簽: 作用類(lèi)和表的映射的
name:類(lèi)的全限定名(cn.itcast.domain.Customer)
table:表的全名(cst_customer)
-->
<class name="cn.itcast.domain.Customer" table="cst_customer">
<!--
id標(biāo)簽:做類(lèi)中的某個(gè)屬性 和 表的主鍵映射關(guān)系
name:類(lèi)的某個(gè)屬性名
column:表的主鍵字段名
-->
<id name="cust_id" column="cust_id">
<!-- 做主鍵的增長(zhǎng)方式的
native: AUTO_INCREMENT 讓主鍵自動(dòng)增長(zhǎng) -->
<generator class="native"></generator>
</id>
<!--
property標(biāo)簽:做其它屬性和其它字段的映射關(guān)系
name屬性:類(lèi)的其它屬性名
column屬性:表的其它字段名
ps:如果屬性名和字段名一致 column可以省略不寫(xiě)
-->
<property name="cust_name" column="cust_name" length="20" not-null="true" unique="true"></property>
<property name="cust_source" column="cust_source"></property>
<property name="cust_industry" column="cust_industry"></property>
<property name="cust_level" column="cust_level"></property>
<property name="cust_address" column="cust_address"></property>
<property name="cust_phone" column="cust_phone"></property>
</class>
</hibernate-mapping>
以上我們就完成了dao層的編碼工作?,F(xiàn)在我們來(lái)測(cè)試:
創(chuàng)建工具類(lèi)HibernateUtils
package cn.itcast.utils;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
public class HibernateUtils
{
static Configuration configuration =null;
static SessionFactory sessionFactory = null;
static
{
// 加載一次配置文件
configuration = new Configuration();
configuration.configure();
// 獲取一個(gè)sessionFactory
sessionFactory=configuration.buildSessionFactory();
}
// 從連接池獲取的
public static Session openSession()
{
return sessionFactory.openSession();
}
// 從當(dāng)前線(xiàn)程中獲取綁定的session
// 好處: 在多層之間調(diào)用方法獲取的都是同一個(gè)session
public static Session getCurrentSession()
{
/*特點(diǎn): 1 默認(rèn)是關(guān)閉的 需要配置開(kāi)啟
2 會(huì)自動(dòng)給你關(guān)閉連接*/
Session session = sessionFactory.getCurrentSession();
return session;
}
}
通過(guò)以上工具類(lèi),我們就可以輕松地獲取管理hibernate的seesion對(duì)象,session對(duì)象具備crud的一系列方法。
save():保存操作
@Test
public void test2()
{
Session session = HibernateUtils.openSession();
Transaction tx = session.beginTransaction();
Customer customer = new Customer();
customer.setCust_name("bbbbb");
session.save(customer);
tx.commit();
session.close();
}
get():查詢(xún)
// oid查詢(xún)
@Test
public void test1() {
Session session = HibernateUtils.openSession();
Transaction tx = session.beginTransaction();
Customer customser = session.get(Customer.class, "abcdefg");
System.out.println(customser);
tx.commit();
session.close();
// 只有增刪改 一級(jí)oid查詢(xún) 才會(huì)自動(dòng)生成sql語(yǔ)句
}
通過(guò)HQL方式查詢(xún):
@Test
public void test3() {
Session session = HibernateUtils.openSession();
Transaction tx = session.beginTransaction();
// 條件查 類(lèi)似sql語(yǔ)句的表達(dá)式 from 持久化類(lèi) where 屬性=?
Query qr = session.createQuery("from Customer where cust_name like ?");
qr.setParameter(0, "h%");
List<Customer> list = qr.list();
for (Customer customer : list) {
System.out.println(customer);
}
tx.commit();
session.close();
}
通過(guò)sql方式查詢(xún):
@Test
public void test5() {
Session session = HibernateUtils.openSession();
Transaction tx = session.beginTransaction();
// 單列查 返回是Object
Query qr = session.createQuery("select cust_id from Customer");
List<Object> list = qr.list();
for (Object object : list) {
System.out.println(object);
}
tx.commit();
session.close();
}
JPA的crud操作
該操作我們用maven的方式來(lái)構(gòu)建依賴(lài)
首先我們需要引入依賴(lài):
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.hibernate.version>5.0.7.Final</project.hibernate.version>
</properties>
<dependencies>
<!-- junit -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<!-- hibernate對(duì)jpa的支持包 -->
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-entitymanager</artifactId>
<version>${project.hibernate.version}</version>
</dependency>
<!-- c3p0 -->
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-c3p0</artifactId>
<version>${project.hibernate.version}</version>
</dependency>
<!-- log日志 -->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
<!-- Mysql and MariaDB -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.6</version>
</dependency>
</dependencies>

在resources目錄下創(chuàng)建META-INF目錄,并在該目錄下創(chuàng)建persistence.xml文件
<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence
http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd"
version="2.0">
<!--配置持久化單元
name:持久化單元名稱(chēng)
transaction-type:事務(wù)類(lèi)型
RESOURCE_LOCAL:本地事務(wù)管理
JTA:分布式事務(wù)管理 -->
<persistence-unit name="myJpa" transaction-type="RESOURCE_LOCAL">
<!--配置JPA規(guī)范的服務(wù)提供商 -->
<provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
<properties>
<!-- 數(shù)據(jù)庫(kù)驅(qū)動(dòng) -->
<property name="javax.persistence.jdbc.driver" value="com.mysql.jdbc.Driver" />
<!-- 數(shù)據(jù)庫(kù)地址 -->
<property name="javax.persistence.jdbc.url" value="jdbc:mysql://localhost:3306/jpa?characterEncoding=utf-8" />
<!-- 數(shù)據(jù)庫(kù)用戶(hù)名 -->
<property name="javax.persistence.jdbc.user" value="root" />
<!-- 數(shù)據(jù)庫(kù)密碼 -->
<property name="javax.persistence.jdbc.password" value="root" />
<!--jpa提供者的可選配置:我們的JPA規(guī)范的提供者為hibernate,所以jpa的核心配置中兼容hibernate的 -->
<!--配置jpa實(shí)現(xiàn)方(hibernate)的配置信息
顯示sql : false|true
自動(dòng)創(chuàng)建數(shù)據(jù)庫(kù)表 : hibernate.hbm2ddl.auto
create : 程序運(yùn)行時(shí)創(chuàng)建數(shù)據(jù)庫(kù)表(如果有表,先刪除表再創(chuàng)建)
update :程序運(yùn)行時(shí)創(chuàng)建表(如果有表,不會(huì)創(chuàng)建表)
none :不會(huì)創(chuàng)建表
-->
<property name="hibernate.show_sql" value="true" />
<property name="hibernate.format_sql" value="true" />
<property name="hibernate.hbm2ddl.auto" value="create" />
</properties>
</persistence-unit>
</persistence>
創(chuàng)建和數(shù)據(jù)庫(kù)表映射的實(shí)體類(lèi)
package com.ithubei.entity;
import java.io.Serializable;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
/**
* @Entity
作用:指定當(dāng)前類(lèi)是實(shí)體類(lèi)。
@Table
作用:指定實(shí)體類(lèi)和表之間的對(duì)應(yīng)關(guān)系。
屬性:
name:指定數(shù)據(jù)庫(kù)表的名稱(chēng)
@Id
作用:指定當(dāng)前字段是主鍵。
@GeneratedValue
作用:指定主鍵的生成方式。。
屬性:
strategy :指定主鍵生成策略。
@Column
作用:指定實(shí)體類(lèi)屬性和數(shù)據(jù)庫(kù)表之間的對(duì)應(yīng)關(guān)系
屬性:
name:指定數(shù)據(jù)庫(kù)表的列名稱(chēng)。
unique:是否唯一
nullable:是否可以為空
inserttable:是否可以插入
updateable:是否可以更新
columnDefinition: 定義建表時(shí)創(chuàng)建此列的DDL
secondaryTable: 從表名。如果此列不建在主表上(默認(rèn)建在主表),該屬性定義該列所在從表的名字搭建開(kāi)發(fā)環(huán)境[重點(diǎn)]
* @author DELL
*
*/
@Entity //聲明該類(lèi)是和數(shù)據(jù)庫(kù)表映射的實(shí)體類(lèi)
@Table(name="cst_customer") //建立實(shí)體類(lèi)與表的映射關(guān)系
public class Customer implements Serializable{
@Id //聲明當(dāng)前私有屬性為主鍵
@GeneratedValue(strategy=GenerationType.IDENTITY) //配置主鍵的生成策略,為自增主鍵
@Column(name = "cust_id")
private Long custId;
@Column(name="cust_name") //指定和表中cust_name字段的映射關(guān)系
private String custName;
@Column(name="cust_source") //指定和表中cust_source字段的映射關(guān)系
private String custSource;
@Column(name="cust_industry")
private String custIndustry;
@Column(name="cust_level")
private String custLevel;
@Column(name="cust_address")
private String custAddress;
@Column(name="cust_phone")
private String custPhone;
public Long getCustId() {
return custId;
}
public void setCustId(Long custId) {
this.custId = custId;
}
public String getCustName() {
return custName;
}
public void setCustName(String custName) {
this.custName = custName;
}
public String getCustSource() {
return custSource;
}
public void setCustSource(String custSource) {
this.custSource = custSource;
}
public String getCustIndustry() {
return custIndustry;
}
public void setCustIndustry(String custIndustry) {
this.custIndustry = custIndustry;
}
public String getCustLevel() {
return custLevel;
}
public void setCustLevel(String custLevel) {
this.custLevel = custLevel;
}
public String getCustAddress() {
return custAddress;
}
public void setCustAddress(String custAddress) {
this.custAddress = custAddress;
}
public String getCustPhone() {
return custPhone;
}
public void setCustPhone(String custPhone) {
this.custPhone = custPhone;
}
}
創(chuàng)建工具類(lèi)JpaUtils
package com.ithubei.utils;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
/**
* 解決實(shí)體管理器工廠的浪費(fèi)資源和耗時(shí)問(wèn)題
* 通過(guò)靜態(tài)代碼塊的形式,當(dāng)程序第一次訪(fǎng)問(wèn)此工具類(lèi)時(shí),創(chuàng)建一個(gè)公共的實(shí)體管理器工廠對(duì)象
*
* 第一次訪(fǎng)問(wèn)getEntityManager方法:經(jīng)過(guò)靜態(tài)代碼塊創(chuàng)建一個(gè)factory對(duì)象,再調(diào)用方法創(chuàng)建一個(gè)EntityManager對(duì)象
* 第二次方法getEntityManager方法:直接通過(guò)一個(gè)已經(jīng)創(chuàng)建好的factory對(duì)象,創(chuàng)建EntityManager對(duì)象
*/
public class JpaUtils {
private static EntityManagerFactory entityManagerFactory;
static {
//1.加載配置文件,創(chuàng)建entityManagerFactory
entityManagerFactory = Persistence.createEntityManagerFactory("myJpa");
}
public static EntityManager getEntityManager() {
return entityManagerFactory.createEntityManager();
}
}
通過(guò)以上工具類(lèi),我們就可以得到EntityManager實(shí)體管理類(lèi)來(lái)進(jìn)行crud等操作。
在 JPA 規(guī)范中, EntityManager是完成持久化操作的核心對(duì)象。實(shí)體類(lèi)作為普通 java對(duì)象,只有在調(diào)用 EntityManager將其持久化后才會(huì)變成持久化對(duì)象。EntityManager對(duì)象在一組實(shí)體類(lèi)與底層數(shù)據(jù)源之間進(jìn)行 O/R 映射的管理。它可以用來(lái)管理和更新 Entity Bean, 根椐主鍵查找 Entity Bean, 還可以通過(guò)JPQL語(yǔ)句查詢(xún)實(shí)體。
我們可以通過(guò)調(diào)用EntityManager的方法完成獲取事務(wù),以及持久化數(shù)據(jù)庫(kù)的操作。
方法說(shuō)明:
getTransaction:獲取事務(wù)對(duì)象persist:保存操作merge:更新操作remove:刪除操作find(立即加載)/getReference(延遲加載):根據(jù)id查詢(xún)
現(xiàn)在我們就來(lái)通過(guò)EntityManager對(duì)象來(lái)進(jìn)行crud操作。
測(cè)試:
package com.ithubei.test;
import javax.persistence.EntityManager;
import javax.persistence.EntityTransaction;
import org.junit.Test;
import com.ithubei.entity.Customer;
import com.ithubei.utils.JpaUtils;
public class JpaTest {
/**
* 保存操作
*/
@Test
public void testSave() {
//通過(guò)工具類(lèi)來(lái)獲取EntityManager對(duì)象
EntityManager em = JpaUtils.getEntityManager();
//獲取事務(wù)對(duì)象
EntityTransaction tx = em.getTransaction();
tx.begin(); //開(kāi)啟事務(wù)
//完成增刪改查操作,保存一個(gè)用戶(hù)到數(shù)據(jù)庫(kù)中
Customer customer = new Customer();
customer.setCustName("授課");
customer.setCustIndustry("教育");
//保存操作
em.persist(customer);
tx.commit(); //提交事務(wù)
em.close(); //釋放資源
}
/**
* 保存一個(gè)實(shí)體
*/
@Test
public void testAdd() {
// 定義對(duì)象
Customer c = new Customer();
c.setCustName("傳智學(xué)院");
c.setCustLevel("VIP客戶(hù)");
c.setCustSource("網(wǎng)絡(luò)");
c.setCustIndustry("IT教育");
c.setCustAddress("昌平區(qū)北七家鎮(zhèn)");
c.setCustPhone("010-84389340");
EntityManager em = null;
EntityTransaction tx = null;
try {
// 獲取實(shí)體管理對(duì)象
em = JpaUtils.getEntityManager();
// 獲取事務(wù)對(duì)象
tx = em.getTransaction();
// 開(kāi)啟事務(wù)
tx.begin();
// 執(zhí)行操作
em.persist(c);
// 提交事務(wù)
tx.commit();
} catch (Exception e) {
// 回滾事務(wù)
tx.rollback();
e.printStackTrace();
} finally {
// 釋放資源
em.close();
}
}
/**
* 修改操作
*/
@Test
public void testMerge(){
//定義對(duì)象
EntityManager em=null;
EntityTransaction tx=null;
try{
//獲取實(shí)體管理對(duì)象
em=JpaUtils.getEntityManager();
//獲取事務(wù)對(duì)象
tx=em.getTransaction();
//開(kāi)啟事務(wù)
tx.begin();
//執(zhí)行操作
Customer c1 = em.find(Customer.class, 6L);
c1.setCustName("江蘇傳智學(xué)院");
em.clear();//把c1對(duì)象從緩存中清除出去
em.merge(c1);
//提交事務(wù)
tx.commit();
}catch(Exception e){
//回滾事務(wù)
tx.rollback();
e.printStackTrace();
}finally{
//釋放資源
em.close();
}
}
/**
* 刪除操作
*/
@Test
public void testRemove() {
// 定義對(duì)象
EntityManager em = null;
EntityTransaction tx = null;
try {
// 獲取實(shí)體管理對(duì)象
em = JpaUtils.getEntityManager();
// 獲取事務(wù)對(duì)象
tx = em.getTransaction();
// 開(kāi)啟事務(wù)
tx.begin();
// 執(zhí)行操作
Customer c1 = em.find(Customer.class, 6L);
em.remove(c1);
// 提交事務(wù)
tx.commit();
} catch (Exception e) {
// 回滾事務(wù)
tx.rollback();
e.printStackTrace();
} finally {
// 釋放資源
em.close();
}
}
/**
* 查詢(xún)操作find()
*/
@Test
public void testGetOne() {
// 定義對(duì)象
EntityManager em = null;
EntityTransaction tx = null;
try {
// 獲取實(shí)體管理對(duì)象
em = JpaUtils.getEntityManager();
// 獲取事務(wù)對(duì)象
tx = em.getTransaction();
// 開(kāi)啟事務(wù)
tx.begin();
// 執(zhí)行操作
Customer c1 = em.find(Customer.class, 96);
// 提交事務(wù)
tx.commit();
System.out.println(c1); // 輸出查詢(xún)對(duì)象
} catch (Exception e) {
// 回滾事務(wù)
tx.rollback();
e.printStackTrace();
} finally {
// 釋放資源
em.close();
}
}
}
雖然我們已經(jīng)使用EntityManager對(duì)象完成了JPA的新增改查操作,但是我們這里還要介紹另外一種查詢(xún)方式,那就是JPQL(java持久化查詢(xún)語(yǔ)言),JPQL與hibernate的HQL方式類(lèi)似。
package com.ithubei.test;
import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.EntityTransaction;
import javax.persistence.Query;
import org.junit.Test;
import com.ithubei.utils.JpaUtils;
/**
* 使用JPQL(java持久化查詢(xún)語(yǔ)言)來(lái)查詢(xún)數(shù)據(jù)
* @author DELL
*
*/
public class JpqlTest {
/**
* 查詢(xún)?nèi)康目蛻?hù)
*/
@Test
public void findAll() {
EntityManager em = null;
EntityTransaction tx = null;
try {
//獲取是管理對(duì)象
em = JpaUtils.getEntityManager();
//獲取事務(wù)對(duì)象
tx = em.getTransaction();
//開(kāi)啟事務(wù)
tx.begin();
String jpql = "from Customer";
//創(chuàng)建query對(duì)象
Query query = em.createQuery(jpql);
//使用query對(duì)象查詢(xún)客戶(hù)信息
List list = query.getResultList(); //查詢(xún)所有的客戶(hù)
for (Object object : list) {
System.out.println(object);
}
//提交事務(wù)
tx.commit();
}catch (Exception e) {
// TODO: handle exception
//發(fā)生異常進(jìn)行回滾
tx.rollback();
e.printStackTrace();
}finally {
//釋放資源
em.close();
}
}
//分頁(yè)查詢(xún)客戶(hù)
@Test
public void findPaged () {
EntityManager em = null;
EntityTransaction tx = null;
try {
//獲取實(shí)體管理對(duì)象
em = JpaUtils.getEntityManager();
//獲取事務(wù)對(duì)象
tx = em.getTransaction();
tx.begin();
//創(chuàng)建query對(duì)象
String jpql = "from Customer";
Query query = em.createQuery(jpql);
//起始索引
query.setFirstResult(0);
//每頁(yè)顯示條數(shù)
query.setMaxResults(2);
//查詢(xún)并得到返回結(jié)果
List list = query.getResultList(); //得到集合返回類(lèi)型
for (Object object : list) {
System.out.println(object);
}
tx.commit();
} catch (Exception e) {
// 回滾事務(wù)
tx.rollback();
e.printStackTrace();
} finally {
// 釋放資源
em.close();
}
}
//條件查詢(xún)
@Test
public void findCondition () {
EntityManager em = null;
EntityTransaction tx = null;
try {
//獲取實(shí)體管理對(duì)象
em = JpaUtils.getEntityManager();
//獲取事務(wù)對(duì)象
tx = em.getTransaction();
tx.begin();
//創(chuàng)建query對(duì)象
String jpql = "from Customer where custName like ? ";
Query query = em.createQuery(jpql);
//對(duì)占位符賦值,從1開(kāi)始
query.setParameter(1, "傳智%");
//查詢(xún)并得到返回結(jié)果
Object object = query.getSingleResult(); //得到唯一的結(jié)果集對(duì)象
System.out.println(object);
tx.commit();
} catch (Exception e) {
// 回滾事務(wù)
tx.rollback();
e.printStackTrace();
} finally {
// 釋放資源
em.close();
}
}
//根據(jù)客戶(hù)id倒序查詢(xún)所有客戶(hù)
//查詢(xún)所有客戶(hù)
@Test
public void testOrder() {
EntityManager em = null;
EntityTransaction tx = null;
try {
//獲取實(shí)體管理對(duì)象
em = JpaUtils.getEntityManager();
//獲取事務(wù)對(duì)象
tx = em.getTransaction();
tx.begin();
// 創(chuàng)建query對(duì)象
String jpql = "from Customer order by custId desc";
Query query = em.createQuery(jpql);
// 查詢(xún)并得到返回結(jié)果
List list = query.getResultList(); // 得到集合返回類(lèi)型
for (Object object : list) {
System.out.println(object);
}
tx.commit();
} catch (Exception e) {
// 回滾事務(wù)
tx.rollback();
e.printStackTrace();
} finally {
// 釋放資源
em.close();
}
}
//統(tǒng)計(jì)查詢(xún)
@Test
public void findCount() {
EntityManager em = null;
EntityTransaction tx = null;
try {
//獲取實(shí)體管理對(duì)象
em = JpaUtils.getEntityManager();
//獲取事務(wù)對(duì)象
tx = em.getTransaction();
tx.begin();
// 查詢(xún)?nèi)靠蛻?hù)
// 1.創(chuàng)建query對(duì)象
String jpql = "select count(custId) from Customer";
Query query = em.createQuery(jpql);
// 2.查詢(xún)并得到返回結(jié)果
Object count = query.getSingleResult(); // 得到集合返回類(lèi)型
System.out.println(count); //客戶(hù)人數(shù)
tx.commit();
} catch (Exception e) {
// 回滾事務(wù)
tx.rollback();
e.printStackTrace();
} finally {
// 釋放資源
em.close();
}
}
}
通過(guò)以上等操作,我們就完成了JPA的crud操作。
接下來(lái)我們就開(kāi)始使用spring data jpa來(lái)完成crud操作,讓我們體會(huì)一下什么叫優(yōu)勢(shì)。
spring data jpa的crud操作:
首先我們需要引入依賴(lài)
<properties>
<spring.version>4.2.4.RELEASE</spring.version>
<hibernate.version>5.0.7.Final</hibernate.version>
<slf4j.version>1.6.6</slf4j.version>
<log4j.version>1.2.12</log4j.version>
<c3p0.version>0.9.1.2</c3p0.version>
<mysql.version>5.1.6</mysql.version>
</properties>
<dependencies>
<!-- junit單元測(cè)試 -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.9</version>
<scope>test</scope>
</dependency>
<!-- spring beg -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.6.8</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-orm</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${spring.version}</version>
</dependency>
<!-- spring end -->
<!-- hibernate beg -->
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>${hibernate.version}</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-entitymanager</artifactId>
<version>${hibernate.version}</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
<version>5.2.1.Final</version>
</dependency>
<!-- hibernate end -->
<!-- c3p0 beg -->
<dependency>
<groupId>c3p0</groupId>
<artifactId>c3p0</artifactId>
<version>${c3p0.version}</version>
</dependency>
<!-- c3p0 end -->
<!-- log end -->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>${log4j.version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>${slf4j.version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>${slf4j.version}</version>
</dependency>
<!-- log end -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>${mysql.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-jpa</artifactId>
<version>1.9.0.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>4.2.4.RELEASE</version>
</dependency>
<!-- el beg 使用spring data jpa 必須引入 -->
<dependency>
<groupId>javax.el</groupId>
<artifactId>javax.el-api</artifactId>
<version>2.2.4</version>
</dependency>
<dependency>
<groupId>org.glassfish.web</groupId>
<artifactId>javax.el</artifactId>
<version>2.2.4</version>
</dependency>
<!-- el end -->
</dependencies>
創(chuàng)建spring配置文件applicationContext.xml,使用spring來(lái)管理
<?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:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context" xmlns:jdbc="http://www.springframework.org/schema/jdbc" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:jpa="http://www.springframework.org/schema/data/jpa" xmlns:task="http://www.springframework.org/schema/task" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd http://www.springframework.org/schema/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa.xsd"> <!-- 1.dataSource 配置數(shù)據(jù)庫(kù)連接池--> <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"> <property name="driverClass" value="com.mysql.jdbc.Driver" /> <property name="jdbcUrl" value="jdbc:mysql://localhost:3306/jpa?characterEncoding=utf-8" /> <property name="user" value="root" /> <property name="password" value="root" /> </bean> <!-- 2.配置entityManagerFactory --> <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"> <property name="dataSource" ref="dataSource" /> <property name="packagesToScan" value="com.ithubei.entity" /> <property name="persistenceProvider"> <bean class="org.hibernate.jpa.HibernatePersistenceProvider" /> </property> <!--JPA的供應(yīng)商適配器--> <property name="jpaVendorAdapter"> <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"> <property name="generateDdl" value="false" /> <property name="database" value="MYSQL" /> <property name="databasePlatform" value="org.hibernate.dialect.MySQLDialect" /> <property name="showSql" value="true" /> </bean> </property> <property name="jpaDialect"> <bean class="org.springframework.orm.jpa.vendor.HibernateJpaDialect" /> </property> </bean> <!-- 3.事務(wù)管理器--> <!-- JPA事務(wù)管理器 --> <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager"> <property name="entityManagerFactory" ref="entityManagerFactory" /> </bean> <!-- 整合spring data jpa--> <jpa:repositories base-package="com.ithubei.dao" transaction-manager-ref="transactionManager" entity-manager-factory-ref="entityManagerFactory"></jpa:repositories> <!-- 4.txAdvice--> <tx:advice id="txAdvice" transaction-manager="transactionManager"> <tx:attributes> <tx:method name="save*" propagation="REQUIRED"/> <tx:method name="insert*" propagation="REQUIRED"/> <tx:method name="update*" propagation="REQUIRED"/> <tx:method name="delete*" propagation="REQUIRED"/> <tx:method name="get*" read-only="true"/> <tx:method name="find*" read-only="true"/> <tx:method name="*" propagation="REQUIRED"/> </tx:attributes> </tx:advice> <!-- 5.aop--> <aop:config> <aop:pointcut id="pointcut" expression="execution(* com.ithubei.service.*.*(..))" /> <aop:advisor advice-ref="txAdvice" pointcut-ref="pointcut" /> </aop:config> <context:component-scan base-package="com.ithubei"></context:component-scan> <!--組裝其它 配置文件--> </beans>
創(chuàng)建和數(shù)據(jù)庫(kù)表映射的實(shí)體類(lèi)
package com.ithubei.entity;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
/**
*
* * 所有的注解都是使用JPA的規(guī)范提供的注解,
* * 所以在導(dǎo)入注解包的時(shí)候,一定要導(dǎo)入javax.persistence下的
*/
@Entity //聲明實(shí)體類(lèi)
@Table(name="cst_customer") //建立實(shí)體類(lèi)和表的映射關(guān)系
public class Customer {
@Id//聲明當(dāng)前私有屬性為主鍵
@GeneratedValue(strategy=GenerationType.IDENTITY) //配置主鍵的生成策略
@Column(name="cust_id") //指定和表中cust_id字段的映射關(guān)系
private Long custId;
@Column(name="cust_name") //指定和表中cust_name字段的映射關(guān)系
private String custName;
@Column(name="cust_source")//指定和表中cust_source字段的映射關(guān)系
private String custSource;
@Column(name="cust_industry")//指定和表中cust_industry字段的映射關(guān)系
private String custIndustry;
@Column(name="cust_level")//指定和表中cust_level字段的映射關(guān)系
private String custLevel;
@Column(name="cust_address")//指定和表中cust_address字段的映射關(guān)系
private String custAddress;
@Column(name="cust_phone")//指定和表中cust_phone字段的映射關(guān)系
private String custPhone;
public Long getCustId() {
return custId;
}
public void setCustId(Long custId) {
this.custId = custId;
}
public String getCustName() {
return custName;
}
public void setCustName(String custName) {
this.custName = custName;
}
public String getCustSource() {
return custSource;
}
public void setCustSource(String custSource) {
this.custSource = custSource;
}
public String getCustIndustry() {
return custIndustry;
}
public void setCustIndustry(String custIndustry) {
this.custIndustry = custIndustry;
}
public String getCustLevel() {
return custLevel;
}
public void setCustLevel(String custLevel) {
this.custLevel = custLevel;
}
public String getCustAddress() {
return custAddress;
}
public void setCustAddress(String custAddress) {
this.custAddress = custAddress;
}
public String getCustPhone() {
return custPhone;
}
public void setCustPhone(String custPhone) {
this.custPhone = custPhone;
}
}
創(chuàng)建dao層接口CustomerDao,并繼承JpaRepository和JpaSpecificationExecutor接口
/**
* 定義一個(gè)dao層接口,此接口只需要繼承JpaRepository和JpaSpecificationExecutor接口即可,該接口就具備了增刪改 * 查和分頁(yè)等功能。
* JpaRepository<實(shí)體類(lèi)類(lèi)型,主鍵類(lèi)型>:完成基本的CRUD操作
* JpaSpecificationExecutor<實(shí)體類(lèi)類(lèi)型>:用于復(fù)雜查詢(xún)(分頁(yè)等查詢(xún)操作)
* @author DELL
*
*/
public interface CustomerDao extends JpaRepository<Customer, Long>, JpaSpecificationExecutor<Customer>{
}
dao層編碼已經(jīng)寫(xiě)好了,現(xiàn)在我們就可以來(lái)測(cè)試CustomerDao來(lái)實(shí)現(xiàn)crud操作。
package com.ithubei.test;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import com.ithubei.dao.CustomerDao;
import com.ithubei.entity.Customer;
/**
* 測(cè)試:調(diào)用CustomerDao接口完成增刪改查就等操作
* @author DELL
*
*/
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations="classpath:applicationContext.xml")
public class CustomerDaoTest {
@Autowired
private CustomerDao customerDao;
/**
* 保存操作:調(diào)用save()方法
*/
@Test
public void testSave() {
Customer customer = new Customer();
customer.setCustName("黑馬程序員");
//保存
customerDao.save(customer);
}
/**
* 修改客戶(hù)信息:調(diào)用save()方法
* 對(duì)于save():如果執(zhí)行此方法時(shí)對(duì)象中存在id屬性,即為更新操作,會(huì)根據(jù)id查詢(xún),再更新
* 如果此方法中不存在id屬性,則為保存操作
*/
@Test
public void testUpdate() {
//先根據(jù)id查詢(xún)id為1的客戶(hù)
Customer customer = customerDao.findOne(96l);
//修改客戶(hù)名稱(chēng)
customer.setCustName("授課123");
//更新
customerDao.save(customer);
}
/**
* 刪除操作
*/
@Test
public void testDelete() {
customerDao.delete(96l);
}
/**
* 根據(jù)id查詢(xún):調(diào)用findOne()
*/
@Test
public void testFindById() {
Customer customer = customerDao.findOne(97l);
System.out.println(customer);
}
}
通過(guò)以上測(cè)試,我們發(fā)現(xiàn)CustomerDao接口下并沒(méi)有寫(xiě)任何的方法,但是它卻具備了crud等操作,只是因?yàn)樗^承了JpaRepository和JpaSpecificationExecutor兩個(gè)接口,我們就可以使用這兩個(gè)接口為我們提供的方法來(lái)進(jìn)行crud等操作。
現(xiàn)在我們就來(lái)看一下這兩個(gè)接口下的方法列表:


這兩個(gè)接口中定義了如此多的方法,方便我們?cè)谖覀冺?xiàng)目中完成基本的操作了。
spring data jpa是一個(gè)優(yōu)勢(shì),它減輕了我們的工作量。所以學(xué)會(huì)它是每個(gè)程序員應(yīng)該做的事情,建議大家都能夠去學(xué)好它。
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
Java實(shí)現(xiàn)幾種序列化方式總結(jié)
本篇文章主要介紹了Java實(shí)現(xiàn)幾種序列化方式總結(jié),包括Java原生以流的方法進(jìn)行的序列化、Json序列化、FastJson序列化、Protobuff序列化,有興趣的可以了解一下,2017-03-03
@JsonFormat?和?@DateTimeFormat?時(shí)間格式化注解(場(chǎng)景示例代碼)
這篇文章主要介紹了@JsonFormat和@DateTimeFormat時(shí)間格式化注解,本文通過(guò)場(chǎng)景示例代碼詳解給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2023-05-05
java控制臺(tái)實(shí)現(xiàn)學(xué)生信息管理系統(tǒng)
這篇文章主要為大家詳細(xì)介紹了java控制臺(tái)實(shí)現(xiàn)學(xué)生信息管理系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-02-02
java編譯時(shí)與運(yùn)行時(shí)概念與實(shí)例詳解
本篇文章通過(guò)實(shí)例對(duì) java程序編譯時(shí)與運(yùn)行時(shí)進(jìn)行了詳解,需要的朋友可以參考下2017-04-04
ActiveMQ簡(jiǎn)單入門(mén)(新手必看篇)
下面小編就為大家?guī)?lái)一篇ActiveMQ簡(jiǎn)單入門(mén)(新手必看篇)。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-06-06
springboot使用之多個(gè)filter的執(zhí)行順序以及配置方式
這篇文章主要介紹了springboot使用之多個(gè)filter的執(zhí)行順序以及配置方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-08-08

