Spring Data JPA的运行原理:
@PersistenceContext(name="entityManagerFactory")
private EntityManager em;
@Test
public void test1(){
//org.springframework.data.jpa.repository.support.SimpleJpaRepositor
y@fba8bf
//System.out.println(this.usersDao);
//class com.sun.proxy.$Proxy29 代理对象是基于JDK的动态代理方式
创建的
//System.out.println(this.usersDao.getClass());
JpaRepositoryFactory factory = new JpaRepositoryFactory(em);
//getRepository(UsersDao.class);可以帮助我们为接口生成实现类,而这个实现类是SimpleJpaRepository的对象
//要求:该接口必须要是继承 Repository 接口
UsersDao ud = factory.getRepository(UsersDao.class);
System.out.println(ud);
System.out.println(ud.getClass());
}
然后我们再次说下Spring Data的介绍,这样好带入查询:
Spring Data是什么?
Spring Data是一个用于简化数据库访问,并支持云服务的开源框架。其主要目标是使得对数据的访问变得方便快捷。
Spring Data JPA能干什么?
可以极大的简化JPA的写法,可以在几乎不用写实现的情况下,实现对数据的访问和操作,除了CRUD外,还包括如分页、排序等一些常用的功能。
Spring Data JPA提供的接口,Spring Data JPA的核心概念:
1:Repository:最顶层的接口,是一个空的接口,目的是为了统一所有Repository的类型,且能让组件扫描的时候自动识别。
2:CrudRepository :是Repository的子接口,提供CRUD的功能
3:PagingAndSortingRepository:是CrudRepository的子接口,添加分页和排序的功能
4:JpaRepository:是PagingAndSortingRepository的子接口,增加了一些实用的功能,比如:批量操作等。
5:JpaSpecificationExecutor:用来做负责查询的接口
6:Specification:是Spring Data JPA提供的一个查询规范,要做复杂的查询,只需围绕这个规范来设置查询条件
Repository 接口:
Repository 接口是 Spring Data JPA 中为我我们提供的所有接口中的顶层接口。
Repository 提供了两种查询方式的支持
1)基于方法名称命名规则查询
2)基于@Query 注解查询
一、方法名称命名规则查询
规则:findBy(关键字)+属性名称(属性名称的首字母大写)+查询条件(首字母大写)
如果打错字了,还是啥的,评论修正下哈(手动滑稽),其实还有很多的,只是我把一些常用的拿出来了。
结构:
Dao层的UsersDao 接口:
import com.msk.pojo.Users;
import org.springframework.data.repository.Repository;import java.util.List;/** Repository接口* @author Administrator**/
public interface UsersDao extends Repository<Users, Integer> {List<Users> findByUsernameIs(String string);List<Users> findByUsernameLike(String string);List<Users> findByUsernameAndUserageGreaterThanEqual(String name, Integer age);
}
实体bean Users:
package com.msk.pojo;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
@Table(name="t_users")
public class Users implements Serializable{@Id@GeneratedValue(strategy=GenerationType.IDENTITY)//strategy=GenerationType.IDENTITY 自增长@Column(name="userid")private Integer userid;@Column(name="username")private String username;@Column(name="userage")private Integer userage;public Integer getUserid() {return userid;}public void setUserid(Integer userid) {this.userid = userid;}public String getUsername() {return username;}public void setUsername(String username) {this.username = username;}public Integer getUserage() {return userage;}public void setUserage(Integer userage) {this.userage = userage;}@Overridepublic String toString() {return "Users [userid=" + userid + ", username=" + username + ", userage=" + userage + "]";}}
Test测试类:
package com.msk.test;import com.msk.dao.UsersDao;
import com.msk.pojo.Users;
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 java.util.List;/*** Repository接口测试* @author Administrator**/
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class RepositoryTest {@Autowiredprivate UsersDao usersDao;/*** 需求:使用用户名作为查询条件*/@Testpublic void test1(){/*** 判断相等的条件,有三种表示方式* 1,什么都不写,默认的就是做相等判断* 2,Is* 3,Equal*/List<Users> list = this.usersDao.findByUsernameIs("莫名其妙");for (Users users : list) {System.out.println(users);}}/*** 需求:根据用户姓名做Like处理* Like:条件关键字*/@Testpublic void test2(){List<Users> list = this.usersDao.findByUsernameLike("莫%");for (Users users : list) {System.out.println(users);}}/*** 需求:查询名称为莫淞凯,并且他的年龄大于等于22岁*/@Testpublic void test3(){List<Users> list = this.usersDao.findByUsernameAndUserageGreaterThanEqual("莫名其妙", 23);for (Users users : list) {System.out.println(users);}}
}
配置文件:
applicationContext.xml
<?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:aop="http://www.springframework.org/schema/aop" 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.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context.xsdhttp://www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop.xsdhttp://www.springframework.org/schema/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa.xsdhttp://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd"><!-- 配置读取properties文件的工具类 --><context:property-placeholder location="classpath:jdbc.properties"/><!-- 配置c3p0数据库连接池 --><bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"><property name="jdbcUrl" value="${jdbc.url}"/><property name="driverClass" value="${jdbc.driver.class}"/><property name="user" value="${jdbc.username}"/><property name="password" value="${jdbc.password}"/></bean><!-- Spring整合JPA 配置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"><!-- hibernate相关的属性的注入 --><!-- 配置数据库类型 --><property name="database" value="MYSQL"/><!-- 正向工程 自动创建表 --><property name="generateDdl" value="true"/><!-- 显示执行的SQL --><property name="showSql" value="true"/></bean></property><!-- 扫描实体的包 --><property name="packagesToScan"><list><value>com.msk.pojo</value></list></property></bean><!-- 配置Hibernate的事务管理器 --><bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager"><property name="entityManagerFactory" ref="entityManagerFactory"/></bean><!-- 配置开启注解事务处理 --><tx:annotation-driven transaction-manager="transactionManager"/><!-- 配置springIOC的注解扫描 --><context:component-scan base-package="com.msk"/><!-- Spring Data JPA 的配置 --><!-- base-package:扫描dao接口所在的包 --><jpa:repositories base-package="com.msk.dao"/>
</beans>
jdbc.properties:
jdbc.url=jdbc:mysql://localhost:3306/test
jdbc.driver.class=com.mysql.jdbc.Driver
jdbc.username=root
jdbc.password=root
二、基于@Query 注解的查询
通过 JPQL 语句查询
JPQL:通过Hibernate的HQL演变过来的,它和HQL语法及其相似。
接口中:
//使用@Query注解查询
@Query(value="from Users where username = ?")
List<Users> queryUserByNameUseJPQL(String name);
//参数名是随意定义,如果你只是一个参数,只要写一个问号,它直接会参数绑定,没问题,如果你具有多个参数的话,它解析起来,是从左至右的去绑定@Query("from Users where username like ?")
List<Users> queryUserByLikeNameUseJPQL(String name);@Query("from Users where username = ? and userage >= ?")
List<Users> queryUserByNameAndAge(String name,Integer age);
测试类:
/*** 测试@Query查询 JPQL*/
@Test
public void test4(){List<Users> list = this.usersDao.queryUserByNameUseJPQL("莫名其妙");for (Users users : list) {System.out.println(users);}
}/*** 测试@Query查询 JPQL*/
@Test
public void test5(){List<Users> list = this.usersDao.queryUserByLikeNameUseJPQL("莫%");for (Users users : list) {System.out.println(users);}
}/*** 测试@Query查询 JPQL*/
@Test
public void test6(){List<Users> list = this.usersDao.queryUserByNameAndAge("莫名其妙", 23);for (Users users : list) {System.out.println(users);}
}