入门
初始化springboot
依赖引入
<!-- springdata--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!-- 阿里巴巴数据库池--> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> <version>1.1.16</version> </dependency> <!-- mysql引擎--> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <scope>runtime</scope> </dependency> <!-- lombok--> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency>配置文件
spring: datasource: driver-class-name: com.mysql.cj.jdbc.Driver url: jdbc:mysql://127.0.0.1:3306/blog?useSSL=false&serverTimezone=UTC&useUnicode=true&characterEncoding=UTF-8 username: root password: xx type: com.alibaba.druid.pool.DruidDataSource #JPA配置 jpa: database-platform: org.hibernate.dialect.MySQL5Dialect # 自动更新数据库表结构,也可以是 validate | update | create | create-drop properties: hibernate: hbm2ddl: auto: update # 显示sql语句 show-sql: true实体类
package com.learn.springdata.pojo; import lombok.*; import org.hibernate.Hibernate; import javax.persistence.*; import java.util.Date; import java.util.Objects; /** * 测试用户实体类 * * @author itdragon */ @Table(name = "itdragon_user") @Entity @Getter @Setter @ToString @NoArgsConstructor @AllArgsConstructor public class UserTest { @Id //GeneratedValue(生成的值) //strategy代表主键生成策略 @GeneratedValue(strategy = GenerationType.AUTO) private Long id; // 自增长主键 private String account; // 登录的账号 //Column对一个字段进行标注,nullable:是否可为NULL //unique:值是否不能重复 //name:数据库中的字段名 @Column(nullable = false,unique = false,name = "user_name") private String userName; // 注册的昵称 //transient(暂时的) 标注此注解后在创建数据表的时候将会忽略该属性 @Transient private String isTest; // Temporal(时间的) :向数据库映射日期(Date)属性时用来调整映射的精度。Date 类型的数据有 DATE, TIME, 和 TIMESTAMP 三种精度(即单纯的日期,时间,或者两者兼备). @Temporal(TemporalType.DATE) private Date birth; @Temporal(TemporalType.TIMESTAMP) private Date createTime; @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || Hibernate.getClass(this) != Hibernate.getClass(o)) return false; UserTest userTest = (UserTest) o; return id != null && Objects.equals(id, userTest.id); } @Override public int hashCode() { return getClass().hashCode(); } }效果
接口的springdata的书写(重点)
知识点2
* 重点知识:SpringData 查询方法定义规范 * 1. 查询方法名一般以 find | read | get 开头,建议用find * findByAccount : 通过account查询User * account是User的属性,拼接时首字母需大写 * 2. 支持的关键词有很多比如 Or,Between,isNull,Like,In等 * findByEmailEndingWithAndCreatedDateLessThan : 查询在指定时间前注册,并以xx邮箱结尾的用户 * And : 并且 * EndingWith : 以某某结尾 * LessThan : 小于 * 注意 * 若有User(用户表) Platform(用户平台表) 存在一对一的关系,且User表中有platformId字段 * SpringData 为了区分: * findByPlatFormId 表示通过platformId字段查询 * findByPlatForm_Id 表示通过platform实体类中id字段查询 * <p> * 开发建议 * 表的设计,尽量做单表查询,以确保高并发场景减轻数据库的压力。知识点3
- 重点知识:使用 @Query 注解 * <p> * 上面的方法虽然简单(不用写sql语句),但它有最为致命的问题-----不支持复杂查询,其次是命名太长 * 1. 使用@Query 注解实现复杂查询,设置 nativeQuery=true 使查询支持原生sql * 2. 配合@Modifying 注解实现创建,修改,删除操作 * 3. SpringData 默认查询事件为只读事务,若要修改数据则需手动添加事务注解 * <p> * 注意 * 若@Query 中有多个参数,SpringData 提供两种方法: * 第一种 ?1 ... ?2 要求参数顺序一致 * 第二种 :xxx ... :yyy xxx 和 yyy 必须是实体类对应的属性值,不要求参数顺序但参数前要加上@Param("xxx") * 模糊查询可使用 %xxx% * <p> * 开发建议 * 1. 参数填写的顺序要保持一致,不要给自己添加麻烦 * 2. 建议使用@Query,可读性较高
接口清单
JpaRepository接口提供的方法与说明
方法 描述 List<T> findAll(); 查找所有实体。 List<T> findAll(Sort var1); 排序、查找所有实体。 List<T> findAllById(Iterable<ID> var1); 返回制定一组ID的实体。 <S extends T> List<S> saveAll(Iterable<S> var1); 保存集合。 void flush(); 执行缓存与数据库同步。 <S extends T> S saveAndFlush(S var1); 强制执行持久化。 void deleteInBatch(Iterable<T> var1); 删除一个实体集合。 void deleteAllInBatch(); 删除所有实体。 T getOne(ID var1); 返回ID对应的实体。如果不存在,则返回空值。 <S extends T> List<S> findAll(Example<S> var1); 查询满足Example的所有对象。 <S extends T> List<S> findAll(Example<S> var1, Sort var2); 查询满足Example的所有对象,并且进行排序返回
CrudRepository接口提供的方法与说明:
方法 说明 <S extends T> S save(S var1); 保存实体。当实体中包含主键时,JPA会进行更新操作。 <S extends T> Iterable<S> saveAll(Iterable<S> var1); 保存所有实体。实体必须不为空。 Optional<T> findById(ID var1); 根据主键ID检索实体。 boolean existsById(ID var1); 根据主键ID检索实体,返回是否存在。值为布尔类型。 Iterable<T> findAll(); 返回所有实体。 Iterable<T> findAllById(Iterable<ID> var1); 根据给定的一组ID值返回一组实体。 long count(); 返回实体的数量 void deleteById(ID var1); 根据ID删除数据。 void delete(T var1); 删除给定的实体。 void deleteAll(Iterable<? extends T> var1); 删除实体。 void deleteAll(); 删除所有实体。 开发建议
简单的增删查改
接口
public interface UserRepository extends PagingAndSortingRepository<UserTest, Long>, JpaSpecificationExecutor<UserTest> { }测试代码
@Autowired UserRepository us; //查找所有用户 @Test public void findAllUser() { Iterable<UserTest> usAll = us.findAll(); usAll.forEach(System.out::println); } // 新增用户 @Test public void saveUser() { UserTest u=new UserTest(); u.setUserName("张三四次"); u.setAccount("你爹"); UserTest byAccount = us.save(u); System.out.println(byAccount); } //删除用户 @Test public void deleteUser(){ //方法1 Optional<UserTest> us1 = us.findById(1L); UserTest test; //Present为存在之意,isPresent表示us1中是否存在值 if (us1.isPresent()) { //没有返回值奥,和mp不一样 us.deleteById(1L); System.out.println("删除成功!"); } else { System.out.println("删除失败!"); } //方法2 try { us.deleteById(1L); System.out.println("删除成功!"); } catch(Exception ex) { System.out.println("删除失败!"); } } //更新用户 @Test public void updateUser(){ UserTest u=new UserTest(); u.setUserName("张fd三四次"); u.setAccount("你df爹"); u.setId(2L); //使用的方法和新增一样 UserTest save = us.save(u); System.out.println(save); }使用类SQL(注解开发)
适用于复杂的业务场景
使用JPQL语句(HQL)
1 查询时使用的是实体类的字段,而不是数据库中的字段 2 变量使用:变量名的形式,在方法参数中还有使用@Param("xx") 3 更新操作需要加上 @Modifying--接口代码--
//查找用户id通过用户名 @Query("select id from UserTest where userName=:name") List<Long> findUserIdByName(@Param("name") String name); //查找所有用户并排序(升) @Query("select userName from UserTest order by userName") List<String> findAllUserNameSort(); //查找所有用户并排序(降) @Query("select userName from UserTest order by userName desc ") List<String> findAllUserNameSortDesc(); //模糊加分页查询 @Query("select u from UserTest u where u.userName like %:name%") Page<UserTest> findUserByLikeName(String name, Pageable pageable);--测试代码--
//查找用户id通过用户名 @Test void findUserIdByName(){ List<Long> ids = us.findUserIdByName("张fd三四次"); System.out.println(ids); } //查找所有用户名并对用户名排序 @Test void findAllUserName(){ List<String> userSort = us.findAllUserNameSort(); List<String> userSort2 = us.findAllUserNameSortDesc(); System.out.println(userSort); System.out.println(userSort2); } //模糊加分页查询 @Test void findTest(){ //构建排序 Sort sort= Sort.by(Sort.Direction.ASC,"id"); //构建分页 int pageIndex=0; int pageSize=2; PageRequest pageRequest = PageRequest.of(pageIndex, pageSize,sort); //执行分页+排序+模糊 Page<UserTest> lists = us.findUserByLikeName("张",pageRequest); //获取结果 List<UserTest> content = lists.getContent(); System.out.println(content); }使用SQL语句
提示: 1这里的占位符使用的是?与jdbc相似,1表示第几个参数 2使用sql查询是SQL语句中的字段必须要和数据库对应 --接口代码--
//使用SQL @Query(value = "select id from itdragon_user where user_name=?1",nativeQuery = true) List<Long> findUserIdByNameUserSQL(String name);--测试代码--
//使用SQL语句 @Test void UserSQLTest(){ List<Long> sql = us.findUserIdByNameUserSQL("张fd三四次3"); System.out.println(sql); }使用接口查询语法
献上一张图,内容全在其中 --接口--
//使用接口查询语法 // 1 通过账号查用户信息 List<UserTest> findByAccount(String account); //2 对用户名模糊查询 List<UserTest> findByUserNameLike(String name); //3 批量查找特定id的用户 List<UserTest> findByIdIn(List<Long> ids); //4 查找用户名为:张fd三四次1,昵称为你df爹的用户 UserTest findByUserNameAndAccount(String userName, String account);--测试--
@Test void UserTSTest(){ List<UserTest> a = us.findByAccount("你df爹"); System.out.println(a); List<UserTest> a1 = us.findByUserNameLike("你"); System.out.println(a1); UserTest b = us.findByUserNameAndAccount("张fd三四次3", "你df爹"); System.out.println(b); List<Long> ids=new ArrayList<>(); ids.add(2L); ids.add(3L); List<UserTest> c = us.findByIdIn(ids); System.out.println(c); }