Spring Data JPA简单教程

Spring Data JPA 简单教程。

配置类:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
@Configuration
@EnableTransactionManagement
@EnableJpaRepositories("com.framework.dao")
@PropertySource("classpath:jdbc.properties")
public class DataConfig {
//数据库连接配置
private static final String DATABASE_DRIVER="db.driver";
private static final String DATABASE_USERNAME="db.user";
private static final String DATABASE_PASSWORD="db.pwd";
private static final String DATABASE_URL="db.url";
//Hibernate配置
private static final String HIBERNATE_DIALECT="hibernate.dialect";
private static final String HIBERNATE_SHOW_SQL="hibernate.show_sql";
private static final String HIBERNATE_FORMAT_SQL="hibernate.format_sql";
private static final String HIBERNATE_HBM2DDL_AUTO="hibernate.hbm2ddl.auto";
//需要扫描的数据原型包
private static final String PACKAGES_TO_SCAN="com.framework.model";

@Autowired
private Environment env;

@Bean
public DriverManagerDataSource dataSource() {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
//读取配置文件中的信息
dataSource.setDriverClassName(env.getRequiredProperty(DATABASE_DRIVER));
dataSource.setUrl(env.getRequiredProperty(DATABASE_URL));
dataSource.setUsername(env.getRequiredProperty(DATABASE_USERNAME));
dataSource.setPassword(env.getRequiredProperty(DATABASE_PASSWORD));
return dataSource;
}

@Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory(){
LocalContainerEntityManagerFactoryBean factory = new LocalContainerEntityManagerFactoryBean();
factory.setDataSource(dataSource());
factory.setPackagesToScan(PACKAGES_TO_SCAN);
factory.setJpaVendorAdapter(new HibernateJpaVendorAdapter());
factory.setJpaProperties(hibernateProperties());

return factory;
}

@Bean
public JpaTransactionManager transactionManager(){
JpaTransactionManager manager = new JpaTransactionManager();
manager.setEntityManagerFactory(entityManagerFactory().getObject());
return manager;
}

private Properties hibernateProperties(){
Properties pros = new Properties();
pros.setProperty(HIBERNATE_DIALECT, env.getRequiredProperty(HIBERNATE_DIALECT));
pros.setProperty(HIBERNATE_SHOW_SQL, env.getRequiredProperty(HIBERNATE_SHOW_SQL));
pros.setProperty(HIBERNATE_FORMAT_SQL, env.getRequiredProperty(HIBERNATE_FORMAT_SQL));
pros.setProperty(HIBERNATE_HBM2DDL_AUTO, env.getRequiredProperty(HIBERNATE_HBM2DDL_AUTO));

return pros;
}
}

@Configuration
@EnableWebMvc
@Import({DataConfig.class}) //引入上面的数据配置类
@ComponentScan(basePackages={"com.framework.controller, com.framework.service"})
public class WebMvcConfig extends WebMvcConfigurerAdapter{

@Bean
public ViewResolver viewResolver(){
InternalResourceViewResolver resolver = new InternalResourceViewResolver();
resolver.setPrefix("/WEB-INF/page/");
resolver.setSuffix(".jsp");
return resolver;
}

public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/resources/**").addResourceLocations("/resources/");
}

@Override
public void configureMessageConverters(
List<HttpMessageConverter<?>> converters) {
super.configureMessageConverters(converters);
GsonHttpMessageConverter converter = new GsonHttpMessageConverter();
Gson gson = new GsonBuilder().setFieldNamingPolicy(FieldNamingPolicy.UPPER_CAMEL_CASE).create();
converter.setGson(gson);
converters.add(converter);
}
}

数据原型

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
@Entity
@Table(name="user")
public class UserBean {
private int id;
private String username;
private String password;
private String createDate;
private String timestamp;

//主键,自动生成
@Id @GeneratedValue(strategy=GenerationType.AUTO)
public int getId() {
return id;
}
@Column(unique=true,nullable=false,length=50)
public String getUsername() {
return username;
}
@Column(nullable=false,length=50)
public String getPassword() {
return password;
}
@Column(length=25)
public String getCreateDate() {
return createDate;
}
//临时状态,不会存到数据库中
@Transient
public String getTimestamp() {
return timestamp;
}
//setter...
}

DAO层(com.framework.dao)
使用了SpringDataJpa之后DAO层只要定义接口即可,无需再定义一个类实现它的方法,默认开头为findBy的方法都是查找数据的方法,后面还可以跟其他的关键字,比如LessThan,Like,OrderBy等等,与SQL关键字的功能一样。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public interface UserDao extends JpaRepository<UserBean,Integer>{
//以findBy开头的方法则是查询数据
public UserBean findByUsernameAndPassword(String username,String password);
//以countByd开头的方法则是统计数据
public long countByUsername(String username);
//@Query注解可以指定查询语句获取制定的返回数据
@Query("select createDate from UserBean where username = :name")
public String findByUsernameAndUsertype(@Param("name")String username);
//nativeQuery可以使用原生SQL查询
@Query(value="select * from user where createDate = :createDate "
+"order by convert(uname using gbk)",nativeQuery=true)
public List<UserBean> findByUserStatus(@Param("createDate")String createDate);

}

JpaRepository是继承于PagingAndSortingRepository,此接口提供了分页查询排序功能,而它又继承于CrudRepository,此接口则提供了最基本的增删查改功能。接口后面跟的泛型参数为数据模型类与主键的类型。

服务层(com.framework.service)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
@Service
@Transactional(propagation=Propagation.REQUIRED)
public class UserService {
@Autowired
private UserDao userDao;

public void saveUser(UserBean user) {
userDao.save(user);
}

public void deleteUser(int id) {
userDao.delete(id);
}

@Transactional(propagation=Propagation.NOT_SUPPORTED,readOnly=true)
public boolean checkUsername(String username) {
return userDao.countByUsername(username) > 0;
}

@Transactional(propagation=Propagation.NOT_SUPPORTED,readOnly=true)
public List<UserBean> selectAll(String orderBy, String sc, int page, int size) {
//这里的page是指第几页,而不是从多少开始,例如指定为1,则是显示 limit 1*size,size
Pageable pageable = new PageRequest(page, size, sc.equals("asc")?Direction.ASC:Direction.DESC, orderBy);
return userDao.findAll(pageable).getContent();
}
//...
}

在服务层,增/改操作皆为save,传入的类有ID则为修改,无则为添加

控制层(com.framework.controller)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
@RestController
@RequestMapping("/user")
public class UserController {
@Autowired
private UserService userService;

@RequestMapping(value="/save", method=RequestMethod.POST)
public void saveUser(UserBean user){
user.setCreateDate(CommonUtil.cloneDate(Calendar.DATE, 0));
userService.saveUser(user);
}

@RequestMapping(value="/del/{id}", method=RequestMethod.POST)
public void userDel(@PathVariable int id){
userService.deleteUser(id);
}

@RequestMapping(value="/list",method=RequestMethod.GET,produces="text/html;charset=UTF-8")
public List<UserBean> list(@RequestParam String sortCol, @RequestParam String sortDir, @RequestParam int start, @RequestParam int length) {
List<UserBean> users = userService.selectAll(sortCol, sortDir, start, length);
//在配置类中配置了包装json的转换器,因此直接返回对应集合即可
return users;
}
}

测试一下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
@RunWith(SpringJUnit4ClassRunner.class)
@WebAppConfiguration
@ContextConfiguration(classes = { TestConfig.class })
public class TestController {

@Test
public void testCheckFileInfo() throws Exception {
mockMvc.perform(MockMvcRequestBuilders.post("/user/add")
.param("username", "11")
.param("password", "11"))
.andDo(MockMvcResultHandlers.print())
.andReturn();
}

//...
}

参考
Spring JPA Data + Hibernate + MySQL + Maven
Spring Data Jpa 详解 (配置篇)
spring-data-jpa 使用
深入浅出学Spring Data JPA