桃花岛--SpringBoot系列之Spring Data Jpa注解和基础操作
本章小宋讲一下Spring Data Jpa的一些常用注解和一些简单的基础操作。
目录
- JPA注解和简单操作
- 1.相关依赖
- 2.配置数据库连接信息和JPA配置
- 3.实体类
- 3.1 创建表
- 3.2 创建主键
- 3.3 设置字段类型
- 3.4 指定不持久化特定字段
- 3.5 声明大字段
- 3.6 创建枚举类型的字段
- 4.创建操作数据库的 Repository 接口
- 4.1 JPA自带方法用例
- 4.1.1 增删改查
- 4.1.2 条件查询
- 4.2 JPA自定义Sql语句
- 4.3 创建异步方法
- 5.测试
JPA注解和简单操作
这里小宋讲解一下Spring Data Jpa的相关知识。
1.相关依赖
<dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-jpa</artifactId></dependency><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><scope>runtime</scope></dependency><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></dependencies>
2.配置数据库连接信息和JPA配置
下面的配置中要先去单独说一下 spring.jpa.hibernate.ddl-auto=create这个配置选项。
该属性常用的选项包含4种:
- create:每次重新启动项目都会重新创建新表结构,会导致数据丢失
- create-drop:每次启动项目创建表结构,关闭项目删除表结构
- update:每次启动项目会更新表结构
- validate:验证表结构,不对数据库进行任何更改
一定要不要在生产环境使用 ddl 自动生成表结构,一般推荐手写 SQL 语句配合 Flyway 来做这些事情。
spring.datasource.url=jdbc:mysql://localhost:3306/springboot_jpa?useSSL=false&serverTimezone=CTT
spring.datasource.username=root
spring.datasource.password=123456
# 打印出 sql 语句
spring.jpa.show-sql=true
spring.jpa.hibernate.ddl-auto=create
spring.jpa.open-in-view=false
# 创建的表的 ENGINE 为 InnoDB
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL55Dialect
3.实体类
我们为这个类添加 @Entity 注解代表它是数据库持久化类,并配置主键 id。
import lombok.Data;
import lombok.NoArgsConstructor;import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;@Entity
@Data
@NoArgsConstructor
publicclass Person {@Id@GeneratedValue(strategy = GenerationType.IDENTITY)private Long id;@Column(unique = true)private String name;private Integer age;public Person(String name, Integer age) {this.name = name;this.age = age;}}
3.1 创建表
@Entity:声明一个类对应一个数据库实体。
@Table:设置表名
@NoArgsConstructor:无参构造方法
@Entity
@Data
@NoArgsConstructor
publicclass Person {@Id@GeneratedValue(strategy = GenerationType.IDENTITY)private Long id;@Column(unique = true)private String name;private Integer age;public Person(String name, Integer age) {this.name = name;this.age = age;}
3.2 创建主键
@Id:声明一个字段为主键。
使用@Id声明之后,我们还需要定义主键的生成策略。我们可以使用 @GeneratedValue 指定主键生成策略。
1.通过 @GeneratedValue直接使用 JPA 内置提供的四种主键生成策略来指定主键生成策略。
@Id@GeneratedValue(strategy = GenerationType.IDENTITY)private Long id;
JPA使用枚举定义了4种常见的主键生成策略:
public enum GenerationType {/*** 使用一个特定的数据库表格来保存主键* 持久化引擎通过关系数据库的一张特定的表格来生成主键,*/TABLE,/***在某些数据库中,不支持主键自增长,比如Oracle、PostgreSQL其提供了一种叫做"序列(sequence)"的机制生成主键*/SEQUENCE,/*** 主键自增长*/IDENTITY,/***把主键生成策略交给持久化引擎(persistence engine),*持久化引擎会根据数据库在以上三种主键生成 策略中选择其中一种*/AUTO
}
@GeneratedValue注解默认使用的策略是GenerationType.AUTO
public @interface GeneratedValue {GenerationType strategy() default AUTO;String generator() default "";
}
一般使用 MySQL 数据库的话,使用GenerationType.IDENTITY策略比较普遍一点(分布式系统的话需要另外考虑使用分布式 ID)。
2.通过 @GenericGenerator声明一个主键策略,然后 @GeneratedValue使用这个策略
@Id
@GeneratedValue(generator = "IdentityIdGenerator")
@GenericGenerator(name = "IdentityIdGenerator", strategy = "identity")
private Long id;
等同于:
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
jpa 提供的主键生成策略有如下一些:
public class DefaultIdentifierGeneratorFactoryimplements MutableIdentifierGeneratorFactory, Serializable, ServiceRegistryAwareService {@SuppressWarnings("deprecation")public DefaultIdentifierGeneratorFactory() {register( "uuid2", UUIDGenerator.class );register( "guid", GUIDGenerator.class ); // can be done with UUIDGenerator + strategyregister( "uuid", UUIDHexGenerator.class ); // "deprecated" for new useregister( "uuid.hex", UUIDHexGenerator.class ); // uuid.hex is deprecatedregister( "assigned", Assigned.class );register( "identity", IdentityGenerator.class );register( "select", SelectGenerator.class );register( "sequence", SequenceStyleGenerator.class );register( "seqhilo", SequenceHiLoGenerator.class );register( "increment", IncrementGenerator.class );register( "foreign", ForeignGenerator.class );register( "sequence-identity", SequenceIdentityGenerator.class );register( "enhanced-sequence", SequenceStyleGenerator.class );register( "enhanced-table", TableGenerator.class );}public void register(String strategy, Class generatorClass) {LOG.debugf( "Registering IdentifierGenerator strategy [%s] -> [%s]", strategy, generatorClass.getName() );final Class previous = generatorStrategyToClassNameMap.put( strategy, generatorClass );if ( previous != null ) {LOG.debugf( " - overriding [%s]", previous.getName() );}}}
3.3 设置字段类型
@Column:声明字段。
示例:
设置属性 userName 对应的数据库字段名为 user_name,长度为 32,非空
@Column(name = "user_name", nullable = false, length=32)
private String userName;
设置字段类型并且加默认值,这个还是挺常用的。
@Column(columnDefinition = "tinyint(1) default 1")
private Boolean enabled;
3.4 指定不持久化特定字段
@Transient :声明不需要与数据库映射的字段,在保存的时候不需要保存进数据库 。
如果我们想让secrect 这个字段不被持久化,可以使用 @Transient关键字声明。
@Entity(name="USER")
public class User {......@Transientprivate String secrect; // not persistent because of @Transient}
除了 @Transient关键字声明, 还可以采用下面3种方法:
static String secrect; // not persistent because of static
final String secrect = “Satish”; // not persistent because of final
transient String secrect; // not persistent because of transient
但是一般注解的方式使用的比较多
3.5 声明大字段
@Lob:声明某个字段为大字段。
@Lob
private String content;
@Lob
//指定 Lob 类型数据的获取策略, FetchType.EAGER 表示非延迟 加载,而 FetchType. LAZY 表示延迟加载 ;
@Basic(fetch = FetchType.EAGER)
//columnDefinition 属性指定数据表对应的 Lob 字段类型
@Column(name = "content", columnDefinition = "LONGTEXT NOT NULL")
private String content;
3.6 创建枚举类型的字段
public enum Gender {MALE("男性"),FEMALE("女性");private String value;Gender(String str){value=str;}
}
可以通过@Enumerated注解去使用枚举类型的字段
@Entity
@Table(name = "role")
public class Role {@Id@GeneratedValue(strategy = GenerationType.IDENTITY)private Long id;private String name;private String description;@Enumerated(EnumType.STRING)private Gender gender;省略getter/setter......
}
数据库里面对应存储的是 MAIL/FEMAIL。
如何验证我们已经成功,运行项目后,查看控制台是否打印出创建表的 sql 语句,并且数据库中表真的被创建出来的话,说明你成功了。
控制台打印出来的 sql 语句类似下面这样:
droptableifexists person
CREATETABLE`person` (`id`bigint(20) NOTNULL AUTO_INCREMENT,`age`int(11) DEFAULTNULL,`name`varchar(255) DEFAULTNULL,PRIMARY KEY (`id`)
) ENGINE=InnoDBDEFAULTCHARSET=utf8;
altertable person addconstraint UK_p0wr4vfyr2lyifm8avi67mqw5 unique (name)
4.创建操作数据库的 Repository 接口
@Repository
public interface PersonRepository extends JpaRepository<Person, Long> {
}
首先这个接口加了 @Repository 注解,代表它和数据库操作有关。另外,它继承了 JpaRepository<Person, Long>接口,而JpaRepository<Person, Long>源码如下:
@NoRepositoryBean
publicinterface JpaRepository<T, ID> extends PagingAndSortingRepository<T, ID>, QueryByExampleExecutor<T> {List<T> findAll();List<T> findAll(Sort var1);List<T> findAllById(Iterable<ID> var1);<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);<S extends T> List<S> findAll(Example<S> var1);<S extends T> List<S> findAll(Example<S> var1, Sort var2);
}
所以当我们继承了JpaRepository<T, ID> ,也就可以去调用 JPA 为我们提供好的增删改查、分页查询以及根据条件查询等方法。
4.1 JPA自带方法用例
4.1.1 增删改查
- 增(保存用户到数据库)
Person person = new Person("SnailClimb", 23);personRepository.save(person);
save()方法对应 sql 语句是: insert into person (age, name) values (23,"snailclimb")
- 查(根据id查找用户)
Optional<Person> personOptional = personRepository.findById(id);
findById()方法对应 sql 语句就是:select * from person p where p.id = id
- 删(根据id删除用户)
personRepository.deleteById(id);
deleteById()方法对应 sql 语句就是:delete from person where id=id
- 改(根据id更新用户信息)
更新操作也是通过save()方法实现。
Person person = new Person("SnailClimb", 23);Person savedPerson = personRepository.save(person);// 更新 person 对象的姓名savedPerson.setName("UpdatedName");personRepository.save(savedPerson);
这里是先新增再去更新,也可以先查出一个用户的信息再去更新。
这里最后的save()方法相当于 sql 语句:update person set name="UpdatedName" where id=id
4.1.2 条件查询
下面这些方法是根据 JPA 提供的语法自定义的,你需要将下面这些方法写到 PersonRepository 中。
假如我们想要根据 Name 来查找 Person ,你可以这样:
Optional<Person> findByName(String name);
如果你想要找到年龄大于某个值的人,你可以这样:
List<Person> findByAgeGreaterThan(int age);
4.2 JPA自定义Sql语句
很多时候我们自定义 sql 语句会非常有用。
根据 name 来查找 Person:
@Query("select p from Person p where p.name = :name")
Optional<Person> findByNameCustomeQuery(@Param("name") String name);
Person 部分属性查询,避免 select *操作:
@Query("select p.name from Person p where p.id = :id")
String findPersonNameById(@Param("id") Long id);
根据 id 更新Person name:
@Modifying
@Transactional
@Query("update Person p set p.name = ?1 where p.id = ?2")
void updatePersonNameById(String name, Long id);
根据 id 删除Person name:
@Modifying
@Transactional
@Query("delete from Person where id = ?1")
void deletePersonNameById(Long id);
4.3 创建异步方法
如果我们需要创建异步方法的话,也比较方便。
异步方法在调用时立即返回,然后会被提交给TaskExecutor执行。当然你也可以选择得出结果后才返回给客户端。
@Async
Future<User> findByName(String name);@Async
CompletableFuture<User> findByName(String name);
5.测试
@SpringBootTest
@RunWith(SpringRunner.class)
publicclass PersonRepositoryTest {@Autowiredprivate PersonRepository personRepository;private Long id;/*** 保存person到数据库*/@Beforepublic void setUp() {assertNotNull(personRepository);Person person = new Person("SnailClimb", 23);Person savedPerson = personRepository.saveAndFlush(person);// 更新 person 对象的姓名savedPerson.setName("UpdatedName");personRepository.save(savedPerson);id = savedPerson.getId();}/*** 使用 JPA 自带的方法查找 person*/@Testpublic void should_get_person() {Optional<Person> personOptional = personRepository.findById(id);assertTrue(personOptional.isPresent());assertEquals("SnailClimb", personOptional.get().getName());assertEquals(Integer.valueOf(23), personOptional.get().getAge());List<Person> personList = personRepository.findByAgeGreaterThan(18);assertEquals(1, personList.size());// 清空数据库personRepository.deleteAll();}/*** 自定义 query sql 查询语句查找 person*/@Testpublic void should_get_person_use_custom_query() {// 查找所有字段Optional<Person> personOptional = personRepository.findByNameCustomeQuery("SnailClimb");assertTrue(personOptional.isPresent());assertEquals(Integer.valueOf(23), personOptional.get().getAge());// 查找部分字段String personName = personRepository.findPersonNameById(id);assertEquals("SnailClimb", personName);System.out.println(id);// 更新personRepository.updatePersonNameById("UpdatedName", id);Optional<Person> updatedName = personRepository.findByNameCustomeQuery("UpdatedName");assertTrue(updatedName.isPresent());// 清空数据库personRepository.deleteAll();}}
讲到这里本章对Spring Data Jpa注解和基础操作知识讲解也就结束了,如果想了解更多知识可以在对应的专栏中看系列文章,谢谢大家的观看,希望能给各位同学带来帮助。如果觉得博主写的还可以的,可以点赞收藏。
桃花岛--SpringBoot系列之Spring Data Jpa注解和基础操作相关推荐
- SpringBoot系列之Spring Data MongoDB教程
SpringBoot系列之Spring Data MongoDB教程 1.MongoDB下载安装 因为没有买linux服务器,所以本博客只安装window来学习,可以点击官网下载链接进行下载,安装过程 ...
- ORM框架之Spring Data JPA(二)spring data jpa方式的基础增删改查
上一篇主要在介绍hibernate实现jpa规范,如何实现数据增删改查,这一篇将会着重spring data jpa 一.Spring Data JPA 1.1 Spring Data JPA介绍: ...
- 使用H2Database+Druid连接池+Spring Data JPA+Ehcache实现CRUD操作
前言 注:本篇为纯实践篇,主要用于技术整合,介绍如何搭建一个完整全面的Web项目.如果对于技术原理还不了解的童鞋可点击下方链接,学习后在来~ H2数据库教程:H2数据库入门 缓存使用教程:在Sprin ...
- spring-boot (三) spring data jpa
学习文章来自:http://www.ityouknow.com/spring-boot.html spring data jpa介绍 首先了解JPA是什么? JPA(Java Persistence ...
- Spring Security+Spring Data Jpa 强强联手,安全管理只有更简单!
Spring Security+Spring Data Jpa 强强联手,安全管理没有简单,只有更简单! 这周忙着更新 OAuth2,Spring Security 也抽空来一篇. Spring Se ...
- Spring Data JPA(官方文档翻译)
关于本书 介绍 关于这本指南 第一章 前言 第二章 新增及注意点 第三章 项目依赖 第四章 使用Spring Data Repositories 4.1 核心概念 4.2 查询方法 4.3 定义rep ...
- Springboot 系列(十)使用 Spring data jpa 访问数据库
前言 Springboot data jpa 和 Spring jdbc 同属于 Spring开源组织,在 Spring jdbc 之后又开发了持久层框架,很明显 Spring data jpa 相对 ...
- springboot整合hibernate_峰哥说技术系列-17 .Spring Boot 整合 Spring Data JPA
今日份主题 Spring Boot 整合 Spring Data JPA JPA(Java Persistence API)是用于对象持久化的 API,是Java EE 5.0 平台标准的 ORM 规 ...
- SpringBoot 实战 (八) | 使用 Spring Data JPA 访问 Mysql 数据库
微信公众号:一个优秀的废人 如有问题或建议,请后台留言,我会尽力解决你的问题. 前言 如题,今天介绍 Spring Data JPA 的使用. 什么是 Spring Data JPA 在介绍 Spri ...
- springboot jpa sql打印_SpringBoot集成Spring Data JPA以及读写分离
相关代码:github OSCchina JPA是什么 JPA(Java Persistence API)是Sun官方提出的Java持久化规范,它为Java开发人员提供了一种对象/关联映射工具 来管理 ...
最新文章
- React系列---Redux高阶运用
- ecplise 使用 git
- java中 有没有方法将浏览器标签栏去掉_用JS去掉IE窗口的标题栏,工具栏,地址栏...
- vb子程序未定义怎么改怎么办_vb中子程序或者函数未定义!求教解决方案,
- requests与bs4编码
- python动态图形_利用matplotlib实现根据实时数据动态更新图形
- python爬虫使用代理ip_爬虫使用代理IP的为什么不能全部成功
- 二叉树:你真的会翻转二叉树么?
- fork函数_Linux中子进程回收函数:wait和waitpid
- 算法导论 资源 课后答案 PDF
- 51单片机驱动TM1638芯片+Proteus仿真
- FastReport报表控件使用技巧总结
- 七大江河水系--黄河(二)
- java并发三大特性--有序性、可见性、原子性
- php fileinfo 作用,PHP Fileinfo函数 详解
- LightSwitch 社区内容汇总 – 2012年9月
- AndroidStudio运行app,会装上多个app
- java语言for模板_Java中使用FreeMaker实现模板渲染
- 名悦集团:为什么司机建议买车尽量买便宜的
- 既然硕士毕业也去搞开发,那还去读研值吗?
热门文章
- MAC中SPSS无法打开数据
- 深入理解CatBoost
- 通过倍福Twincat的R3IO添加外部C++程序
- vue build打包后提示:Tip: built files are meant to be served over an HTTP server
- python计算无穷级数求和_[探求无穷级数求和的几种常用方法]无穷级数求和常用公式...
- 使用Java写入Excel下拉选择框选项过多不显示问题
- redis读缓存超时故障处理
- 安卓 控件靠右对齐_LinearLayout中组件右对齐
- linux添加字体库
- 算法题:矩阵修改为黑白矩阵