Spring Data Jpa(三)
程序员文章站
2022-04-25 20:01:30
...
Spring Data Jpa介绍
A、Spring Data JPA 是 Spring 基于 ORM 框架、JPA 规范的基础上封装的套 JPA 应用框架,
可使开发者用极简的代码即可实现对数据的访问和操作。它提供了包括增删改查等在内的常用功能,
且易于扩展!学习并使用 Spring Data JPA 可以极大提高开发效率!
B、Spring Data JPA 简化了 DAO 层的操作,基本上所有 CRUD 都可以依赖于其实现。
1、入门案例
A、添加依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
B、添加配置文件:
# 配置数据库
spring.datasource.url=jdbc:mysql://localhost:3306/test
spring.datasource.username=root
spring.datasource.password=root
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
# 配置 Jpa 相关参数
spring.jpa.properties.hibernate.hbm2ddl.auto=update
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL5InnoDBDialect
spring.jpa.show-sql= true
# hibernate.hbm2ddl.auto 参数的作用主要用于:自动创建 | 更新 | 验证数据库表结构,有四个值:
# create:每次加载 hibernate 时都会删除上一次的生成的表,然后根据 model 类再重新来生成新表,
# 哪怕两次没有任何改变也要这样执行,这就是导致数据库表数据丢失的一个重要原因。
# create-drop:每次加载 hibernate 时根据 model 类生成表,但是 sessionFactory 关闭,表就自动删除。
# update:最常用的属性,第1次加载 hibernate 时根据 model 类会自动建立起表的结构(前提是先建好
# 数据库),以后加载 hibernate 时根据 model 类自动更新表结构,即使表结构改变了,但表中的行仍
# 然存在,不会删除以前的行。要注意的是当部署到服务器后,表结构是不会被马上建立起来的,是要等
# 应用第一次运行起来后才会。
# validate:每次加载 hibernate 时,验证创建数据库表结构,只会和数据库中的表进行比较,不会创建新
# 表,但是会插入新值。
# dialect:主要是指定生成表名的存储引擎为 InneoDB。
# show-sql:是否打印出自动生产的 SQL,方便调试的时候查看。
C、添加实体类和Dao : Entity 中不映射成列的字段得加 @Transient 注解,不加注解也会映射成列
@Entity
public class User implements Serializable {
@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 = false)
private String regTime;
//省略 getter settet 方法、构造方法
}
Dao:
public interface UserRepository extends JpaRepository<User, Long> {
User findByUserName(String userName);
User findByUserNameOrEmail(String username,String email);
}
D、编写测试类
@RunWith(SpringRunner.class)
@SpringBootTest
public class UserRepositoryTest {
@Resource
private UserRepository userRepository;
@Test
public void findByUserName() throws Exception {
/**
* 数据库造数据
* Date date=new Date();
* DateFormat dateFormat = DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.LONG);
* String formatDate = dateFormat.format(date);
* userRepository.save(new User("aa", "aa123456","[email protected]",formatDate));
* userRepository.save(new User("bb", "bb123456","[email protected]",formatDate));
* userRepository.save(new User("cc", "cc123456","[email protected]",formatDate));
*/
Assert.assertEquals(3,userRepository.findAll().size());
//userRepository.delete(userRepository.findByUserName("aa"));
}
@Test
public void findByUserNameOrEmail() throws Exception {
Assert.assertEquals("bb",userRepository.findByUserNameOrEmail("bb","[email protected]").getUserName());
}
}
2、基本查询分为两种,① Spring Data 默认已经实现 ② 根据查询的方法来自动解析成 SQL。
A、Spring Data JPA 默认预先生成一些基本的 CURD 的方法,如增、删、改等。
继承 JpaRepository:
public interface UserRepository extends JpaRepository<User, Long> {
}
使用默认方法:
@Test
public void testBaseQuery() {
userRepository.findAll();
userRepository.findOne(1l);
userRepository.save(user);
userRepository.delete(user);
userRepository.count();
userRepository.exists(1l);
// ...
}
B、自定义的简单查询就是根据方法名来自动生成 SQL,主要的语法是 findXXBy、readAXXBy、queryXXBy、countXXBy、getXXBy
后面跟属性名称:
User findByUserName(String userName);
也可加一些关键字 And、Or:
User findByUserNameOrEmail(String username, String email);
修改、删除、统计类似语法:
Long deleteById(Long id);
Long countByUserName(String userName)
基本上 SQL 体系中的关键词都可以使用,如 LIKE、IgnoreCase、OrderBy:
List<User> findByEmailLike(String email);
User findByUserNameIgnoreCase(String userName);
List<User> findByUserNameOrderByEmailDesc(String email);
3、复杂查询
在实际的开发中需要用到分页、筛选、连表等查询的时候就需要特殊的方法或者自定义 SQL。
分页查询:
分页查询在实际使用中非常普遍,Spring Data JPA 已经帮我们实现了分页的功能,在查询的方法中,
需要传入参数 Pageable,当查询中有多个参数的时候, Pageable 建议做为最后一个参数传入
Pageable 是 Spring 封装的分页实现类,使用的时候需要传入页数、每页条数和排序规则。
@Query("select u from User u")
Page<User> findALL(Pageable pageable);
Page<User> findByUserName(String userName,Pageable pageable);
测试
@Test
public void testPageQuery(){
int page=1,size=2;
Sort sort=new Sort(Sort.Direction.DESC,"id");
Pageable pageable=new PageRequest(page,size,sort);
userRepository.findALL(pageable);
userRepository.findByUserName("aa",pageable);
}
4、自定义SQL查询
A、使用 Spring Data 大部分的 SQL 都可以根据方法名定义的方式来实现,如果我们想使用自定义的
SQL 来查询,Spring Data 也可以支持
B、在 SQL 的查询方法上面使用 @Query 注解,如涉及到删除和修改需要加上 @Modifying,也可以
根据需要添加 @Transactional 对事物的支持,查询超时的设置等。
@Transactional(timeout = 10)
@Modifying
@Query("update User set userName =?1 where id =?2")
int modifyById(String userName,Long id);
@Transactional
@Modifying
@Query("delete from User where id =?1")
void deleteById(Long id);
@Query("select u from User u where u.email = ?1")
User findByEmail(String email);
5、多数据源的支持(重点)
项目开发中,常需要在一个项目中使用多个数据源,因此需要配置 Spring Data JPA 对多数据源的使用,一般分为以下三步:
a、配置多数据源
b、不同源的 repository 放入不同包路径
c、声明不同的包路径下使用不同的数据源、事务支持
0、实体类所在包 com.kid.domain
@Entity
public class User implements Serializable {
@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、setter、构造方法省略...
}
A、配置两个数据源:
#primary
spring.primary.datasource.url=jdbc:mysql://localhost:3306/test1
spring.primary.datasource.username=root
spring.primary.datasource.password=root
spring.primary.datasource.driver-class-name=com.mysql.jdbc.Driver
#secondary
spring.secondary.datasource.url=jdbc:mysql://localhost:3306/test2
spring.secondary.datasource.username=root
spring.secondary.datasource.password=root
spring.secondary.datasource.driver-class-name=com.mysql.jdbc.Driver
B、读取两个配置源,构建两个数据源:
com.kid.config 包下:
@Configuration
public class DataSourceConfig {
@Bean(name = "primaryDataSource")
@Qualifier("primaryDataSource")
@ConfigurationProperties(prefix="spring.primary.datasource")
public DataSource primaryDataSource() {
return DataSourceBuilder.create().build();
}
@Bean(name = "secondaryDataSource")
@Qualifier("secondaryDataSource")
@Primary
@ConfigurationProperties(prefix="spring.secondary.datasource")
public DataSource secondaryDataSource() {
return DataSourceBuilder.create().build();
}
}
C、将数据源注入到 Factory,配置 repository、domian 的位置,需要设置一个默认的数据源:
com.kid.config 包下:
PrimaryConfig:
@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(
entityManagerFactoryRef="entityManagerFactoryPrimary",
transactionManagerRef="transactionManagerPrimary",
basePackages= { "com.kid.repository.test1" })//设置dao(repo)所在位置
public class PrimaryConfig {
@Autowired
private JpaProperties jpaProperties;
@Autowired
@Qualifier("primaryDataSource")
private DataSource primaryDataSource;
@Bean(name = "entityManagerPrimary")
@Primary
public EntityManager entityManager(EntityManagerFactoryBuilder builder) {
return entityManagerFactoryPrimary(builder).getObject().createEntityManager();
}
@Bean(name = "entityManagerFactoryPrimary")
@Primary
public LocalContainerEntityManagerFactoryBean entityManagerFactoryPrimary (EntityManagerFactoryBuilder builder) {
return builder
.dataSource(primaryDataSource)
.packages("com.kid.domain") //设置实体类所在位置
.persistenceUnit("primaryPersistenceUnit")
.properties(getVendorProperties())
.build();
}
private Map<String, Object> getVendorProperties() {
return jpaProperties.getHibernateProperties(new HibernateSettings() );
}
@Bean(name = "transactionManagerPrimary")
@Primary
PlatformTransactionManager transactionManagerPrimary(EntityManagerFactoryBuilder builder) {
return new JpaTransactionManager(entityManagerFactoryPrimary(builder).getObject());
}
}
SecondaryConfig:
@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(
entityManagerFactoryRef="entityManagerFactorySecondary",
transactionManagerRef="transactionManagerSecondary",
basePackages= { "com.kid.repository.test2" })
public class SecondaryConfig {
@Autowired
private JpaProperties jpaProperties;
@Autowired
@Qualifier("secondaryDataSource")
private DataSource secondaryDataSource;
@Bean(name = "entityManagerSecondary")
public EntityManager entityManager(EntityManagerFactoryBuilder builder) {
return entityManagerFactorySecondary(builder).getObject().createEntityManager();
}
@Bean(name = "entityManagerFactorySecondary")
public LocalContainerEntityManagerFactoryBean entityManagerFactorySecondary (EntityManagerFactoryBuilder builder) {
return builder
.dataSource(secondaryDataSource)
.properties(getVendorProperties())
.packages("com.kid.domain")
.persistenceUnit("secondaryPersistenceUnit")
.build();
}
private Map<String, Object> getVendorProperties() {
return jpaProperties.getHibernateProperties(new HibernateSettings());
}
@Bean(name = "transactionManagerSecondary")
PlatformTransactionManager transactionManagerSecondary(EntityManagerFactoryBuilder builder) {
return new JpaTransactionManager(entityManagerFactorySecondary(builder).getObject());
}
}
D、配置Dao
com.kid.repository.test1
public interface UserTest1Repository extends JpaRepository<User, Long> {
User findByUserName(String userName);
User findByUserNameOrEmail(String username, String email);
}
com.kid.repository.test2
public interface UserTest2Repository extends JpaRepository<User, Long> {
User findByUserName(String userName);
User findByUserNameOrEmail(String username, String email);
}
E:测试类编写
@Resource
private UserTest1Repository userTest1Repository;
@Resource
private UserTest2Repository userTest2Repository;
@Test
public void testSave() throws Exception {
Date date = new Date();
DateFormat dateFormat = DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.LONG);
String formattedDate = dateFormat.format(date);
userTest1Repository.save(new User("aa", "aa123456","[email protected]", "aa", formattedDate));
userTest1Repository.save(new User("bb", "bb123456","[email protected]", "bb", formattedDate));
userTest2Repository.save(new User("cc", "cc123456","[email protected]", "cc", formattedDate));
}
查看数据库会发现 test1 会有两条数据,test2 有一条。在实际使用中需要哪个数据源使用 @Resource 注入即可。
上一篇: 你生日
下一篇: 201712-2 游戏
推荐阅读
-
Spring Data JPA实现分页Pageable的实例代码
-
详解spring boot jpa整合QueryDSL来简化复杂操作
-
spring data jpa使用详解(推荐)
-
Maven工程搭建spring boot+spring mvc+JPA的示例
-
Spring Data JPA例子代码[基于Spring Boot、Mysql]
-
Spring-Data-JPA整合MySQL和配置的方法
-
详解JAVAEE——SSH三大框架整合(spring+struts2+hibernate)
-
Spring注入值到Bean的三种方式
-
[Oracle] Data Guard 之 三种保护模式介绍
-
在Spring Boot中使用Spring-data-jpa实现分页查询