JPA是Java Persistence API的简称,中文名Java持久层API,是JDK 5.0注解或XML描述对象-关系表的映射关系,并将运行期的实体对象持久化到数据库中.
JPA的总体思想和现有Hibernate、TopLink、JDO等ORM框架大体一致。总的来说,JPA包括以下3方面的技术:
Spring Data JPA 是 spring data 项目下的一个模块。提供了一套基于 JPA标准操作数据库的简化方案。底层默认的是依赖 Hibernate JPA 来实现的.
技术特点: 我们只需要定义接口并集成 Spring Data JPA 中所提供的接口就可以了。不需要编写接口实现类.
官网地址:SpringDataJPA
<parent>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-parentartifactId>
<version>2.1.16.RELEASEversion>
<relativePath/>
parent>
<dependencies>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-data-jpaartifactId>
dependency>
<dependency>
<groupId>mysqlgroupId>
<artifactId>mysql-connector-javaartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-testartifactId>
dependency>
<dependency>
<groupId>org.projectlombokgroupId>
<artifactId>lombokartifactId>
dependency>
dependencies>
server:
port: 9090
spring:
application:
name: spring-data-jpa
datasource:
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://localhost:3306/user?charset=utf-8&serverTimezone=UTC
username: root
password: root
# jpa配置
jpa:
show-sql: true
hibernate:
# create,创建,不管表之前存不存在,不适合生产环境
# update,更新,表存在则更新数据,不存在则创建表,适合生产环境
# none 没有任何操作
ddl-auto: update
package com.cf.pojo;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import javax.persistence.*;
/**
* 用户实体类
*
*/
@Data
@Entity //表示当前类是实体类
@Table(name = "tb_user",catalog = "user")//name 表名 catalog数据库名 可省略,因配置文件url中配置了数据库
@AllArgsConstructor//满参构造
@NoArgsConstructor //无参构造
public class UserInfo {
/**
* 1 如果数据库表中 的字段名称和实体类中的属性名称保持一致的话,可以不需要加@Column注解
*
* 2 @GeneratedValue(strategy=" ") 主键生成策略
* GenerationType.IDENTITY表示针对于mysql中有自增长的数据的生成策略
* GenerationType.SEQUENCE表示针对于oracle数据中的主键生成策略
* GenerationType.AUTO是默认的选项,会根据数据库自动选择
*/
@Id
@Column(name = "id")
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
private String name;
private String gender;
private Integer age;
private String address;
private String qq;
private String email;
private String username;
private String password;
private String phone;
public UserInfo(Integer id,String name, String gender) {
this.id = id;
this.name = name;
this.gender = gender;
}
}
/**
* dao接口
*/
@Repository
public interface UserMapper extends JpaRepository<UserInfo,Integer> {
}
//启动类
@SpringBootApplication
public class JpaApplication {
public static void main(String[] args) {
SpringApplication.run(JpaApplication.class, args);
}
}
//测试类
@RunWith(SpringRunner.class)
@SpringBootTest
public class JpaTest {
@Autowired
private UserMapper userMapper;
//查询方法
@Test
public void queryAll(){
//查询所有用户
List<UserInfo> infoList = userMapper.findAll();
System.out.println(infoList);
}
}
注:在实体类之上加入有参和无参的构造函数的注解,或自定义参数构造函数
@AllArgsConstructor #有参构造的注解
@NoArgsConstructor #无参构造的注解
save操作等于: insert 或 update
/**
* save操作
* id在表中存在,则修改数据
* id不存在,则新增数据
*/
@Test
public void save(){
UserInfo userInfo = new UserInfo(4,"张三","2");
//新增或修改数据
UserInfo info = userMapper.save(userInfo);
System.out.println(info);
UserInfo userInfo2 = new UserInfo(5,"李四","2");
UserInfo userInfo3 = new UserInfo(6,"王五","2");
List<UserInfo> list = new ArrayList<>();
list.add(userInfo2);
list.add(userInfo3);
//批量插入数据
List<UserInfo> userInfos = userMapper.saveAll(list);
System.out.println(userInfos);
}
/**
* id存在则删除
* 不存在报错: No class com.cf.pojo.UserInfo entity with id 3 exists!
*/
@Test
public void delete(){
userMapper.deleteById(3);
}
/**
* 分页查询
*/
@Test
public void pageQuery() {
/**设置分页参数
* Pageable pageable = PageRequest.of(1, 2)
* param1:页码,但是默认是从0开始
* param2:每页显示的记录数
*/
Pageable pageable = PageRequest.of(1, 2);
Page<UserInfo> page = userMapper.findAll(pageable);
//获取分页集合的数据
List<UserInfo> content = page.getContent();
System.out.println(content);
//获取总元素数量
long totalElements = page.getTotalElements();
System.out.println(totalElements);
//获取总页数
int totalPages = page.getTotalPages();
System.out.println(totalPages);
}
1 在mapper接口中定义接口方法
//自定义查询
@Query("from UserInfo ")
public List<UserInfo> selectAll();
2 测试
/**
* 自定义查询
*/
@Test
public void selectAll() {
List<UserInfo> userInfos = userMapper.selectAll();
System.out.println(userInfos);
}
1 在mapper接口中定义接口方法
//自定义查询带条件
//@Query注解表示查询,参数的表示使用?1 , ?2, ?n
@Query("from UserInfo where name=?1 or username=?2")
public List<UserInfo> selectByExample(String name,String username);
@Query注解表示查询,参数的表示使用?1 , ?2, … ?n
接口方法中的参数的顺序必须要和?后面的数字相对应
2、测试
@Test
public void selectExample(){
List<UserInfo> userinfos = userMapper.selectByExample("王五","小小");
System.out.println(userinfos);
}
1 在mapper接口中定义接口方法
@Repository
@Transactional
public interface UserMapper extends JpaRepository<UserInfo,Integer> {
@Query("update UserInfo set name=?1 where id=?2")
@Modifying
public int updateUserInfo(String name,Integer id);
}
1 在执行update或者delete的时候,要加上@Modifying表示更新
2 要加入@Transactional注解,因为jpa要求,没有事务支持
,不能执行更新和删除操作
2 测试
@Test
public void update(){
int i = userMapper.updateUserInfo("abcdefg",2);
System.out.println(i);
}
解决方案: 在HQL的后面加入index(低版本SpringBoot不加是可以运行的)
ps: @Query("update UserInfo set name=?1 where id=?2")
解决方案: 下标用错了 , 注意 从== 1== 开始 不是 0
解决方案: 在方法上加上@Modifying表示更新
解决方案: 在Service层或者Repository层上必须加@Transactional