SpringData jpa篇
源码数据库
链接:https://pan.baidu.com/s/15yRxsHfUbls-AHtOJngOhA
提取码:kzgy
- 随着社会的发展,传统的关系型数据库已经不能完美的适应我们的需求,于是出现了各种各样的非关系型数据库,针对这样的情况 ,我们的项目中除了关系型数据库还有非关系数据库,于是我们的程序就会变的很复杂了,
- 如果能有一个框架/技术能够实现既能管理非关系数据库和关系型数据库的话那就太好了,于是在这样的情况下 我们就引出了今天的主角SpringData
- 1.Springdata:它是Spring的一个子项目,用于简化数据库访问,支持非关系型存储和关系型存储,其主要目标是使得数据库的访问更加的方便和快捷
Springdata所支持的非关系存储的数据库有哪些:
MongoDB:文档型数据库
Neo4j:图形数据库
Redis:键值型数据库
Hbase:列族型数据库 - 备注:Springdata所支持的非关系数据存储的技术:各自的相应的启动包,如spring-data-redis.jar
Springdata所支持的关系型数据库有哪些:
Mysql
Oracle
- spring-data-jap.jar:它是Spring基于ORM框架、JPA规范封装的一套JPA应用框架,可使开发者用极简的代码即可实现对数据的访问和操作。它提供了包括增删改查等在内的常用功能,且易于扩展。学习并使用Spring Data JPA可以极大提高开发效率。
- Spring Data JPA 有什么
1)Repository:最顶层的接口,是一个空接口,目的是为了统一所有的Repository的类型,且能让组件扫描时自动识别。
2)CrudRepository: Repository的子接口,提供CRUD的功能。
3)PagingAndSortingRepository: CrudRepository的子接口, 添加分页排序。
4)JpaRepository: PagingAndSortingRepository的子接口,该接口提供了JPA的相关功能。
5)JpaSpecificationExecutor: 用来做复杂查询的接口,例如条件查询的分页
问题来了,既然有这些具有特定功能的接口,那么是由谁来实现呢?
答案:是由JPA+ORM框架(HIbernate)
1.Springboot的目录结构
2.配置Pom文件
<?xml version="1.0" encoding="UTF-8"?>
<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.0</modelVersion>
<groupId>bj.sh.gy</groupId>
<artifactId>SpringdateJpa</artifactId>
<version>1.0-SNAPSHOT</version>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.4.1.RELEASE</version>
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- mysql数据库连接驱动 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<!-- 数据库连接池 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.0.29</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-test</artifactId>
</dependency>
</dependencies>
</project>
3. 实体类
package com.rj.bd.enity;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
@Table(name = "user")
@Entity
public class User {
@Id
private String id;
private int age;
private String name;
private int t_version;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getT_version() {
return t_version;
}
public void setT_version(int t_version) {
this.t_version = t_version;
}
@Override
public String toString() {
return "User{" +
"id='" + id + '\'' +
", age=" + age +
", name='" + name + '\'' +
", t_version=" + t_version +
'}';
}
}
4.Dao层
package com.rj.bd.Dao;
import com.rj.bd.enity.User;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import java.util.List;
/**
* @author LXY
* @desc
* @time 2022-10-16 16:12
*/
@Repository
public interface UserDao extends JpaRepository<User,String> {
}
5.Service层
package com.rj.bd.Service;
import com.rj.bd.enity.User;
import java.util.List;
/**
* @author LXY
* @desc
* @time 2022-10-16 16:14
*/
public interface UserService {
List<User>queryall();
}
6.ServiceImple
package com.rj.bd.ServiceImple;
import com.rj.bd.Dao.UserDao;
import com.rj.bd.Service.UserService;
import com.rj.bd.enity.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
/**
* @author LXY
* @desc
* @time 2022-10-16 16:15
*/
@Service
public class UserServiceImple implements UserService {
@Autowired
UserDao dao;
@Override
public List<User> queryall() {
return dao.findAll();
}
}
7.Test
package com.rj.bd.Test;
import com.rj.bd.Service.UserService;
import com.rj.bd.enity.User;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import java.util.List;
/**
* @author LXY
* @desc
* @time 2022-10-16 16:10
*/
@RunWith(SpringRunner.class)
@SpringBootTest
public class Test {
@Autowired
UserService service;
@org.junit.Test
public void show(){
List<User> queryall = service.queryall();
System.out.println(queryall);
}
}
8. application.properties
##配置数据源
spring.datasource.url=jdbc:mysql://localhost:3306/hibernates?useUnicode=true&characterEncoding=utf8
spring.datasource.username=root
spring.datasource.password=root
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
#JPA的配置
##hibernate方言的配置
spring.jpa.database-platform=org.hibernate.dialect.MySQLDialect
##控制台显示sql语句
spring.jpa.show-sql=true
##是否根据实体类来更新数据库表
spring.jpa.hibernate.ddl-auto=update
- 运行成功
@Query
package com.rj.bd.Dao;
import com.rj.bd.enity.User;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Repository;
import java.util.List;
/**
* @author LXY
* @desc
* @time 2022-10-16 16:12
*/
@Repository
public interface UserDao extends JpaRepository<User,Integer> {
/**
* @Query:注解查询适用于所查询的数据无法通过关键字查询得到结果的查询。这种查询可以摆脱像关键字查询那样的约束,
将查询直接在相应的接口方法中声明,结构更为清晰,这是Spring Data的特有实现
1).当使用@Query时函数的名词就可以随便一点了
2).没有参数的查询
3).两个或者多个参数的耦合
4).使用@Param注解注入参数
5).模糊查询:like
6).@Query 注解支持使用百分号
7).@Query 使用原生的 SQL:如果我们使用原生的 SQL,控制台打印的语句也会是原生 SQL 的
友情提示:无论是关键字查询还是@Query查询,他们仅是对查询好使,其他不好使
*/
@Query(" select p from com.rj.bd.enity.User p where id=?1 ")
User selectont(String id);
@Query(" select p from com.rj.bd.enity.User p where id=:id ") // @Param注解: 注入/传入参数
User selectont2(@Param("id") String id);
/**
* nativeQuery=true:意思为使用本地查询,其实就是使用原生的sql语句
*
* 友情提示:据数据库的不同,在sql的书写语法方面可能有所区别
*
*/
@Query(value = " select * from user ",nativeQuery = true)
List<User> slectqeuery();
}
@Modifying
- 我们的@query值可以用作查询,但是像添加修改删除怎么办,需要在@query上方添加@Modifying注解
@Modifying
@Query("delete com.rj.bd.enity.User u where u.id=?1")
int deleteuser(String id);
- 最重要的一点必须开启事务在Service层,不然会报错
增删改查
1.增加一条
@Transactional
@Override
public int savauser() {
User user=new User();
user.setId(UUID.randomUUID().toString());
user.setName("猫咪");
user.setAge(15);
dao.save(user);
return 1;
}
2.添加多个
@Transactional
@Override
public int savauser() {
List<User>list=new ArrayList<>();
User user=new User();
user.setId(UUID.randomUUID().toString());
user.setName("猫咪123");
user.setAge(15);
User user1=new User();
user1.setId(UUID.randomUUID().toString());
user1.setName("猫咪123456");
user1.setAge(15);
list.add(user);
list.add(user1);
dao.save(list);
return 1;
}
3. 查询一条
User one = dao.findOne("1");
System.out.println(one);
4.查询全部
List<User> all = dao.findAll();
System.out.println(all);
5.查询一部分
List<String>list=new ArrayList<>();
list.add("1");
list.add("2");
list.add("3");
List<User> all = dao.findAll(list);
System.out.println(all);
6.查询总数
long count = dao.count();
System.out.println(count);
7.修改
User one = dao.findOne("1");
one.setName("xasd");
删除一条数据
dao.delete("ba8069ec-3dac-49f7-aa28-695f18b095b2");
User one = dao.findOne("9dd9db37-7df5-48b2-a3b7-2d94052a62a3");
//两种方法都可 dao.delete(one);
deleteAll();方法删除全部
分页
int page=1-1;
int size=2;
Pageable pageable=new PageRequest(page,2);
Page<User> all = dao.findAll(pageable);
System.out.println("总记录数"+all.getTotalElements());
System.out.println("总页数"+all.getTotalPages());
System.out.println("当前时第几页"+all.getNumber()+1);
System.out.println("当前显示的条数"+all.getNumberOfElements());
List<User> content = all.getContent();
System.out.println(content);
- 分页排序
org.springframework.data.domain.Sort .Order order=new org.springframework.data.domain.Sort .Order(Sort.Direction.ASC,"age");
org.springframework.data.domain.Sort .Order order2=new org.springframework.data.domain.Sort .Order(Sort.Direction.DESC,"name");
Sort sort=new Sort(order,order2);
int page=1-1;
int size=2;
Pageable pageable=new PageRequest(page,2,sort);
Page<User> all = dao.findAll(pageable);
System.out.println("总记录数"+all.getTotalElements());
System.out.println("总页数"+all.getTotalPages());
System.out.println("当前时第几页"+all.getNumber()+1);
System.out.println("当前显示的条数"+all.getNumberOfElements());
List<User> content = all.getContent();
System.out.println(content);
- 复杂分页(条件)
- Dao多继承,在继承一个, JpaSpecificationExecutor
Specification<User> spec=new Specification<User>() {
/**
*
* @param root: 意思为查询的实体类
* @param query :可以从中可到 Root 对象, 即告知 JPA Criteria 查询要查询哪一个实体类. 还可以
* 来添加查询条件, 还可以结合 EntityManager 对象得到最终查询的 TypedQuery 对象.
* @param cb: 用于创建Criteria 相关对象的工厂,且可以从中获取到Predicate
* @return Predicate 代表是一个查询条件
*/
@SuppressWarnings("rawtypes")
@Override
public Predicate toPredicate(Root<User> root, CriteriaQuery<?> query,
CriteriaBuilder cb) {
Path path = root.get("age");//获取Jpa_person表中age这个类的数据,且存入到Path对象中
Predicate predicate = cb.gt(path, 6);//创建一个条件查询:查询person对象对应的Jpa_Person表中的age这个列中的年龄大于50的数据
return predicate;//where __age___ > 60
}
};
org.springframework.data.domain.Sort .Order order=new org.springframework.data.domain.Sort .Order(Sort.Direction.ASC,"age");
org.springframework.data.domain.Sort .Order order2=new org.springframework.data.domain.Sort .Order(Sort.Direction.DESC,"name");
Sort sort=new Sort(order,order2);
int page=1-1;
int size=2;
Pageable pageable=new PageRequest(page,2,sort);
Page<User> all = dao.findAll(spec,pageable);
System.out.println("总记录数"+all.getTotalElements());
System.out.println("总页数"+all.getTotalPages());
System.out.println("当前时第几页"+all.getNumber()+1);
System.out.println("当前显示的条数"+all.getNumberOfElements());
List<User> content = all.getContent();
System.out.println(content);
return 1;
}
自定义接口(使用原生JPA)
继续深入,整合Mybatis
- pom文件
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.2.1</version>
</dependency>
</dependencies>
继续深入,整合MybatisPlus
- 配置Maven
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.4.3</version>
</dependency>
mybatis-plus.type-aliases-package=com.rj.bd.enity
mybatis-plus.mapper-locations=classpath*:/mapper/**/*.xml
mybatis-plus.configuration.map-underscore-to-camel-case: true
mybatis-plus.configuration.cache-enabled: false
mybatis-plus.configuration.call-setters-on-nulls: true
继续深入使用druid连接池
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.2.6</version>
</dependency
@ConfigurationProperties("spring.datasource")
@Bean
public DataSource dataSource() throws SQLException {
DruidDataSource druidDataSource = new DruidDataSource();
//我们一般不建议将数据源属性硬编码到代码中,而应该在配置文件中进行配置(@ConfigurationProperties 绑定)
// druidDataSource.setUrl("jdbc:mysql://127.0.0.1:3306/bianchengbang_jdbc");
// druidDataSource.setUsername("root");
// druidDataSource.setPassword("root");
// druidDataSource.setDriverClassName("com.mysql.cj.jdbc.Driver");
return druidDataSource;
}
测试:
@Autowired
DataSource dataSource;
@Autowired
JdbcTemplate jdbcTemplate;
@org.junit.Test
public void contextLoads() throws SQLException {
System.out.println("默认数据源为:" + dataSource.getClass());
System.out.println("数据库连接实例:" + dataSource.getConnection());
//访问数据库
Integer i = jdbcTemplate.queryForObject("SELECT count(*) from `user`", Integer.class);
System.out.println("user 表中共有" + i + "条数据。");
}