概念
JPA 由来
JPA 是什么
Spring Data JPA
快速上⼿
添加依赖
<dependency>
<groupId>org.Springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
添加配置⽂件
spring.datasource.url=jdbc:mysql://localhost:3306/test?serverTimezone=UTC&useUnico
de=true&characterEncoding=utf-8&useSSL=true
spring.datasource.username=root
spring.datasource.password=root
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.jpa.properties.hibernate.hbm2ddl.auto=create
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL5InnoDBDialect
#SQL 输出
spring.jpa.show-sql=true
#format ⼀下 SQL 进⾏输出
spring.jpa.properties.hibernate.format_sql=true
- create:每次加载 Hibernate 时都会删除上⼀次⽣成的表,然后根据 model 类再重新来⽣成新表,哪怕 两次没有任何改变也要这样执⾏,这就是导致数据库表数据丢失的⼀个重要原因。
- create-drop:每次加载 Hibernate 时根据 model 类⽣成表,但是 sessionFactory ⼀关闭,表就⾃动删 除。
- update:最常⽤的属性,第⼀次加载 Hibernate 时根据 model 类会⾃动建⽴起表的结构(前提是先建⽴ 好数据库),以后加载 Hibernate 时根据 model 类⾃动更新表结构,即使表结构改变了,但表中的⾏仍 然存在,不会删除以前的⾏。要注意的是当部署到服务器后,表结构是不会被⻢上建⽴起来的,是要等 应⽤第⼀次运⾏起来后才会。
- validate :每次加载 Hibernate 时,验证创建数据库表结构,只会和数据库中的表进⾏⽐较,不会创建 新表,但是会插⼊新值。
- dialect 主要是指定⽣成表名的存储引擎为 InneoDB
- show-sql 是否在⽇志中打印出⾃动⽣成的 SQL,⽅便调试的时候查看
实体类
@Entity
public class User {
@Id
@GeneratedValue
private Long id;
@Column(nullable = false, unique = true)
private String userName;
@Column(nullable = false)
private String passWord;
@Column(nullable = false, unique = true)
private String email;
@Column(nullable = true, unique = true)
private String nickName;
@Column(nullable = false)
private String regTime;
//省略getter settet⽅法、构造⽅法
}
- @Entity(name="EntityName") 必须,⽤来标注⼀个数据库对应的实体,数据库中创建的表名默 认和类名⼀致。其中,name 为可选,对应数据库中⼀个表,使⽤此注解标记 Pojo 是⼀个 JPA 实体。
- @Table(name="",catalog="",schema="") 可选,⽤来标注⼀个数据库对应的实体,数据库 中创建的表名默认和类名⼀致。通常和 @Entity 配合使⽤,只能标注在实体的 class 定义处,表示实体 对应的数据库表的信息。
- @Id 必须,@Id 定义了映射到数据库表的主键的属性,⼀个实体只能有⼀个属性被映射为主键。
- @GeneratedValue(strategy=GenerationType,generator="") 可选,strategy: 表示主键 ⽣成策略,有 AUTO、INDENTITY、SEQUENCE 和 TABLE 4 种,分别表示让 ORM 框架⾃动选择, generator: 表示主键⽣成器的名称。
- @Column(name = "user_code", nullable = false, length=32) 可选,@Column 描 述了数据库表中该字段的详细定义,这对于根据 JPA 注解⽣成数据库表结构的⼯具。name: 表示数据库 表中该字段的名称,默认情形属性名称⼀致;nullable: 表示该字段是否允许为 null,默认为 true; unique: 表示该字段是否是唯⼀标识,默认为 false;length: 表示该字段的⼤⼩,仅对 String 类型的字段 有效。
- @Transient 可选,@Transient 表示该属性并⾮⼀个到数据库表的字段的映射,ORM 框架将忽略该 属性。
- @Enumerated 可选,使⽤枚举的时候,我们希望数据库中存储的是枚举对应的 String 类型,⽽不是 枚举的索引值,需要在属性上⾯添加 @Enumerated(EnumType.STRING) 注解。
Repository 构建
public interface UserRepository extends JpaRepository<User, Long> {
User findByUserName(String userName);
User findByUserNameOrEmail(String username,String email);
}
public interface QueryByExampleExecutor<T> {
<S extends T> S findOne(Example<S> example); //根据“实例”查找⼀个对象
<S extends T> Iterable<S> findAll(Example<S> example); //根据“实例”查找⼀批对
象
<S extends T> Iterable<S> findAll(Example<S> example, Sort sort); //根据“实例”
查找⼀批对象,且排序
<S extends T> Page<S> findAll(Example<S> example, Pageable pageable); //根据“
实例”查找⼀批对象,且排序和分⻚
<S extends T> long count(Example<S> example); //根据“实例”查找,返回符合条件的对象
个数
<S extends T> boolean exists(Example<S> example); //根据“实例”判断是否有符合条件的
对象
}
@NoRepositoryBean
public interface CrudRepository<T, ID> extends Repository<T, ID> {
<S extends T> S save(S entity);
<S extends T> Iterable<S> saveAll(Iterable<S> entities);
Optional<T> findById(ID id);
boolean existsById(ID id);
Iterable<T> findAll();
Iterable<T> findAllById(Iterable<ID> ids);
long count();
void deleteById(ID id);
void delete(T entity);
void deleteAll(Iterable<? extends T> entities);
void deleteAll();
}
测试
@RunWith(SpringRunner.class)
@SpringBootTest
public class UserRepositoryTests {
@Resource
private UserRepository userRepository;
@Test
public void test() {
Date date = new Date();
DateFormat dateFormat = DateFormat.getDateTimeInstance(DateFormat.LONG, Da
teFormat.LONG);
String formattedDate = dateFormat.format(date);
userRepository.save(new User("aa", "aa@126.com", "aa", "aa123456",format
tedDate));
userRepository.save(new User("bb", "bb@126.com", "bb", "bb123456",format
tedDate));
userRepository.save(new User("cc", "cc@126.com", "cc", "cc123456",format
tedDate));
Assert.assertEquals(9, userRepository.findAll().size());
Assert.assertEquals("bb", userRepository.findByUserNameOrEmail("bb", "cc@
126.com").getNickName());
userRepository.delete(userRepository.findByUserName("aa1"));
}
}
基本查询
预⽣成⽅法
public interface UserRepository extends JpaRepository<User, Long> {
}
@Test
public void testBaseQuery() {
userRepository.findAll();
userRepository.findById(1l);
userRepository.save(user);
userRepository.delete(user);
userRepository.count();
userRepository.existsById(1l);
// ...
}
⾃定义查询
User findByUserName(String userName);
User findByUserNameOrEmail(String username, String email);
Long deleteById(Long id);
Long countByUserName(String userName)
List<User> findByEmailLike(String email);
User findByUserNameIgnoreCase(String userName);
List<User> findByUserNameOrderByEmailDesc(String email);
Keyword | Sample | JPQL snippet |
And |
findByLastnameAndFirstname | … where x.lastname = ?1 and x.firstname = ?2 |
Or |
findByLastnameOrFirstname | … where x.lastname = ?1 or x.firstname = ?2 |
Is,Equals | findByFirstnameIs, findByFirstnameEquals |
… where x.firstname = ?1 |
Between | findByStartDateBetween | … where x.startDate between ?1 and ?2 |
LessThan | findByAgeLessThan | … where x.age < ?1 |
LessThanEqual | findByAgeLessThanEqual | … where x.age ⇐ ?1 |
GreaterThan | findByAgeGreaterThan | … where x.age > ?1 |
GreaterThanEqual | findByAgeGreaterThanEqual | … where x.age >= ?1 |
After | findByStartDateAfter | … where x.startDate > ?1 |
Before | findByStartDateBefore | … where x.startDate < ?1 |
IsNull | findByAgeIsNull | … where x.age is null |
IsNotNull, NotNull |
findByAge(Is)NotNull |
… where x.age not null |
Like | findByFirstnameLike | … where x.firstname like ?1 |
NotLike | findByFirstnameNotLike | … where x.firstname not like ?1 |
StartingWith |
findByFirstnameStartingWith | … where x.firstname like ?1 (parameter bound with appended %) |
EndingWith |
findByFirstnameEndingWith | … where x.firstname like ?1 (parameter bound with prepended %) |
Containing |
findByFirstnameContaining | … where x.firstname like ?1 (parameter bound wrapped in %) |
OrderBy |
findByAgeOrderByLastnameDesc | … where x.age = ?1 order by x.lastname desc |
Not | findByLastnameNot | … where x.lastname <> ?1 |
In | findByAgeIn(Collection ages) | … where x.age in ?1 |
NotIn | findByAgeNotIn(Collection age) | … where x.age not in ?1 |
|
|
|