SpringBoot系列:Spring Boot集成Spring Data JPA

一、什么是JPA

JPA全称Java Persistence API,可以通过注解或者XML描述【对象-关系表】之间的映射关系,并将实体对象持久化到数据库中。

他为我们提供了ORM映射元数据:JPA支持XML和注解两种元数据的形式,元数据描述对象和表之间的映射关系,框架据此将实体对象持久化到数据库表中。同时,JPA 的API,用来操作实体对象,执行CRUD操作,框架在后台替我们完成所有的事情,开发者从繁琐的JDBC和SQL代码中解脱出来

JPA仅仅是一种规范,也就是说JPA仅仅定义了一些接口,而接口是需要实现才能工作的。所以底层需要某种实现,对于我们熟知的Hibernate就是实现了JPA接口的ORM框架。

而在Spring Boot 中,为了更加简化JPA,推出了Spring Data JPA,Spring Data JPA 可以理解为简化了的Hibernate, 他是对JPA 规范的再次封装抽象,底层还是使用了 Hibernate 的 JPA 技术实现。

按照Spring Data JPA按照约定好的【方法命名规则】写dao层接口,就可以在不写接口实现的情况下,实现对数据库的访问和操作。同时提供了很多除了CRUD之外的功能,如分页、排序、复杂查询等等。

二、示例演示

使用Spring Data JPA,首先我们依然要引入其相应依赖,主要是spring-boot-starter-data-jpa。

 <!--mysql连接-->
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <scope>runtime</scope>
</dependency>

<!--druid连接池-->
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>druid</artifactId>
    <version>1.0.29</version>
</dependency>

<!--jpa依赖-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>

在核心配置文件中,我们需要指明JPA的数据库方言类型,这里我们使用mysql。
在这里插入图片描述
然后我们就可以使用Spring Data JPA。

还是我们的User类,其中@Table(name = “user”)注解用来关联数据库的表名,相同时候可以省略,而@Column注解字段用来表示字段与数据库列名的映射关系,相同时可以省略。@Entity注解为JPA提供,用来声明这是一个实体映射类,@Id指明主键,@GeneratedValue注解表示主键生成策略,这里使用了数据库的主键策略,也即建表时设置的自增长。@Data为lombok注解,这里不再累述。

// 表名关联的表
@Table(name = "user")
@Entity
@Data
public class User {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY) // 使用数据库的主键自增策略
    @Column(name = "id")
    private Integer id;

    private String username;

    private String password;

}

其次是UserApi类,这个是一个简单的Controller,没什么好说的。

@RestController
@RequestMapping("user")
public class UserApi {

    @Autowired
    private UserService userService;

    /**
     * 添加用户
     * @param user
     */
    @PostMapping("addUser")
    public String addUser(User user){
        userService.addUser(user);
        return "添加用户成功";
    }

    /**
     * 删除用户
     * @param id
     */
    @GetMapping("delUser")
    public String delUser(@RequestParam(value = "id") int id){
        userService.delUser(id);
        return "删除用户成功";
    }

    /**
     * 修改用户信息
     * @param user
     */
    @PostMapping("updateUser")
    public String updateUser(User user){
        userService.updateUser(user);
        return "修改用户成功";
    }

    /**
     * 获取用户信息
     * @param id
     * @return
     */
    @GetMapping("getUser")
    public User getUser(@RequestParam(value = "id") int id){
        return userService.getUser(id);
    }

    // 查询全部
    @GetMapping("getUsers")
    public List<User> getUsers(){
        List<User> users = userService.findAll();
        return users;
    }

    // 根据用户名和密码查找用户
    @GetMapping("getUserByUP")
    public User getUserByUP(@RequestParam(value = "username") String username, @RequestParam(value = "password") String password){
        return userService.getUser(username, password);
    }

}

由于业务的简单,service层无任何操作,即直接调用了dao。

@Service
public class UserService {

    @Autowired
    private IUserDao userDao;

    /**
     * 添加用户
     * @param user
     */
    public void addUser(User user){
        userDao.save(user);
    }

    /**
     * 删除用户
     * @param id
     */
    public void delUser(int id){
        userDao.deleteById(id);
    }

    /**
     * 修改用户信息
     * @param user
     */
    public void updateUser(User user){
        Optional<User> opt = userDao.findById(user.getId());
        opt.get().setPassword(user.getPassword());
        opt.get().setUsername(user.getUsername());
        userDao.save(opt.get());
    }

    /**
     * 获取用户信息
     * @param id
     * @return
     */
    public User getUser(int id){
        return userDao.findById(id).get();
    }

    /**
     * 获取全部用户信息
     * @return
     */
    public List<User> findAll() {
        return userDao.findAll();
    }

    /**
     * 获取用户
     * @param username
     * @param password
     * @return
     */
    public User getUser(String username, String password) {
        User user1 = userDao.findByUsernameAndPassword(username, password);
        User user2 = userDao.find(username, password);
        return user1;
    }

}

然后是我们的dao层IUserDao。

public interface IUserDao extends JpaRepository<User, Integer>  {

    /**
     * 根据用户名和密码查询,根据方法名来生成实体类
     * @param username
     * @param password
     * @return
     */
    User findByUsernameAndPassword(String username, String password);

    /**
     * 根据用户名和密码查询
     * @param username
     * @param password
     * @return
     */
    @Query(nativeQuery = true, value = "select * from user where username = :username and password = :password")
    User find(@Param("username") String username, @Param("password") String password);

}

Spring Data JPA特殊的地方就在于dao层,熟悉hibernate的都知道,hibernate为我们提供了基于对象的CRUD,而JPA的呢,更是将这些常用的API封装成了JpaRepository,并为我们提供了实现。所以仅当我们的dao接口集成JpaRepository时,我们就获得了对应的方法。
在这里插入图片描述
这些默认的API,已经能满足大多数操作了,但如果我们仍需要扩展呢?我们可以根据JPA约定方法名、自己提供sql或者JPQL两种方式。

例如IUserDao中的根据用户名和密码查询指定用户,我们仅仅增加findByUsernameAndPassword接口即可,JPA就可以帮我们实现即查询,这是因为我们遵守JPA的方法命名规则。

User findByUsernameAndPassword(String username, String password);

JPA的方法命名规则如下:

[外链图片转存失败(img-Ds9yzazT-1563625046370)(en-resource://database/7987:0)]

除了命名法,JPA也允许我们自己来提供实现,因为有时根据命名会使得方法名格外长。自己实现的话, 可以写原生sql,或者使用JPQL,JPQL类似于HQL。

@Query(nativeQuery = true, value = "select * from user where username = :username and password = :password")
    User find(@Param("username") String username, @Param("password") String password);

这里提供了find方法,同样根据用户名和密码查询指定用户,其中nativeQuery = true表明使用了原生的sql,这对于习惯写sql的人来说是一种福音,false和不指明则使用JPQL。

源码地址:https://github.com/imyanger/springboot-project/tree/master/p6-springboot-jpa

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值