黑马程序员spring data jpa 2019年第一版本
第一步首先创建一个maven工程,导入对于的pom依赖

<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.</modelVersion>
<groupId>com.cib.com</groupId>
<artifactId>heimaspringdatajpa</artifactId>
<version>0.0.-SNAPSHOT</version> <properties>
<!--版本锁定-->
<spring.version>5.0..RELEASE</spring.version>
<hibernate.version>5.0..Final</hibernate.version>
<slf4j.version>1.6.</slf4j.version>
<log4j.version>1.2.</log4j.version>
<c3p0.version>0.9.1.2</c3p0.version>
<mysql.version>5.1.</mysql.version>
</properties> <dependencies>
<!-- junit单元测试 -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency> <!-- spring beg -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.6.</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> <!-- spring对orm框架的支持包-->
<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-c3p0</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..Final</version>
</dependency>
<!-- hibernate 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> <!-- spring data jpa 的坐标-->
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-jpa</artifactId>
<version>1.9..RELEASE</version>
</dependency> <dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>${spring.version}</version>
</dependency> <!-- el beg 使用spring data jpa 必须引入 -->
<dependency>
<groupId>javax.el</groupId>
<artifactId>javax.el-api</artifactId>
<version>2.2.</version>
</dependency> <dependency>
<groupId>org.glassfish.web</groupId>
<artifactId>javax.el</artifactId>
<version>2.2.</version>
</dependency>
<!-- el end -->
</dependencies>
</project>
1、接下来创建jpa的核心配置文件
jpa的核心配置文件必须放在类路径的meta-info文件夹下面,命名也必须满足对于的规则
PA规范要求在类路径的META-INF目录下放置persistence.xml, 文件的名称是固定的,配置模板如下:
<!--必须要有name属性,不能为空 -->
     <persistence-unit name="myJap" transaction-type="RESOURCE_LOCAL">
这里
如果是分布式事务管理,这里就要配置为JTA,这里只操作一个数据库,这里不存在分布式事务,这里设置为RESOURCE_LOCAl



persistence.xml的内容如下所示
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.0" 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"> <!--必须要有name属性,不能为空 -->
<persistence-unit name="myJap" transaction-type="RESOURCE_LOCAL">
<!--可选 -->
<provider>org.hibernate.jpa.HibernatePersistenceProvider</provider> <!--厂商的特定属性 --> <properties>
<property name="javax.persistence.jdbc.driver" value="com.mysql.jdbc.Driver" />
<property name="javax.persistence.jdbc.url" value="jdbc:mysql://localhost:3306/jpa?useUnicode=true&characterEncoding=UTF-8" />
<property name="javax.persistence.jdbc.user" value="root" />
<property name="javax.persistence.jdbc.password" value="123456" />
<property name="hibernate.show_sql" value="true" />
<property name="hibernate.hbm2ddl.auto" value="update" />
</properties>
</persistence-unit> </persistence>
接下来,我们要编写实体类,创建对于的数据库表
创建客户的数据库表
drop table if exists cst_customer;
/*创建客户表*/
CREATE TABLE cst_customer (
cust_id bigint(32) NOT NULL AUTO_INCREMENT COMMENT '客户编号(主键)',
cust_name varchar(32) NOT NULL COMMENT '客户名称(公司名称)',
cust_source varchar(32) DEFAULT NULL COMMENT '客户信息来源',
cust_industry varchar(32) DEFAULT NULL COMMENT '客户所属行业',
cust_level varchar(32) DEFAULT NULL COMMENT '客户级别',
cust_address varchar(128) DEFAULT NULL COMMENT '客户联系地址',
cust_phone varchar(64) DEFAULT NULL COMMENT '客户联系电话',
PRIMARY KEY (`cust_id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=UTF8MB4; ————————————————
版权声明:本文为CSDN博主「底层_码农」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_40794973/article/details/98895832
注:表可以不用创建
3)创建、编写实体类和数据库表的映射配置[重点]
注解描述
@Entity:声明实体类】
@Table : 配置实体类和表的映射关系 , name : 配置数据库表的名称
/**
* @Id:声明主键的配置
* @GeneratedValue:配置主键的生成策略
* strategy
* GenerationType.IDENTITY :自增,mysql
* * 底层数据库必须支持自动增长(底层数据库支持的自动增长方式,对id自增)
* GenerationType.SEQUENCE : 序列,oracle
* * 底层数据库必须支持序列
* GenerationType.TABLE : jpa提供的一种机制,通过一张数据库表的形式帮助我们完成主键自增
* GenerationType.AUTO : 由程序自动的帮助我们选择主键生成策略
* @Column:配置属性和字段的映射关系
* name:数据库表中字段的名称
*/
/**
* 客户编号(主键)
*/
GenerationType.IDENTITY :自增,mysql
     *                 * 底层数据库必须支持自动增长(底层数据库支持的自动增长方式,对id自增) 必须和mysql中的  AUTO_INCREMENT一一对象,cust_id bigint(32) NOT NULL AUTO_INCREMENT COMMENT '客户编号(主键)',
@Column:配置属性和字段的映射关系
     *      name:数据库表中字段的名称
package com.itcast.domain; 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; /**
* 客户的实体类
* 配置映射关系
*
* 1.实体类和表的映射关系
* @Entity:声明实体类
* @Table : 配置实体类和表的映射关系
* name : 配置数据库表的名称
* 2.实体类中属性和表中字段的映射关系
*/
@Entity
@Table(name = "cst_customer")
public class Customer implements Serializable { /**
* @Id:声明主键的配置
* @GeneratedValue:配置主键的生成策略
* strategy
* GenerationType.IDENTITY :自增,mysql
* * 底层数据库必须支持自动增长(底层数据库支持的自动增长方式,对id自增)
* GenerationType.SEQUENCE : 序列,oracle
* * 底层数据库必须支持序列
* GenerationType.TABLE : jpa提供的一种机制,通过一张数据库表的形式帮助我们完成主键自增
* GenerationType.AUTO : 由程序自动的帮助我们选择主键生成策略
* @Column:配置属性和字段的映射关系
* name:数据库表中字段的名称
*/
/**
* 客户编号(主键)
*/
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "cust_id")
private Long custId;
/**
* 客户名称(公司名称)
*/
@Column(name = "cust_name")
private String custName;
/**
* 客户信息来源
*/
@Column(name="cust_source")
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;
} }
接下来我们就可以编写一个测试类,测试对于的jpa的操作
/**
	 * 测试jpa的保存
	 *      案例:保存一个客户到数据库中
	 *  Jpa的操作步骤
	 *     1.加载配置文件创建工厂(实体管理器工厂)对象
	 *     2.通过实体管理器工厂获取实体管理器
	 *     3.获取事务对象,开启事务
	 *     4.完成增删改查操作
	 *     5.提交事务(回滚事务)
	 *     6.释放资源
	 */
package com.itcast.cn; import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityTransaction;
import javax.persistence.Persistence; import org.junit.Test; import com.itcast.domain.Customer; public class TestJpa { /**
* 测试jpa的保存
* 案例:保存一个客户到数据库中
* Jpa的操作步骤
* 1.加载配置文件创建工厂(实体管理器工厂)对象
* 2.通过实体管理器工厂获取实体管理器
* 3.获取事务对象,开启事务
* 4.完成增删改查操作
* 5.提交事务(回滚事务)
* 6.释放资源
*/
@Test
public void testSave() {
//1.加载配置文件创建工厂(实体管理器工厂)对象
EntityManagerFactory factory = Persistence.createEntityManagerFactory("myJap");
//2.通过实体管理器工厂获取实体管理器
EntityManager em = factory.createEntityManager(); //3.获取事务对象,开启事务
EntityTransaction tx = em.getTransaction(); //获取事务对象
tx.begin();//开启事务
try{
//4.完成增删改查操作:保存一个客户到数据库中
Customer customer = new Customer();
customer.setCustName("蔡徐坤");
customer.setCustIndustry("明星");
customer.setCustSource("bibi");
//保存
em.persist(customer); //保存操作
//5.提交事务
tx.commit();
}catch (Exception e){
tx.rollback();//回滚事务
e.printStackTrace();
}finally {
//6.释放资源
em.close();
//关闭工厂
factory.close();
} }
}
运行的sql语句如下所示
log4j:WARN No appenders could be found for logger (org.jboss.logging).
log4j:WARN Please initialize the log4j system properly.
Hibernate: insert into cst_customer (cust_address, cust_industry, cust_level, cust_name, cust_phone, cust_source) values (?, ?, ?, ?, ?, ?)
GenerationType.TABLE : jpa提供的一种机制,通过一张数据库表的形式帮助我们完成主键自增,jpa会另外生成一张表帮助我们进行主键的管理

GenerationType.AUTO : 由程序自动的帮助我们选择主键生成策略

多个线程在内存中共享一份Factory对象,减少Factory对象创建消耗资源

采用静态代码块的方法,减少Factory资源创建消耗性能的问题
1. 抽取JPAUtil工具类
package com.itcast.utils; import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence; /**
* 解决实体管理器工厂的浪费资源和耗时问题
* 通过静态代码块的形式,当程序第一次访问此工具类时,创建一个公共的实体管理器工厂对象
*
* 第一次访问getEntityManager方法:经过静态代码块创建一个factory对象,再调用方法创建一个EntityManager对象
* 第二次方法getEntityManager方法:直接通过一个已经创建好的factory对象,创建EntityManager对象
*/
public class JpaUtils {
private static EntityManagerFactory factory; static {
//1.加载配置文件,创建entityManagerFactory
factory = Persistence.createEntityManagerFactory("myJpa");
}
/**
* 获取EntityManager对象
*/
public static EntityManager getEntityManager() {
return factory.createEntityManager();
}
}
我们在编写一个测试类进行测试
解决创建 EntityManagerFactory 浪费资源问题
3. 测试查询
查询有两个方法,注意区别
package com.itcast.cn; import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityTransaction;
import javax.persistence.Persistence; import org.junit.Test; import com.itcast.domain.Customer;
import com.itcast.utils.JpaUtils; public class TestJpa { /**
* 测试jpa的保存
* 案例:保存一个客户到数据库中
* Jpa的操作步骤
* 1.加载配置文件创建工厂(实体管理器工厂)对象
* 2.通过实体管理器工厂获取实体管理器
* 3.获取事务对象,开启事务
* 4.完成增删改查操作
* 5.提交事务(回滚事务)
* 6.释放资源
*/
@Test
public void testSave() {
//1.加载配置文件创建工厂(实体管理器工厂)对象
EntityManagerFactory factory = Persistence.createEntityManagerFactory("myJap");
//2.通过实体管理器工厂获取实体管理器
EntityManager em = factory.createEntityManager(); //3.获取事务对象,开启事务
EntityTransaction tx = em.getTransaction(); //获取事务对象
tx.begin();//开启事务
try{
//4.完成增删改查操作:保存一个客户到数据库中
Customer customer = new Customer();
customer.setCustName("蔡徐坤");
customer.setCustIndustry("明星");
customer.setCustSource("bibi");
//保存
em.persist(customer); //保存操作
//5.提交事务
tx.commit();
}catch (Exception e){
tx.rollback();//回滚事务
e.printStackTrace();
}finally {
//6.释放资源
em.close();
//关闭工厂
factory.close();
} } @Test
public void testtestSave02(){
//1.获取工厂(实体管理器工厂)对象
EntityManager em = JpaUtils.getEntityManager();
//3.获取事务对象,开启事务
EntityTransaction tx = em.getTransaction(); //获取事务对象
tx.begin();//开启事务
//4.完成增删改查操作:保存一个客户到数据库中
Customer customer = new Customer();
customer.setCustName("蔡徐坤");
customer.setCustIndustry("明星");
customer.setCustSource("bibi");
//保存
em.persist(customer); //保存操作
//5.提交事务
tx.commit();
//6.释放资源
em.close();
} /**
* 根据id查询客户
* 使用find方法查询:
* 1.查询的对象就是当前客户对象本身
* 2.在调用find方法的时候,就会发送sql语句查询数据库
*
* 立即加载
*/
@Test
public void testFind() {
//1.通过工具类获取entityManager
EntityManager entityManager = JpaUtils.getEntityManager();
//3.增删改查 -- 根据id查询客户
/**
* find : 根据id查询数据
* class:查询数据的结果需要包装的实体类类型的字节码
* id:查询的主键的取值
* 没有返回 null
*/
Customer customer = entityManager.find(Customer.class, 1L);//打断点
//不管打不打印(使用),执行到上一条语句时,都会发送SQL语句
//System.out.print(customer);
//class com.bug.domain.Customer
System.out.println(customer.toString());
//5.释放资源
entityManager.close(); } /**
* 根据id查询客户
* getReference方法
* 1.获取的对象是一个动态代理对象
* 2.调用getReference方法不会立即发送sql语句查询数据库
* * 当调用查询结果对象的时候,才会发送查询的sql语句:什么时候用,什么时候发送sql语句查询数据库
*
* 延迟加载(懒加载)
* * 得到的是一个动态代理对象
* * 什么时候用,什么使用才会查询
*/
@Test
public void testReference() {
//1.通过工具类获取entityManager
EntityManager entityManager = JpaUtils.getEntityManager();
//3.增删改查 -- 根据id查询客户
/**
* getReference : 根据id查询数据
* class:查询数据的结果需要包装的实体类类型的字节码
* id:查询的主键的取值
*/
Customer customer = entityManager.getReference(Customer.class, 1L);//打断点
//这里不打印(不使用)就不会发送SQL语句
//System.out.print(customer);
//class com.bug.domain.Customer_$$_jvst88e_0 代理对象
System.out.println("\n\n");
System.out.println(customer.toString());
//5.释放资源
entityManager.close();
} }
//3.增删改查 -- 根据id查询客户
        /**
         * getReference : 根据id查询数据
         *      class:查询数据的结果需要包装的实体类类型的字节码
         *      id:查询的主键的取值
         */
getReference 是懒加载,在find查询语句的时候不会发起sql语句查询,在实际使用使用System.out.print(customer)的时候才发起sql语句进行查询,返回的查询结果是一个代理对象
4. 测试删除
@Test
public void testRemove() {
//1.通过工具类获取entityManager
EntityManager entityManager = JpaUtils.getEntityManager();
//3.增删改查 -- 删除客户
//3.获取事务对象,开启事务
EntityTransaction tx = entityManager.getTransaction(); //获取事务对象
tx.begin();//开启事务
//i 根据id查询客户
Customer customer = entityManager.find(Customer.class, 1L);
System.out.println(customer);
if(customer != null){
//ii 调用remove方法完成删除操作
entityManager.remove(customer);
}
//5.提交事务
tx.commit();
//5.释放资源
entityManager.close();
}
7.JPA中的复杂查询
JPQL全称Java Persistence Query Language,Java持久化查询语言(JPQL),它是一种可移植的查询语言,旨在以面向对象表达式语言的表达式,将SQL语法和简单查询语义绑定在一起·使用这种语言编写的查询是可移植的,可以被编译成所有主流数据库服务器上的SQL。
其特征与原生SQL语句类似,并且完全面向对象,通过类名和属性访问,而不是表名和表的属性。
jpql语句不能写select *,但是能够写select 加上对象的属性值
查询数据库 表中存在多少条记录

//统计查询
@Test
public void findCount() {
EntityManager em = null;
EntityTransaction tx = null;
try {
//获取实体管理对象
em = JPAUtil.getEntityManager();
//获取事务对象
tx = em.getTransaction();
tx.begin();
// 查询全部客户
// 1.创建query对象
String jpql = "select count(custId) from Customer";
Query query = em.createQuery(jpql);
// 2.查询并得到返回结果
Object count = query.getSingleResult(); // 得到集合返回类型
System.out.println(count);
tx.commit();
} catch (Exception e) {
// 回滚事务
tx.rollback();
e.printStackTrace();
} finally {
// 释放资源
em.close();
}
}
————————————————
版权声明:本文为CSDN博主「I Java」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/zlx_508/article/details/97005499
记录总数只有一条记录,使用getSingleResult,返回一条记录
分页查询

0表示查询第一页,2表示第一页显示2条记录
//分页查询客户
@Test
public void findPaged () {
EntityManager em = null;
EntityTransaction tx = null;
try {
//获取实体管理对象
em = JPAUtil.getEntityManager();
//获取事务对象
tx = em.getTransaction();
tx.begin(); //创建query对象
String jpql = "from Customer";
Query query = em.createQuery(jpql);
//起始索引
query.setFirstResult();
//每页显示条数
query.setMaxResults();
//查询并得到返回结果
List list = query.getResultList(); //得到集合返回类型
for (Object object : list) {
System.out.println(object);
}
tx.commit();
} catch (Exception e) {
// 回滚事务
tx.rollback();
e.printStackTrace();
} finally {
// 释放资源
em.close();
}
}
————————————————
版权声明:本文为CSDN博主「I Java」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/zlx_508/article/details/97005499
接下来我们讲解条件查询

//条件查询
@Test
public void findCondition () {
EntityManager em = null;
EntityTransaction tx = null;
try {
//获取实体管理对象
em = JPAUtil.getEntityManager();
//获取事务对象
tx = em.getTransaction();
tx.begin();
//创建query对象
String jpql = "from Customer where custName like ? ";
Query query = em.createQuery(jpql);
//对占位符赋值,从1开始
query.setParameter(, "传智播客%");
//查询并得到返回结果
Object object = query.getSingleResult(); //得到唯一的结果集对象
System.out.println(object);
tx.commit();
} catch (Exception e) {
// 回滚事务
tx.rollback();
e.printStackTrace();
} finally {
// 释放资源
em.close();
}
}
————————————————
版权声明:本文为CSDN博主「I Java」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/zlx_508/article/details/97005499
接下来重点讲解spring -data-jpa
这里配置文件有点问题,不清楚的看佟刚spring data的视频教程


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.</modelVersion>
<groupId>com.cib.com</groupId>
<artifactId>heimaspringdatajpa</artifactId>
<version>0.0.-SNAPSHOT</version> <properties>
<!--版本锁定-->
<spring.version>5.0..RELEASE</spring.version>
<hibernate.version>5.0..Final</hibernate.version>
<slf4j.version>1.6.</slf4j.version>
<log4j.version>1.2.</log4j.version>
<c3p0.version>0.9.1.2</c3p0.version>
<mysql.version>5.1.</mysql.version>
</properties> <dependencies>
<!-- junit单元测试 -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency> <!-- spring beg -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.6.</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> <!-- spring对orm框架的支持包-->
<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-c3p0</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..Final</version>
</dependency>
<!-- hibernate 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> <!-- spring data jpa 的坐标-->
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-jpa</artifactId>
<version>1.9..RELEASE</version>
</dependency> <dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>${spring.version}</version>
</dependency> <!-- el beg 使用spring data jpa 必须引入 -->
<dependency>
<groupId>javax.el</groupId>
<artifactId>javax.el-api</artifactId>
<version>2.2.</version>
</dependency> <dependency>
<groupId>org.glassfish.web</groupId>
<artifactId>javax.el</artifactId>
<version>2.2.</version>
</dependency>
<!-- el end -->
</dependencies>
</project>
db.properties的配置如下
jdbc.user=root
jdbc.password=
jdbc.driverClass=com.mysql.jdbc.Driver
jdbc.jdbcUrl=jdbc:mysql:///jpa
<?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"> <!-- 配置自动扫描的包 -->
<context:component-scan base-package="com.atguigu.springdata"></context:component-scan> <!-- . 配置数据源 -->
<context:property-placeholder location="classpath:db.properties"/> <bean id="dataSource"
class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="user" value="${jdbc.user}"></property>
<property name="password" value="${jdbc.password}"></property>
<property name="driverClass" value="${jdbc.driverClass}"></property>
<property name="jdbcUrl" value="${jdbc.jdbcUrl}"></property> <!-- 配置其他属性 -->
</bean> <!-- . 配置 JPA 的 EntityManagerFactory -->
<bean id="entityManagerFactory"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSource"></property>
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"></bean>
</property>
<property name="packagesToScan" value="com.atguigu.springdata"></property>
<property name="jpaProperties">
<props>
<!-- 二级缓存相关 -->
<!--
<prop key="hibernate.cache.region.factory_class">org.hibernate.cache.ehcache.EhCacheRegionFactory</prop>
<prop key="net.sf.ehcache.configurationResourceName">ehcache-hibernate.xml</prop>
-->
<!-- 生成的数据表的列的映射策略 -->
<prop key="hibernate.ejb.naming_strategy">org.hibernate.cfg.ImprovedNamingStrategy</prop>
<!-- hibernate 基本属性 -->
<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> <!-- . 配置事务管理器 -->
<bean id="transactionManager"
class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory"></property>
</bean> <!-- . 配置支持注解的事务 -->
<tx:annotation-driven transaction-manager="transactionManager"/> <!-- . 配置 SpringData -->
<!-- 加入 jpa 的命名空间 -->
<!-- base-package: 扫描 Repository Bean 所在的 package -->
<jpa:repositories base-package="com.atguigu.springdata"
entity-manager-factory-ref="entityManagerFactory"></jpa:repositories> </beans>
这里有几个配置很关键
<jpa:repositories base-package="com.atguigu.springdata" 指定扫描@Reporisty注解的包
<property name="packagesToScan" value="com.atguigu.springdata"></property>指定@Entiry注解的包
<context:component-scan base-package="com.atguigu.springdata"></context:component-scan>指定spring @service @compent所在的包路径
接下来我们创建包com.atguigu.springdata,所有在的操作都在这个包下面
接下来我们创建实体类
package com.atguigu.springdata;
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 // 声明此类是个实体类 需要导入javax.persistence.Entity; @Table(name = "cst_customer") //需要将该类对应到数据库中的哪一个表中,name中填表的名称 public class Customer { @Id //声明主键 @GeneratedValue(strategy = GenerationType.IDENTITY) //声明主键的生成策略为自动递增 //mysql使用自增模式,orcle 使用序列模式 @Column(name = "cust_id") //设置该属性和数据库中的哪一个字段对应 private Long custId; @Column(name = "cust_name") private String custName; @Column(name = "cust_source") private String custSource; @Column(name = "cust_level") private String custLevel; @Column(name = "cust_industry") private String cusIndustry; @Column(name = "cust_phone") private String custPhone; @Column(name = "cust_address") private String custAddress; 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 getCustLevel() { return custLevel; } public void setCustLevel(String custLevel) { this.custLevel = custLevel; } public String getCusIndustry() { return cusIndustry; } public void setCusIndustry(String cusIndustry) { this.cusIndustry = cusIndustry; } public String getCustPhone() { return custPhone; } public void setCustPhone(String custPhone) { this.custPhone = custPhone; } public String getCustAddress() { return custAddress; } public void setCustAddress(String custAddress) { this.custAddress = custAddress; } @Override public String toString() { return "Customer [custId=" + custId + ", custName=" + custName + ", custSource=" + custSource + ", custLevel=" + custLevel + ", cusIndustry=" + cusIndustry + ", custPhone=" + custPhone + ", custAddress=" + custAddress + "]"; } }
实体类创建成功之后,接下来我们就可以编写jpa的接口进行增删改查的操作了,只需要编写jpa接口,不需要编写jpa的实现类
关键点:
1.编写dao层的接口就可以了,不需要dao接口的实现类
2、编写的dao接口的规范如下

SpringDataJPA通过实现接口(代理的形式)进行简单的CRUD
https://blog.csdn.net/qq_42041712/article/details/94451572
JpaRepository<Customer,Long> 第一个参数是我们要操作的实体类类型,第二个参数是实体类的主键
JpaSpecificationExecutor<Customer> 参数是我们要操作的实体类的类型
package com.atguigu.springdata; import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor; /*
* 符合SpringDatajpa的dao层接口规范
*JpaRepository<操作的实体类类型,实体类中主键属性的类型>
*封装了基本的CRUD操作
JpaSpecificationExecutor<操作的实体类类型>
*封装了复杂查询操作(分页)
* */ public interface CustomerDao extends JpaRepository<Customer,Long>, JpaSpecificationExecutor<Customer>
{ }
接下来编写好接口之后,就可以进行增加删除操作数据库了,注意CustomerDao没有使用注解,只要放在<jpa:repositories base-package="com.atguigu.springdata"对于的包下面就可以了

我们可以编写一个测试类进行操作,首先保证数据库中存在数据

import java.io.FileNotFoundException;
import java.io.IOException;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.stream.Collector;
import java.util.stream.Collectors; import javax.persistence.EntityManager;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Path;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import javax.sql.DataSource; import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.data.domain.Sort.Direction;
import org.springframework.data.domain.Sort.Order;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import com.atguigu.springdata.CustomerDao;
import com.itcast.domain.Customer;
import com.itcast.utils.JpaUtils; @RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations="classpath:applicationContext.xml")
public class SpringDataTest { @Autowired
private CustomerDao dao; @Test
public void testFind() { com.atguigu.springdata.Customer customer = dao.findOne((long) 2);
System.out.println(customer.toString());
} }
测试的结果如下

在eclipse中查看一个类及其父类中的所有方法和属性
只需要连续按两次Ctrl+O
JpaRepository默认实现了下面的方法

在eclipse中查看一个类的集成关系
只需要连续按两次Ctrl+T

JpaRepository继承自PagingAndSortingRepository,PagingAndSortingRepository继承自CrudRepository,CrudRepository集成自Repository
import java.io.FileNotFoundException;
import java.io.IOException;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.stream.Collector;
import java.util.stream.Collectors; import javax.persistence.EntityManager;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Path;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import javax.sql.DataSource; import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.data.domain.Sort.Direction;
import org.springframework.data.domain.Sort.Order;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import com.atguigu.springdata.Customer;
import com.atguigu.springdata.CustomerDao;
import com.itcast.utils.JpaUtils; @RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations="classpath:applicationContext.xml")
public class SpringDataTest { @Autowired
private CustomerDao customerDao; @Test
public void testFind() { com.atguigu.springdata.Customer customer = customerDao.findOne((long) 2);
System.out.println(customer.toString());
} /** * 保存客户:调用save(obj)方法 */ @Test public void testSave() { Customer c = new Customer(); c.setCustName("传智播客"); customerDao.save(c); } /** * 修改客户:调用save(obj)方法 * 对于save方法的解释:如果执行此方法是对象中存在id属性,即为更新操作会先根据id查询,再更新 * 如果执行此方法中对象中不存在id属性,即为保存操作 * */ @Test public void testUpdate() { //根据id查询id为1的客户 Customer customer = customerDao.findOne(1l); //修改客户名称 customer.setCustName("传智播客顺义校区"); //更新 customerDao.save(customer); } }
/**
* 根据id删除:调用delete(id)方法
*/
@Test
public void testDelete() {
customerDao.delete(1l);
}




import java.io.FileNotFoundException;
import java.io.IOException;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.stream.Collector;
import java.util.stream.Collectors; import javax.persistence.EntityManager;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Path;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import javax.sql.DataSource; import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.data.domain.Sort.Direction;
import org.springframework.data.domain.Sort.Order;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import com.atguigu.springdata.Customer;
import com.atguigu.springdata.CustomerDao;
import com.itcast.utils.JpaUtils; @RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations="classpath:applicationContext.xml")
public class SpringDataTest { @Autowired
private CustomerDao customerDao; @Test
public void testFind() { com.atguigu.springdata.Customer customer = customerDao.findOne((long) 2);
System.out.println(customer.toString());
} /** * 保存客户:调用save(obj)方法 */ @Test public void testSave() { Customer c = new Customer(); c.setCustName("传智播客"); customerDao.save(c); } /** * 修改客户:调用save(obj)方法 * 对于save方法的解释:如果执行此方法是对象中存在id属性,即为更新操作会先根据id查询,再更新 * 如果执行此方法中对象中不存在id属性,即为保存操作 * */ @Test public void testUpdate() { //根据id查询id为1的客户 Customer customer = customerDao.findOne(1l); //修改客户名称 customer.setCustName("传智播客顺义校区"); //更新 customerDao.save(customer); } @Test public void testCount() {
long count = customerDao.count();
System.out.println(count);
} @Test public void testExits() {
boolean exists = customerDao.exists((long) 2); System.out.println(exists);
} }

    @Test
    @Transactional
    public void testGetOne() {
          Customer one = customerDao.getOne((long) 2);
          System.out.println(one);
    }
    
getOne是懒加载,findOne是直接加载,懒加载的实现需要依赖事务,所有使用getOne方法的时候,一定要引入事务管理的依赖,这里使用 @Transactiona,否则代码会报错
3.2 使用JPQL的方式查询
使用Spring Data JPA提供的查询方法已经可以解决大部分的应用场景,但是对于某些业务来说,我们还需要灵活的构造查询条件,这时就可以使用@Query注解,结合JPQL的语句方式完成查询

package com.atguigu.springdata; import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.data.jpa.repository.Query;
import org.springframework.stereotype.Repository; import antlr.collections.List; /*
* 符合SpringDatajpa的dao层接口规范
*JpaRepository<操作的实体类类型,实体类中主键属性的类型>
*封装了基本的CRUD操作
JpaSpecificationExecutor<操作的实体类类型>
*封装了复杂查询操作(分页)
* */ public interface CustomerDao extends JpaRepository<Customer,Long>, JpaSpecificationExecutor<Customer>
{ //@Query 使用jpql的方式查询。?1代表参数的占位符,其中1对应方法中的参数索引 @Query(value="from Customer where custName = ?1") public Customer findCustomer(String custName); }
//@Query 使用jpql的方式查询。?1代表参数的占位符,其中1对应方法中的参数索引

2表示的是输入参数为name,1表示输入的参数是id

此外,也可以通过使用 @Query 来执行一个更新操作,为此,我们需要在使用 @Query 的同时,用 @Modifying 来将该操作标识为修改查询,这样框架最终会生成一个更新的操作,而非查询
package com.atguigu.springdata; import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
import org.springframework.stereotype.Repository; import antlr.collections.List; /*
* 符合SpringDatajpa的dao层接口规范
*JpaRepository<操作的实体类类型,实体类中主键属性的类型>
*封装了基本的CRUD操作
JpaSpecificationExecutor<操作的实体类类型>
*封装了复杂查询操作(分页)
* */ public interface CustomerDao extends JpaRepository<Customer,Long>, JpaSpecificationExecutor<Customer>
{ //@Query 使用jpql的方式查询。?1代表参数的占位符,其中1对应方法中的参数索引 @Query(value="from Customer where custName = ?1") public Customer findCustomer(String custName); @Query(value="update Customer set custName = ?1 where custId = ?2") @Modifying public void updateCustomer(String custName,Long custId); }
执行更新或者删除操作,必须需要添加 @Modifying,此外必须要具有事务操作
@Test
@Transactional
@Rollback(value=false)
public void testupdateCustomer() {
customerDao.updateCustomer("我是可不2222", (long) 2);
}
执行更新删除操作需要有事务所有上面有@Transactional,此外jpa执行事务操作完成之后默认会回滚,当数据更新操作成功之后,因为jpa默认要回滚,会把更新的数据还原回去,我们要在数据库中看到更新的
数据,我们要禁止jpa的回滚@Rollback(value=false)

3.3 使用SQL语句查询
Spring Data JPA同样也支持sql语句的查询,如下:


package com.atguigu.springdata; import java.util.List; import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
import org.springframework.stereotype.Repository; /*
* 符合SpringDatajpa的dao层接口规范
*JpaRepository<操作的实体类类型,实体类中主键属性的类型>
*封装了基本的CRUD操作
JpaSpecificationExecutor<操作的实体类类型>
*封装了复杂查询操作(分页)
* */ public interface CustomerDao extends JpaRepository<Customer,Long>, JpaSpecificationExecutor<Customer>
{ //@Query 使用jpql的方式查询。?1代表参数的占位符,其中1对应方法中的参数索引 @Query(value="from Customer where custName = ?1") public Customer findCustomer(String custName); @Query(value="update Customer set custName = ?1 where custId = ?2")
@Modifying
public void updateCustomer(String custName,Long custId); /** * nativeQuery : 使用本地sql的方式查询 */ @Query(value="select * from cst_customer",nativeQuery=true) public List<Object[]> findSql(); }
这里千万要注意返回的是一个List<Object[]>,每一个元素是一个Object类型的数组,不能写成List<Customer[]>
@Test
public void testfindSql() {
List<Object[]> datas = customerDao.findSql(); for(Object[] data:datas){ System.out.println(Arrays.toString(data));
} }
package com.atguigu.springdata; import java.util.List; import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
import org.springframework.stereotype.Repository; /*
* 符合SpringDatajpa的dao层接口规范
*JpaRepository<操作的实体类类型,实体类中主键属性的类型>
*封装了基本的CRUD操作
JpaSpecificationExecutor<操作的实体类类型>
*封装了复杂查询操作(分页)
* */ public interface CustomerDao extends JpaRepository<Customer,Long>, JpaSpecificationExecutor<Customer>
{ //@Query 使用jpql的方式查询。?1代表参数的占位符,其中1对应方法中的参数索引 @Query(value="from Customer where custName = ?1") public Customer findCustomer(String custName); @Query(value="update Customer set custName = ?1 where custId = ?2")
@Modifying
public void updateCustomer(String custName,Long custId); /** * nativeQuery : 使用本地sql的方式查询 */ @Query(value="select * from cst_customer",nativeQuery=true) public List<Object[]> findSql(); @Query(value = "select * from cst_customer where cust_name like ?1",nativeQuery = true)
public List<Object []> findSql2(String name);
}
测试代码
import java.io.FileNotFoundException;
import java.io.IOException;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.stream.Collector;
import java.util.stream.Collectors; import javax.persistence.EntityManager;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Path;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import javax.sql.DataSource; import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.data.domain.Sort.Direction;
import org.springframework.data.domain.Sort.Order;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.data.jpa.repository.Query;
import org.springframework.test.annotation.Rollback;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.transaction.annotation.Transactional; import com.atguigu.springdata.Customer;
import com.atguigu.springdata.CustomerDao;
import com.itcast.utils.JpaUtils; @RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations="classpath:applicationContext.xml")
public class SpringDataTest { @Autowired
private CustomerDao customerDao; @Test
public void testFind() { com.atguigu.springdata.Customer customer = customerDao.findOne((long) 2);
System.out.println(customer.toString());
} /** * 保存客户:调用save(obj)方法 */ @Test public void testSave() { Customer c = new Customer(); c.setCustName("传智播客"); customerDao.save(c); } /** * 修改客户:调用save(obj)方法 * 对于save方法的解释:如果执行此方法是对象中存在id属性,即为更新操作会先根据id查询,再更新 * 如果执行此方法中对象中不存在id属性,即为保存操作 * */ @Test public void testUpdate() { //根据id查询id为1的客户 Customer customer = customerDao.findOne(1l); //修改客户名称 customer.setCustName("传智播客顺义校区"); //更新 customerDao.save(customer); } @Test public void testCount() {
long count = customerDao.count();
System.out.println(count);
} @Test public void testExits() {
boolean exists = customerDao.exists((long) 2); System.out.println(exists);
} @Test @Transactional
public void testGetOne() {
Customer one = customerDao.getOne((long) 2); System.out.println(one);
} @Test
@Transactional
@Rollback(value=false)
public void testupdateCustomer() {
customerDao.updateCustomer("我是可不2222", (long) 2);
} @Test
public void testfindSql() {
List<Object[]> datas = customerDao.findSql(); for(Object[] data:datas){ System.out.println(Arrays.toString(data));
} } //测试sql查询
@Test
public void testFindSql()
{ List<Object[]> list = customerDao.findSql2("迅腾软件%");//模糊查询
for(Object[] obj: list){ System.out.println(Arrays.toString(obj));
}
} }
3.4 方法命名规则查询
顾名思义,方法命名规则查询就是根据方法的名字,就能创建查询。只需要按照Spring Data JPA提供的方法命名规则定义方法的名称,就可以完成查询工作。Spring Data JPA在程序执行的时候会根据方法名称进行解析,并自动生成查询语句进行查询
按照Spring Data JPA 定义的规则,查询方法以findBy开头,涉及条件查询时,条件的属性用条件关键字连接,要注意的是:条件属性首字母需大写。框架在进行方法名解析时,会先把方法名多余的前缀截取掉,然后对剩下部分进行解析。

package com.atguigu.springdata; import java.util.List; import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
import org.springframework.stereotype.Repository; /*
* 符合SpringDatajpa的dao层接口规范
*JpaRepository<操作的实体类类型,实体类中主键属性的类型>
*封装了基本的CRUD操作
JpaSpecificationExecutor<操作的实体类类型>
*封装了复杂查询操作(分页)
* */ public interface CustomerDao extends JpaRepository<Customer,Long>, JpaSpecificationExecutor<Customer>
{ //@Query 使用jpql的方式查询。?1代表参数的占位符,其中1对应方法中的参数索引 @Query(value="from Customer where custName = ?1") public Customer findCustomer(String custName); @Query(value="update Customer set custName = ?1 where custId = ?2")
@Modifying
public void updateCustomer(String custName,Long custId); /** * nativeQuery : 使用本地sql的方式查询 */ @Query(value="select * from cst_customer",nativeQuery=true) public List<Object[]> findSql(); @Query(value = "select * from cst_customer where cust_name like ?1",nativeQuery = true)
public List<Object []> findSql2(String name); //方法命名方式查询(根据客户名称查询客户) public Customer findByCustName(String custName); }
测试代码如下
@Test
public void testFindSql22()
{ Customer customer = customerDao.findByCustName("3333");
System.out.println(customer.toString());
}




我们使用下Like查看下模糊查询
package com.atguigu.springdata; import java.util.List; import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
import org.springframework.stereotype.Repository; /*
* 符合SpringDatajpa的dao层接口规范
*JpaRepository<操作的实体类类型,实体类中主键属性的类型>
*封装了基本的CRUD操作
JpaSpecificationExecutor<操作的实体类类型>
*封装了复杂查询操作(分页)
* */ public interface CustomerDao extends JpaRepository<Customer,Long>, JpaSpecificationExecutor<Customer>
{ //@Query 使用jpql的方式查询。?1代表参数的占位符,其中1对应方法中的参数索引 @Query(value="from Customer where custName = ?1") public Customer findCustomer(String custName); @Query(value="update Customer set custName = ?1 where custId = ?2")
@Modifying
public void updateCustomer(String custName,Long custId); /** * nativeQuery : 使用本地sql的方式查询 */ @Query(value="select * from cst_customer",nativeQuery=true) public List<Object[]> findSql(); @Query(value = "select * from cst_customer where cust_name like ?1",nativeQuery = true)
public List<Object []> findSql2(String name); //方法命名方式查询(根据客户名称查询客户) public Customer findByCustName(String custName); public List<Customer> findByCustNameLike(String custName); }
测试代码如下
    @Test
    public void testFindSql22()
    {
       List<Customer> customers = customerDao.findByCustNameLike("3333%");
       for(Customer customer:customers){
           System.out.println(customer.toString());
       }
    }


这里没有占位符,两个参数顺利不能弄错了
package com.atguigu.springdata; import java.util.List; import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
import org.springframework.stereotype.Repository; /*
* 符合SpringDatajpa的dao层接口规范
*JpaRepository<操作的实体类类型,实体类中主键属性的类型>
*封装了基本的CRUD操作
JpaSpecificationExecutor<操作的实体类类型>
*封装了复杂查询操作(分页)
* */ public interface CustomerDao extends JpaRepository<Customer,Long>, JpaSpecificationExecutor<Customer>
{ //@Query 使用jpql的方式查询。?1代表参数的占位符,其中1对应方法中的参数索引 @Query(value="from Customer where custName = ?1") public Customer findCustomer(String custName); @Query(value="update Customer set custName = ?1 where custId = ?2")
@Modifying
public void updateCustomer(String custName,Long custId); /** * nativeQuery : 使用本地sql的方式查询 */ @Query(value="select * from cst_customer",nativeQuery=true) public List<Object[]> findSql(); @Query(value = "select * from cst_customer where cust_name like ?1",nativeQuery = true)
public List<Object []> findSql2(String name); //方法命名方式查询(根据客户名称查询客户) public Customer findByCustName(String custName); public List<Customer> findByCustNameLike(String custName); public List<Customer> findByCustNameLikeAndCusIndustry(String custName,String cusIndustry); }
测试代码如下
@Test
public void testFindSql22()
{ List<Customer> customers = customerDao.findByCustNameLikeAndCusIndustry("3333%","明星");
for(Customer customer:customers){
System.out.println(customer.toString());
} }
Hibernate:
select
customer0_.cust_id as cust_id1_0_,
customer0_.cust_industry as cust_ind2_0_,
customer0_.cust_address as cust_add3_0_,
customer0_.cust_level as cust_lev4_0_,
customer0_.cust_name as cust_nam5_0_,
customer0_.cust_phone as cust_pho6_0_,
customer0_.cust_source as cust_sou7_0_
from
cst_customer customer0_
where
(
customer0_.cust_name like ?
)
and customer0_.cust_industry=?

我们重点来看下JpaSpecificationExecutor方法

这个接口有上面的几个方法,T findOne(Specification<T> spec);之前的JpaRepository接口也有findOne方法只能依据主键查询,但是没有携带Specification参数,这里携带了Specification参数
我们可以按照主键查询,也可以安装名称查询,我们可以自定义查询条件


/**
* Specification in the sense of Domain Driven Design.
*
* @author Oliver Gierke
* @author Thomas Darimont
*/
public interface Specification<T> { /**
* Creates a WHERE clause for a query of the referenced entity in form of a {@link Predicate} for the given
* {@link Root} and {@link CriteriaQuery}.
*
* @param root
* @param query
* @return a {@link Predicate}, must not be {@literal null}.
*/
Predicate toPredicate(Root<T> root, CriteriaQuery<?> query, CriteriaBuilder cb);
}
我们来测试下上面的几个接口


对象CriteriaBuilder有下面这样多的比较的方式


@Test
public void testFindSql223333()
{ Specification<Customer> spec = new Specification<Customer>() { public Predicate toPredicate(Root<Customer> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
// TODO Auto-generated method stub
Path<Object> custName = root.get("custName");
Predicate predicate = cb.equal(custName, "3333");
return predicate;
}
}; Customer customer = customerDao.findOne(spec);
System.out.println(customer.toString());
}
多个查询条件的拼接

@Test
public void testFindSql223333222()
{ Specification<Customer> spec = new Specification<Customer>() { public Predicate toPredicate(Root<Customer> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
// TODO Auto-generated method stub
Path<Object> custName = root.get("custName");
Path<Object> cusIndustry = root.get("cusIndustry");
Predicate predicate1 = cb.equal(custName, "3333");
Predicate predicate2 = cb.equal(cusIndustry, "2222");
Predicate predicate3 = cb.and(predicate1,predicate2);
return predicate3;
}
}; Customer customer = customerDao.findOne(spec);
System.out.println(customer.toString());
}


@Test
public void testFindSql223333222wwww()
{ Specification<Customer> spec = new Specification<Customer>() { public Predicate toPredicate(Root<Customer> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
// TODO Auto-generated method stub
Path<Object> custName = root.get("custName");
Predicate predicate = cb.like(custName.as(String.class), "33%");
return predicate;
}
}; List<Customer> customer = customerDao.findAll(spec);
System.out.println(customer.toString());
}
对于 List<Customer> customer = customerDao.findAll(spec)返回的数据是一个集合,我们可以指定返回的集合中的数据按照某种方式进行排序

@Test
public void testFindSql223333222wwwwww()
{ Specification<Customer> spec = new Specification<Customer>() { public Predicate toPredicate(Root<Customer> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
// TODO Auto-generated method stub
Path<Object> custName = root.get("custName");
Predicate predicate = cb.like(custName.as(String.class), "33%");
return predicate;
}
}; Sort sort = new Sort(Sort.Direction.ASC,"custId");
List<Customer> customer = customerDao.findAll(spec,sort);
System.out.println(customer.toString());
}
按照"custId"的Sort.Direction.ASC进行排序

/**
* 目标: 实现带查询条件的分页. id > 5 的条件
*
* 调用 JpaSpecificationExecutor 的 Page<T> findAll(Specification<T> spec, Pageable pageable);
* Specification: 封装了 JPA Criteria 查询的查询条件
* Pageable: 封装了请求分页的信息: 例如 pageNo, pageSize, Sort
*/
@Test
public void testJpaSpecificationExecutorss(){
int pageNo = 3 - 1;
int pageSize = 5;
Sort sort = new Sort(Sort.Direction.ASC,"custId");
//封装分页的信息
PageRequest pageable = new PageRequest(pageNo, pageSize,sort); Specification<Customer> spec = new Specification<Customer>() { public Predicate toPredicate(Root<Customer> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
// TODO Auto-generated method stub
Path<Object> custName = root.get("custName");
Predicate predicate = cb.like(custName.as(String.class), "33%");
return predicate;
}
}; Page<Customer> page = customerDao.findAll(spec, pageable); System.out.println("总记录数: " + page.getTotalElements());
System.out.println("当前第几页: " + (page.getNumber() + 1));
System.out.println("总页数: " + page.getTotalPages());
System.out.println("当前页面的 List: " + page.getContent());
List<Customer> content = page.getContent();
System.out.println("当前页面的记录数: " + page.getNumberOfElements());
/*List<Person> collect = page.getContent().stream().map(stat->(Person)stat).collect(Collectors.toList());
System.out.println("当前页面的 List1: " + collect);*/
}
打印结果如下
Hibernate:
select
count(customer0_.cust_id) as col_0_0_
from
cst_customer customer0_
where
customer0_.cust_name like ?
总记录数: 1
当前第几页: 3
总页数: 1
当前页面的 List: []
当前页面的记录数: 0



客户个联系人是一对多的关系



3.2 实战Hibernate一对多关联映射
3.2.1 创建数据表(客户----联系人)
客户表: CREATE TABLE `cst_customer` ( `cust_id` bigint(32) NOT NULL AUTO_INCREMENT COMMENT '客户编号(主键)', `cust_name` varchar(32) NOT NULL COMMENT '客户名称(公司名称)', `cust_source` varchar(32) DEFAULT NULL COMMENT '客户信息来源', `cust_industry` varchar(32) DEFAULT NULL COMMENT '客户所属行业', `cust_level` varchar(32) DEFAULT NULL COMMENT '客户级别', `cust_phone` varchar(64) DEFAULT NULL COMMENT '固定电话', `cust_mobile` varchar(16) DEFAULT NULL COMMENT '移动电话', PRIMARY KEY (`cust_id`) ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8; 联系人表: CREATE TABLE `cst_linkman` ( `lkm_id` bigint(32) NOT NULL AUTO_INCREMENT COMMENT '联系人编号(主键)', `lkm_name` varchar(16) DEFAULT NULL COMMENT '联系人姓名', `lkm_cust_id` bigint(32) DEFAULT NULL COMMENT '客户id', `lkm_gender` char(1) DEFAULT NULL COMMENT '联系人性别', `lkm_phone` varchar(16) DEFAULT NULL COMMENT '联系人办公电话', `lkm_mobile` varchar(16) DEFAULT NULL COMMENT '联系人手机', `lkm_email` varchar(64) DEFAULT NULL COMMENT '联系人邮箱', `lkm_qq` varchar(16) DEFAULT NULL COMMENT '联系人qq', `lkm_position` varchar(16) DEFAULT NULL COMMENT '联系人职位', `lkm_memo` varchar(512) DEFAULT NULL COMMENT '联系人备注', PRIMARY KEY (`lkm_id`), KEY `FK_cst_linkman_lkm_cust_id` (`lkm_cust_id`), CONSTRAINT `FK_cst_linkman_lkm_cust_id` FOREIGN KEY (`lkm_cust_id`) REFERENCES `cst_customer` (`cust_id`) ON DELETE NO ACTION ON UPDATE NO ACTION ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;

接下来我们要新增一个联系人的实体类对象
在customer客户端实体类中,需要配置下面的信息

package com.atguigu.springdata;
import java.util.HashSet;
import java.util.Set; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.OneToMany;
import javax.persistence.Table; @Entity // 声明此类是个实体类 需要导入javax.persistence.Entity; @Table(name = "cst_customer") //需要将该类对应到数据库中的哪一个表中,name中填表的名称 public class Customer { @Id //声明主键 @GeneratedValue(strategy = GenerationType.IDENTITY) //声明主键的生成策略为自动递增 //mysql使用自增模式,orcle 使用序列模式 @Column(name = "cust_id") //设置该属性和数据库中的哪一个字段对应 private Long custId; @Column(name = "cust_name") private String custName; @Column(name = "cust_source") private String custSource; @Column(name = "cust_level") private String custLevel; @Column(name = "cust_industry") private String cusIndustry; @Column(name = "cust_phone") private String custPhone; @Column(name = "cust_address") private String custAddress; @OneToMany(targetEntity=LinkMan.class)
@JoinColumn(name="lkm_cust_id",referencedColumnName="cust_id")
private Set<LinkMan> linkMans = new HashSet<LinkMan>(); 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 getCustLevel() { return custLevel; } public void setCustLevel(String custLevel) { this.custLevel = custLevel; } public String getCusIndustry() { return cusIndustry; } public void setCusIndustry(String cusIndustry) { this.cusIndustry = cusIndustry; } public String getCustPhone() { return custPhone; } public void setCustPhone(String custPhone) { this.custPhone = custPhone; } public String getCustAddress() { return custAddress; } public void setCustAddress(String custAddress) { this.custAddress = custAddress; } @Override public String toString() { return "Customer [custId=" + custId + ", custName=" + custName + ", custSource=" + custSource + ", custLevel=" + custLevel + ", cusIndustry=" + cusIndustry + ", custPhone=" + custPhone + ", custAddress=" + custAddress + "]"; } public Set<LinkMan> getLinkMans() {
return linkMans;
} public void setLinkMans(Set<LinkMan> linkMans) {
this.linkMans = linkMans;
} }
在联系人方需要配置如下

package com.atguigu.springdata; import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.Table; @Entity // 声明此类是个实体类 需要导入javax.persistence.Entity; @Table(name = "cst_linkman") //需要将该类对应到数据库中的哪一个表中,name中填表的名称
public class LinkMan {
@Id //声明主键 
	@GeneratedValue(strategy = GenerationType.IDENTITY) //声明主键的生成策略为自动递增
	@Column(name = "lkm_id") //设置该属性和数据库中的哪一个字段对应
    private Long lkmId;
    @Column(name = "lkm_gender") //设置该属性和数据库中的哪一个字段对应
    private Character lkmGender;
    @Column(name = "lkm_name") //设置该属性和数据库中的哪一个字段对应
    private String lkmName;
    @Column(name = "lkm_phone") //设置该属性和数据库中的哪一个字段对应
    private String lkmPhone;
    @Column(name = "lkm_email") //设置该属性和数据库中的哪一个字段对应
    private String lkmEmail;
    @Column(name = "lkm_qq") //设置该属性和数据库中的哪一个字段对应
    private String lkmQq;
    @Column(name = "lkm_mobile") //设置该属性和数据库中的哪一个字段对应
    private String lkmMobile;
    @Column(name = "lkm_memo") //设置该属性和数据库中的哪一个字段对应
    private String lkmMemo;
    @Column(name = "lkm_position") //设置该属性和数据库中的哪一个字段对应
    private String lkmPosition;
    @ManyToOne(targetEntity=Customer.class)
    @JoinColumn(name="lkm_cust_id",referencedColumnName="cust_id")
    private Customer customer;
    public Customer getCustomer() {
        return customer;
    }
    public void setCustomer(Customer customer) {
        this.customer = customer;
    }
    public Long getLkmId() {
        return lkmId;
    }
    public void setLkmId(Long lkmId) {
        this.lkmId = lkmId;
    }
    public Character getLkmGender() {
        return lkmGender;
    }
    public void setLkmGender(Character lkmGender) {
        this.lkmGender = lkmGender;
    }
    public String getLkmName() {
        return lkmName;
    }
    public void setLkmName(String lkmName) {
        this.lkmName = lkmName;
    }
    public String getLkmPhone() {
        return lkmPhone;
    }
    public void setLkmPhone(String lkmPhone) {
        this.lkmPhone = lkmPhone;
    }
    public String getLkmEmail() {
        return lkmEmail;
    }
    public void setLkmEmail(String lkmEmail) {
        this.lkmEmail = lkmEmail;
    }
    public String getLkmQq() {
        return lkmQq;
    }
    public void setLkmQq(String lkmQq) {
        this.lkmQq = lkmQq;
    }
    public String getLkmMobile() {
        return lkmMobile;
    }
    public void setLkmMobile(String lkmMobile) {
        this.lkmMobile = lkmMobile;
    }
    public String getLkmMemo() {
        return lkmMemo;
    }
    public void setLkmMemo(String lkmMemo) {
        this.lkmMemo = lkmMemo;
    }
    public String getLkmPosition() {
        return lkmPosition;
    }
    public void setLkmPosition(String lkmPosition) {
        this.lkmPosition = lkmPosition;
    }
}
@JoinColumn(name="lkm_cust_id",referencedColumnName="cust_id")中表示的是表联系人中的lkm_cust_id字段的值,来自于表客户的cust_id
接下来,我们要编写一个操作联系人的接口类
package com.atguigu.springdata; import java.util.List; import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
import org.springframework.stereotype.Repository; /*
* 符合SpringDatajpa的dao层接口规范
*JpaRepository<操作的实体类类型,实体类中主键属性的类型>
*封装了基本的CRUD操作
JpaSpecificationExecutor<操作的实体类类型>
*封装了复杂查询操作(分页)
* */ public interface LinnkManDao extends JpaRepository<LinkMan,Long>, JpaSpecificationExecutor<LinkMan>
{ }
整个工程的结构如下所示

接下来我们来就可以进行测试了

我们来看下程序的代码
import java.io.FileNotFoundException;
import java.io.IOException;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.stream.Collector;
import java.util.stream.Collectors; import javax.persistence.EntityManager;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Path;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import javax.sql.DataSource; import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.data.domain.Sort.Direction;
import org.springframework.data.domain.Sort.Order;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.data.jpa.repository.Query;
import org.springframework.test.annotation.Rollback;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.transaction.annotation.Transactional; import com.atguigu.springdata.Customer;
import com.atguigu.springdata.CustomerDao;
import com.atguigu.springdata.LinkMan;
import com.atguigu.springdata.LinnkManDao;
import com.itcast.utils.JpaUtils; @RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations="classpath:applicationContext.xml")
public class oneToManyTest { @Autowired
private CustomerDao customerDao; @Autowired
private LinnkManDao linnkManDao; @Test
@Transactional
@Rollback(value=false)
public void save(){ Customer customer = new Customer();
customer.setCustName("百度"); LinkMan linkMan = new LinkMan();
linkMan.setLkmName("小明");
linkMan.setCustomer(customer); customerDao.save(customer); linnkManDao.save(linkMan); } }
这里操作了两张表要保证事务的一致性 @Transactional,其次事务操作成功之后要让更新的记录保存到数据库,不进行回滚 @Rollback(value=false)
黑马程序员spring data jpa 2019年第一版本的更多相关文章
- Spring Data JPA教程,第一部分: Configuration(翻译)
		Spring Data JPA项目旨在简化基于仓库的JPA的创建并减少与数据库交互的所需的代码量.本人在自己的工作和个人爱好项目中已经使用一段时间,它却是是事情如此简单和清洗,现在是时候与你分享我的知 ... 
- Spring Data JPA教程, 第二部分: CRUD(翻译)
		我的Spring Data Jpa教程的第一部分描述了,如何配置Spring Data JPA,本博文进一步描述怎样使用Spring Data JPA创建一个简单的CRUD应用.该应用要求如下: pe ... 
- Spring Data JPA 教程(翻译)
		写那些数据挖掘之类的博文 写的比较累了,现在翻译一下关于spring data jpa的文章,觉得轻松多了. 翻译正文: 你有木有注意到,使用Java持久化的API的数据访问代码包含了很多不必要的模式 ... 
- Spring Data JPA入门
		1. Spring Data JPA是什么 它是Spring基于ORM框架.JPA规范封装的一套JPA应用框架,可使开发者用极简的代码即可实现对数据的访问和操作.它提供了包括增删改查等在内的常用功能, ... 
- 课程10:《黑马程序员_Hibernate开发资料》视频目录--没有细看
		老师很厉害,讲得蛮详细的 \Hibernate视频教程\01_黑马程序员_Hibernate教程__Hibernate入门基础.avi; \Hibernate视频教程\02_黑马程序员_Hiberna ... 
- 2019年最新超级有趣好玩的html+css网页布局课程,前端入门基础,html5+css3零基础入门课程-黑马程序员pink老师精心录制
		大家好,我是黑马程序员pink老师!! 本次视频是前端零基础入门的课程,pink老师采取有趣好玩讲法,带你快乐的学习枯燥的html+css知识,学完之后让你能快速布局pc端页面.代码也可以讲的好玩有趣 ... 
- <Spring Data JPA>二 Spring Data Jpa
		1.pom依赖 <?xml version="1.0" encoding="UTF-8"?> <project xmlns="htt ... 
- Spring Data JPA基本增删改查和JPQL查询(含完整代码和视频连接)
		问题:SpringDataJPA怎么使用? 一.考察目标 主要考核SpringDataJPA的用法 二.题目分析 spring data jpa 的使用步骤(下面有具体实现细节) 1.创建maven工 ... 
- Springboot 系列(十)使用 Spring data jpa 访问数据库
		前言 Springboot data jpa 和 Spring jdbc 同属于 Spring开源组织,在 Spring jdbc 之后又开发了持久层框架,很明显 Spring data jpa 相对 ... 
随机推荐
- [256个管理学理论]002.青蛙效应(Frog Effect)
			青蛙效应(Frog Effect) 从一个话题开始: 当下,社会发展突飞猛进,日新月异.在世界经济危机中,我国国民生产总值增长幅度始终在8%以上,引起世人的瞩目. 但,在国内时常也能听到广大投资者对股 ... 
- 【MetaPruning】2019-ICCV-MetaPruning Meta Learning for Automatic Neural Network Channel Pruning-论文阅读
			MetaPruning 2019-ICCV-MetaPruning Meta Learning for Automatic Neural Network Channel Pruning Zechun ... 
- 添加对docker的监控
			一.环境:已安装docker机器ip:192.168.0.202 二.原理 使用docker的metrics-add参数,提供对docker运行参数的访问条件. 三.修改/etc/docker/dae ... 
- Chisel3 - util - OneHot
			https://mp.weixin.qq.com/s/Jsy8P3m9W2EYKwneGVekiw 独热码相关的电路生成器. 参考链接: https://github.com/freechip ... 
- 从按下url到显示页面
			从按下url到渲染页面流程图 处理输入信息 检查用户输入 当用户在地址栏中输入一个查询关键字时,地址栏会判断输入的关键字是搜索内容,还是请求的 URL.如果是搜索内容,地址栏会使用浏览器默认的搜索引擎 ... 
- Java实现 LeetCode 793 阶乘函数后K个零 (分析)
			793. 阶乘函数后K个零 f(x) 是 x! 末尾是0的数量.(回想一下 x! = 1 * 2 * 3 * - * x,且0! = 1) 例如, f(3) = 0 ,因为3! = 6的末尾没有0:而 ... 
- Java实现 蓝桥杯VIP 算法训练 乘法表
			问题描述 输出九九乘法表. 输出格式 输出格式见下面的样例.乘号用""表示. 样例输出 下面给出输出的前几行: 11=1 21=2 22=4 31=3 32=6 33=9 41=4 ... 
- Java实现 蓝桥杯VIP 算法训练 会议中心
			算法训练 会议中心 时间限制:2.0s 内存限制:512.0MB 会议中心 Siruseri政府建造了一座新的会议中心.许多公司对租借会议中心的会堂很感兴趣,他们希望能够在里面举行会议. 对于一个客户 ... 
- Java实现 LeetCode 168 Excel表列名称
			168. Excel表列名称 给定一个正整数,返回它在 Excel 表中相对应的列名称. 例如, 1 -> A 2 -> B 3 -> C ... 26 -> Z 27 -&g ... 
- MD760按键说明书
