0%

使用Java类配置整合SpringDataJPA

在学Spring的路上偶然用上了一次SpringDataJpa , 不需要自己手写sql的方式 , 让我用的非常舒服 , 这和我以前用的mybatis用起来是完全不一样的体验 , 不过由于之前对Spring不是特别的了解 , 是跟着书上的XML配置一步一步走过来的.

现在回头看过去发现这种配置虽然简单易上手 , 但是XML配置标签繁多 , 可读性差 ,而且最大的问题是类型不安全.

SPring还支持XML + 注解的方式进行配置 , 这种配置简单明了 , 但是注解的配置只能针对自定义的包进行快速配置 , 对于第三方类库 , 我们还是需要XML来配置.

不过从Spring3.0开始 , Spring支持了一种新的配置方式 JavaConfig , 也就是通过java类来进行Spring的配置.

emmm, 讲多了 ,其实使用java类配置纯粹因为我懒,xml写起来太麻烦了 , 有时候还不带联想 23333

项目环境

  • JDK 1.8
  • IDEA 19.01
  • Maven 3.6

这里只做了Spring整合SpringDataJPA的配置 , 然后用单测进行测试 , 没有和SpringMVC进行整合

项目依赖

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
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
<!-- 依赖版本控制 -->
<properties>
<spring.version>4.2.4.RELEASE</spring.version>
<hibernate.version>5.0.7.Final</hibernate.version>
<slf4j.version>1.6.6</slf4j.version>
<log4j.version>1.2.12</log4j.version>
<c3p0.version>0.9.1.2</c3p0.version>
<mysql.version>5.1.6</mysql.version>
</properties>

<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>

<!-- spring beg -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
</dependency>

<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<version>${spring.version}</version>
</dependency>

<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-orm</artifactId>
<version>${spring.version}</version>
</dependency>

<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>${spring.version}</version>
</dependency>

<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${spring.version}</version>
</dependency>

<!-- spring end -->

<!-- hibernate beg -->
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>${hibernate.version}</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-entitymanager</artifactId>
<version>${hibernate.version}</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
<version>5.2.1.Final</version>
</dependency>
<!-- hibernate end -->

<!-- c3p0 beg -->
<dependency>
<groupId>c3p0</groupId>
<artifactId>c3p0</artifactId>
<version>${c3p0.version}</version>
</dependency>
<!-- c3p0 end -->

<!-- log end -->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>${log4j.version}</version>
</dependency>

<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>${slf4j.version}</version>
</dependency>

<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>${slf4j.version}</version>
</dependency>
<!-- log end -->


<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>${mysql.version}</version>
</dependency>

<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-jpa</artifactId>
<version>1.9.0.RELEASE</version>
</dependency>

<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>4.2.4.RELEASE</version>
</dependency>

<!-- el beg 使用spring data jpa 必须引入 -->
<dependency>
<groupId>javax.el</groupId>
<artifactId>javax.el-api</artifactId>
<version>2.2.4</version>
</dependency>

<dependency>
<groupId>org.glassfish.web</groupId>
<artifactId>javax.el</artifactId>
<version>2.2.4</version>
</dependency>
<!-- el end -->
</dependencies>

创建工程

使用idea创建maven项目 , 选空骨架或者quickstart都可以 , 这里不整合Springmvc不用选webapp .

创建完项目后 , 把大概目录创建好
项目结构

进行配置

java配置类

在config包下创建config类当作Spring的配置类

1
2
3
public class config {

}

添加@Configuration注解来声明当前类是一个配置类

1
2
3
4
@Configuration
public class config {

}

然后添加jpa核心beanEntityManagerFactory , 以及相关属性需要的bean

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
@Configuration
public class config {
/**
* 数据库连接池
* @return
* @throws PropertyVetoException
*/
@Bean
public DataSource dataSource() throws PropertyVetoException {
ComboPooledDataSource dataSource = new ComboPooledDataSource();
dataSource.setJdbcUrl("jdbc:mysql:///test");
dataSource.setDriverClass("com.mysql.jdbc.Driver");
dataSource.setPassword("root");
dataSource.setUser("root");
return dataSource;
}

/**
* jpa实现厂家
* @return
*/
@Bean
public HibernatePersistenceProvider persistenceProvider(){
return new HibernatePersistenceProvider();
}


/**
* 实现厂家适配器
* @return
*/
@Bean
public JpaVendorAdapter jpaVendorAdapter(){
HibernateJpaVendorAdapter jpaVendorAdapter =
new HibernateJpaVendorAdapter();
jpaVendorAdapter.setDatabase(Database.MYSQL);
jpaVendorAdapter.setGenerateDdl(false);
jpaVendorAdapter.setShowSql(true);
jpaVendorAdapter.setDatabasePlatform("org.hibernate.dialect.MySQLDialect");
return jpaVendorAdapter;
}

/**
* jpa方言
* @return
*/
@Bean
public JpaDialect jpaDialect(){
HibernateJpaDialect dialect = new HibernateJpaDialect();
return dialect;
}

/**
* jpa工厂类
* @return
* @throws PropertyVetoException
*/
@Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory() throws PropertyVetoException {
LocalContainerEntityManagerFactoryBean entityManagerFactory =
new LocalContainerEntityManagerFactoryBean();
// 设置数据库连接池
entityManagerFactory.setDataSource(dataSource());
// 设置自动扫描实体类
entityManagerFactory.setPackagesToScan("com.weison.domain");
// 设置jpa实现厂家
entityManagerFactory.setPersistenceProvider(persistenceProvider());
// 设置实现厂家适配器
entityManagerFactory.setJpaVendorAdapter(jpaVendorAdapter());
// 设置jpa方言
entityManagerFactory.setJpaDialect(jpaDialect());
return entityManagerFactory;
}

}

然后添加事务支持 , emmm , 虽然现在直接用单测也用不到事务 , 不过还是加上吧

1
2
3
4
5
6
7
8
9
10
/**
* 事务管理器
* @return
*/
@Bean
public PlatformTransactionManager transactionManager() throws PropertyVetoException {
JpaTransactionManager transactionManager = new JpaTransactionManager();
transactionManager.setEntityManagerFactory(entityManagerFactory().getObject());
return transactionManager;
}

最后在添加下包自动扫描注解 , 添加Jpa代理持久层扫描目录

1
2
3
4
5
6
7
8
9
// java配置类
@Configuration
// 自动扫描spring注解包路径
@ComponentScan("com.weison")
// Jpa代理持久层路径
@EnableJpaRepositories("com.weison.dao")
public class config {

}

@EnableJpaRepositories注解还支持其他一些属性的配置 , 如果jpa工厂和事务管理器的bean id不为规定写法 , 则需要自己添加属性
默认值

1
2
3
@EnableJpaRepositories(basePackages = "com.weison.dao",
entityManagerFactoryRef = "工厂beanid",
transactionManagerRef = "事务管理器beanid")

配置类搞完后现在来配置下实体类

配置实体类

创建Customer客户实体类
需要在实体类上加上两个注解

  • @Entity : 注明该类为实体类
  • @Table : 注明该实体类映射的数据库表 ,需要配置name属性
1
2
3
4
5
6
// 声明实体类
@Entity
// 映射表
@Table(name = "customer")
public class Customer {
}

然后配置实体类属性并配置属性对应的数据库表列

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
// 声明实体类
@Entity
// 映射表
@Table(name = "customer")
public class Customer {

// 指定主键
@Id
// 配置主键生成策略
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "cust_id")
private Long custId;

@Column(name = "cust_name")
private String custName;

@Column(name = "cust_source")
private String custSource;

@Column(name = "cust_industry")
private String custIndustry;

@Column(name = "cust_level")
private String custLevel;

@Column(name = "cust_address")
private String custAddress;

@Column(name = "cust_phone")
private String custPhone;

}

配置完成后 , 再来配置持久层

持久层配置

创建持久层接口 , 并继承Jpa接口来完成Jpa自动代理

1
2
3
4
5
6
7
8
9
10
11
12
/**
* JpaRepository<实体类类型, 主键类型>
* - 已经封装了基本的CRUD操作
* JpaSpecificationExecutor<实体类类型>
* - 负责复杂查询
*/
@Repository
public interface Customerdao extends JpaRepository<Customer,Long> ,
JpaSpecificationExecutor<Customer> {


}

配置到这里 , Spring和SpringdataJpa的整合已经完成了 , 可以进行测试看看

测试

创建test测试类

加上SPringtest注解

1
2
3
4
5
6
// 指定配置类位置
@ContextConfiguration(classes = {config.class})
// 使用SPringtest
@RunWith(SpringJUnit4ClassRunner.class)
public class AppTest {
}

编写测试方法进行测试 , 添加私有成员让Spring自动注入

1
2
3
4
5
6
7
8
9
10
11
12
13
@Autowired
private Customerdao customerdao;

/**
* 查询所有
*/
@Test
public void testFindAll(){
List<Customer> list = customerdao.findAll();
for (Customer customer : list) {
System.out.println(customer);
}
}

运行结果

ok , 测试很顺利 , 完美运行