文章目录
写在前面
Spring Boot 系列文章源于 深入实践Spring Boot 一书(感谢作者)。时过境迁,我使用了更新的版本来学习,并且拓展了许多内容(结合文档)。写下系列的博客,一则为了加强记忆,便于回顾,再则也希望帮助到正在学习 Spring Boot 的同学。当然,这也算给自己列下了一个学习计划吧!
Spring Boot 引入 (后续所有的依赖配置均建立在此基础之上)
-
通过继承
spring-boot-starter-parent
<!-- Inherit defaults from Spring Boot --> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.1.8.RELEASE</version> </parent> <!-- Package as an executable jar; 不是必要的 --> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build>
-
如果不想继承父模块,通过使用scope=import依赖项,仍然可以保持依赖项管理(但不是插件管理)的好处
<dependencyManagement> <dependencies> <dependency> <!-- Import dependency management from Spring Boot --> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-dependencies</artifactId> <version>2.1.8.RELEASE</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement>
项目中还引入了 lombok
,有了它不在需要繁琐的 getter 和 setter 方法了,只需要一个 @Data
注解即可。
<!--lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.16.20</version>
</dependency>
一、JPA and Spring Data JPA
Java Persistence API是一种标准技术,允许将对象“映射”到关系数据库。spring-boot-starter-data-jpa
POM提供了一种快速启动方法。它提供了以下关键依赖项:
-
Hibernate:最流行的 JPA 实现之一
-
Spring Data JPA: 使基于 JPA 的
Repositories
易于实现 -
Spring ORMS:Spring 框架核心的ORM支持
1. 依赖配置
为了使用 JPA 和 Mysql ,首先在 maven 工程中 引入依赖 :
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
</dependencies>
2. 实体类
创建一些普通对象,用来与数据库的表建立映射关系;
假设现在有三个实体:部门、用户和角色,且一个用户只能隶属于一个部门,一个用户可以拥有多个角色。
@Data
@Entity
@Table(name="user")
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
private Date createDate;
@ManyToOne
@JoinColumn(name="dId")
private Deparment deparment;
@ManyToMany(cascade = {},fetch = FetchType.EAGER)
@JoinTable(name="user_role",joinColumns = {@JoinColumn(name = "user_id")},
inverseJoinColumns = {@JoinColumn(name="roles_id")})
private List<Role> roles;
}
@Data
@Entity
@Table(name = "role")
public class Role {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
}
@Data
@Entity
@Table(name = "deparment")
public class Deparment {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
}
3. Spring Data JPA Repositories
上面三个实体,实现了使用 Java 的普通对象 (POJO) 与数据库表建立映射关系(ORM) ,接下来使用 JPA 实现持久化。
实体使用 JPA 进行持久化的例子如下代码所示。它是一个接口,并继承与 JPA 资源库 JpaRepository 接口,并使用注解 @Repository
将这个接口也定义为一个资源库。
@Repository
public interface DeparmentRepository extends JpaRepository<Deparment,Long> {
}
@Repository
public interface RoleRepository extends JpaRepository<Role, Long> {
}
@Repository
public interface UserRepository extends JpaRepository<User,Long> {
}
这样就实现了对数据库进行增删改查、进行分页查询和指定排序的字段等操作。
4. 测试
测试代码写在 src.test.java
下,需要加入新的依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency>
application.yml 文件如下:
spring:
datasource:
url: jdbc:mysql://localhost:3306/springboot?characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&autoReconnect=true&serverTimezone=Asia/Shanghai
username: root
password: root
jpa:
database: mysql
show-sql: true
hibernate:
# 自动生成表结构
ddl-auto: update
Jpa 配置类:
@EnableTransactionManagement
@EnableJpaRepositories(basePackages = {"com.duofei.db.mysql.repositories"})
@EntityScan("com.duofei.db.mysql.entity")
public class JpaConfiguration {
}
测试代码如下:
@RunWith(SpringRunner.class)
@SpringBootTest
public class MysqlTest {
private static Logger logger = LoggerFactory.getLogger(MysqlTest.class);
@Autowired
private DeparmentRepository deparmentRepository;
@Autowired
private RoleRepository roleRepository;
@Autowired
private UserRepository userRepository;
@Before
public void initData(){
userRepository.deleteAll();
roleRepository.deleteAll();
deparmentRepository.deleteAll();
Deparment deparment = new Deparment();
deparment.setName("开发部");
deparmentRepository.save(deparment);
Assert.assertNotNull(deparment.getId());
Role role = new Role();
role.setName("admin");
roleRepository.save(role);
Assert.assertNotNull(role.getId());
User user = new User();
user.setName("user");
user.setCreateDate(new Date());
user.setDeparment(deparment);
List<Role> roles = roleRepository.findAll();
Assert.assertNotNull(roles);
user.setRoles(roles);
userRepository.save(user);
Assert.assertNotNull(user.getId());
}
@Test
public void pageFind(){
PageRequest pageRequest = PageRequest.of(0, 10);
Page<User> users = userRepository.findAll(pageRequest);
Assert.assertNotNull(users);
users.getContent().forEach(user -> {
logger.info("===user=== user name:{}, department name:{}, roles : {}",user.getName(),user.getDeparment().getName(),user.getRoles());
});
}
}
二、JdbcTemplate
JdbcTemplate
不需要额外的配置,在 yml 文件配置完成后就可以使用了。
测试代码加入以下代码:
@Autowired
private JdbcTemplate jdbcTemplate;
@Test
public void findAll(){
List<User> users = jdbcTemplate.query("select * from user", rs ->{
List<User> result = new ArrayList<>();
while (rs.next()){
User user = new User();
user.setId(rs.getLong("id"));
user.setCreateDate(rs.getDate("create_date"));
user.setName(rs.getString("name"));
result.add(user);
}
return result;
});
users.forEach(user ->
logger.info("===user=== user name:{}, department:{}, roles : {}",user.getName(),user.getDeparment(),user.getRoles())
);
}
三、总结
JPA 方式 操作数据库非常方便,但其实还有许多细节问题需要注意,比如说就我现在看到的而言,创建的表就不是我需要的,并且,我记得有懒加载数据等功能,还有外键的设定等,这些都是细细研究的。
JdbcTemplate
需要编写 SQL 语句操作数据库,但更加灵活;所以将两者结合使用,我想威力一定无穷(需要写库的实现类)。
代码注释较少,但其语义已经很明显了,所以多余的注释,我就未加了;
对于不理解的代码,多看看文档,文档不理解了,再去百度,我也是这样解决问题的。