而SpringDataJPA是什么样子的呢?相信学过hibernate的同学一定也学过hibernate template,甚至自己实现过hibernate template。没错,SpringData JPA就很像这样一款template,把该有的东西都给你封装好,当然,其强大不止这一点点。相信学过mybatis的同学也知道,我们只需要一个mapper接口与一些mapper.xml,就可以让其代理实现的持久层。SpringDataJPA在使用的时候,也只需要声明一个接口,让其Spring以代理的形式生成Dao。对于SpringDataJPA与hibernate等ORM框架、JPA的关系是这样子的:
SpringDataJPA对类似hibernate这样的框架又做了一层封装,以便于我们编程的时候使用更方便。好了,说了那么多理论,下面就开始实践吧。
org.springframework.boot
spring-boot-starter-parent
1.4.1.RELEASE
UTF-8
1.8
org.springframework.boot
${springBoot.groupId}
spring-boot-starter-web
${springBoot.groupId}
spring-boot-starter-data-jpa
${springBoot.groupId}
spring-boot-starter-test
mysql
mysql-connector-java
junit
junit
4.12
server:
port: 8080
tomcat:
uri-encoding: UTF-8
spring:
datasource:
url: jdbc:mysql://127.0.0.1:3306/springboot_test?characterEncoding=utf8
username: root
password: root
jpa:
database: MYSQL
show-sql: true
#hibernate ddl auto(validate,create,update,create-drop)
hibernate:
ddl-auto: update
naming:
strategy: org.hibernate.cfg.ImprovedNamingStrategy
properties:
hibernate:
dialect: org.hibernate.dialect.MySQL5Dialect
这些配置相信大家都能看得懂,最后一行是数据库方言,如果是oracle,就有oracle的方言。
package org.fage;
import org.springframework.boot.autoconfigure.domain.EntityScan;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.transaction.annotation.EnableTransactionManagement;
/**
*
* @author Caizhfy
* @email [email protected]
* @createTime 2017年10月30日
* @description JPA基础配置类
*
*/
@Order(Ordered.HIGHEST_PRECEDENCE)
@Configuration
@EnableTransactionManagement(proxyTargetClass=true)
@EnableJpaRepositories(basePackages={"org.fage.**.repository"})
@EntityScan(basePackages={"org.fage.**.domain"})
public class JpaConfiguration {
@Bean
PersistenceExceptionTranslationPostProcessor persistenceExceptionTranslationPostProcessor(){
return new PersistenceExceptionTranslationPostProcessor();
}
}
@Order声明了组件加载的顺序,其中接受一个整形值,值越低约先加载;
package org.fage;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.ImportAutoConfiguration;
import org.springframework.boot.autoconfigure.SpringBootApplication;
/**
*
* @author Caizhfy
* @email [email protected]
* @createTime 2017年10月30日
* @description Springboot-jpa学习创建步骤:
* 1.创建项目
* 2.添加依赖,填写配置类
* 3.配置application.yml
* 4.配置实体jpa关系
* 5.继承jpaRepository
* 6.编写测试用例
*/
@SpringBootApplication
@ImportAutoConfiguration(value=JpaConfiguration.class)
public class App {
public static void main(String[] args) {
SpringApplication.run(App.class, args);
}
}
@Entity
@Table(name = "department")
public class Department implements Serializable {
private static final long serialVersionUID = 159714803901985366L;
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
private Long id;
private String name;
@OneToMany(mappedBy="department",fetch=FetchType.LAZY)
private List users;
//getter and setter
...
}
@Entity
@Table(name = "user")
public class User implements Serializable{
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String username;
@Column(name = "create_date")
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@Temporal(TemporalType.TIMESTAMP)
private Date createDate;
//一对多映射
@ManyToOne
@JoinColumn(name = "department_id")
@JsonBackReference // 防止对象的递归访问
private Department department;
//多对多映射
@ManyToMany(fetch=FetchType.EAGER)
@JoinTable(name = "user_role",
joinColumns = {@JoinColumn(name="user_id")},
inverseJoinColumns = {@JoinColumn(name = "role_id")}
)
//getter and setter
}
@Entity
@Table(name="role")
public class Role implements Serializable{
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
private Long id;
private String name;
//getter and setter
}
package org.fage.repository;
import org.fage.domain.Department;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
@Repository
public interface DepartmentRepository extends JpaRepository{}
@Repository
public interface UserRepository extends JpaRepository{
//And用法
User findById(long id);
User findByIdAndUsername(long id, String username);
//Or用法
User findByIdOrUsername(long id, String name);
//Between用法
User findByCreateDateBetween(Date start, Date end);
//LessThan用法
List findByCreateDateLessThan(Date start);
//GreaterThan用法
List findByCreateDateGreaterThan(Date start);
//IsNull/IsNutNull用法
List findByUsernameIsNull();
//Like/NotLike用法
List findByUsernameLike(String username);
//OrderBy用法
List findByUsernameOrderByIdAsc(String username);
//Not用法
List findByUsernameNot(String username);
//In/NotIn用法
List findByUsernameIn(Collection nameList);
}
@Repository
public interface RoleRepository extends JpaRepository{}
@RunWith(SpringRunner.class)
@SpringBootTest
public class RepositoryTest {
private final Logger log = LoggerFactory.getLogger(RepositoryTest.class);
@Autowired
UserRepository userRepository;
@Autowired
RoleRepository roleRepository;
@Autowired
DepartmentRepository departmentRepository;
@Before
public void initData() {
departmentRepository.deleteAll();
roleRepository.deleteAll();
userRepository.deleteAll();
Department d = new Department();
d.setName("开发部");
departmentRepository.save(d);
Assert.assertNotNull(d.getId());
Role r = new Role();
r.setName("部门经理");
roleRepository.save(r);
Assert.assertNotNull(r.getId());
List roles = new ArrayList();
roles.add(r);
User u = new User();
u.setUsername("蔡智法");
u.setCreateDate(new Date());
u.setDepartment(d);
u.setRoles(roles);
userRepository.save(u);
Assert.assertNotNull(u.getId());
}
@Test
public void testGeneralMethod(){
System.out.println(userRepository.findByUsernameLike("蔡智法"));
}
@Test
public void testFindPage() {
//hibernate一对多分页原理:先分页,然后在将id作为引子查询(效率低)
Pageable pageable = new PageRequest(0, 5, new Sort(Sort.Direction.ASC, "id"));
Page page = departmentRepository.findAll(pageable);
System.out.println(page.getNumberOfElements());
}
}
至此,运行成功。其实如果你也动手试一试,发现增删改查都不需要实现代码就能拥有这些功能,这些Repository接口中还有很多方法可以尝试,希望大家自行踊跃尝试,太便捷了。