Spring Data JPA中CrudRepository常用方法及其底层源码解读

Spring Data JPA中CrudRepository常用方法及其底层源码解读
使用Spring Data JPA,Dao层对象实际上是SimpleJpaRepository的代理对象,我们可以去这个类里看各个方法是如何实现的。
1.save(S entity)

@Transactional
    public <S extends T> S save(S entity) {
        if(this.entityInformation.isNew(entity)) {
            this.em.persist(entity);
            return entity;
        } else {
            return this.em.merge(entity);
        }
    }

save()方法包含插入和更新两个功能,根据传入实体entity的主键ID是否为空,来判断执行哪个操作,这个在之前的博客中有说明。
在这里需要关注下该方法上的事务注解@Transactional。我们在调用完save()方法后,从日志里可以看出有commit,这说明save方法会自动完成事务提交,而不依赖于所在方法的事务,其原因就是save方法本身就是一个事务。
2.save(Iterable entities)
Iterable其实就是我们常用的集合List,List继承了Iterable,如下所示

public interface List<E> extends Collection<E> {}
public interface Collection<E> extends Iterable<E> {
@Transactional
    public <S extends T> List<S> save(Iterable<S> entities) {
        List<S> result = new ArrayList();
        if(entities == null) {
            return result;
        } else {
            Iterator var3 = entities.iterator();
            while(var3.hasNext()) {
                S entity = var3.next();
                result.add(this.save(entity));
            }
            return result;
        }
    }

使用save方法保存集合,save方法会先判断该集合是否为空,不为空,就迭代获取每一个实体,再对实体进行保存或者更新操作,同样该方法是自带事务的。

save(S entity)和save(Iterable entities)方法都有返回值,返回的都是被操作的实体对象或者实体对象的集合。
3.findOne(ID id)

 public T findOne(ID id) {
        Assert.notNull(id, "The given id must not be null!");
        Class<T> domainType = this.getDomainClass();
        if(this.metadata == null) {
            return this.em.find(domainType, id);
        } else {
            LockModeType type = this.metadata.getLockModeType();
            Map<String, Object> hints = this.metadata.getQueryHints();
            return type == null?this.em.find(domainType, id, hints):this.em.find(domainType, id, type, hints);
        }
    }
public static void notNull(Object object, String message) {
        if(object == null) {
            throw new IllegalArgumentException(message);
        }
    }

findOne根据主键ID查询,首先会判断ID是否为空,为空,则会抛出IllegalArgumentException非法参数异常,接着获取当前实体类对象,通过反射去查询数据。
4.delete(ID id)

@Transactional
    public void delete(ID id) {
        Assert.notNull(id, "The given id must not be null!");
        T entity = this.findOne(id);
        if(entity == null) {
            throw new EmptyResultDataAccessException(String.format("No %s entity with id %s exists!", new Object[]{this.entityInformation.getJavaType(), id}), 1);
        } else {
            this.delete(entity);
        }
    }

按主键ID进行删除,首先判断ID是否为空,接着调用findOne去根据ID查询实体,若返回null,则抛出对应实体不存在的异常,若实体存在,则进行删除。该方法被@Transactional修饰,会自动完成事务提交。
5.delete(Iterable<? extends T> entities)

 @Transactional
    public void delete(Iterable<? extends T> entities) {
        Assert.notNull(entities, "The given Iterable of entities not be null!");
        Iterator var2 = entities.iterator();
        while(var2.hasNext()) {
            T entity = var2.next();
            this.delete(entity);
        }
    }

删除多个实体,首先判断集合是否为空,不为空则遍历集合进行删除,同样会自动完成事务提交。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
很抱歉,由于篇幅限制,我无法在这里提供整个项目的完整源代码。但我可以为您提供一些示例代码来演示如何实现根据不同的登录方式使用不同的数据库操作方式。 首先,您可以创建一个包含用户信息的数据库表,并在应用程序创建对应的Java实体类。例如,以下代码显示了一个名为User的实体类: ```java @Entity @Table(name = "users") public class User { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; private String username; private String email; private String phone; private String password; // getters and setters } ``` 接下来,您可以为每种数据库操作方式创建相应的DAO接口。例如,以下代码显示了一个名为UserJdbcDao的JDBC DAO接口: ```java public interface UserJdbcDao { User findByUsernameAndPassword(String username, String password); } ``` 然后,您可以实现这些DAO接口。例如,以下代码显示了一个名为UserJdbcDaoImpl的JDBC DAO实现类: ```java @Repository public class UserJdbcDaoImpl implements UserJdbcDao { private final JdbcTemplate jdbcTemplate; @Autowired public UserJdbcDaoImpl(JdbcTemplate jdbcTemplate) { this.jdbcTemplate = jdbcTemplate; } @Override public User findByUsernameAndPassword(String username, String password) { String sql = "SELECT * FROM users WHERE username = ? AND password = ?"; return jdbcTemplate.queryForObject(sql, new Object[]{username, password}, new UserRowMapper()); } private static class UserRowMapper implements RowMapper<User> { @Override public User mapRow(ResultSet rs, int rowNum) throws SQLException { User user = new User(); user.setId(rs.getLong("id")); user.setUsername(rs.getString("username")); user.setEmail(rs.getString("email")); user.setPhone(rs.getString("phone")); user.setPassword(rs.getString("password")); return user; } } } ``` 类似地,您可以创建相应的MyBatis DAO接口和Spring Data JPA DAO接口,并实现它们。 最后,您可以创建一个处理登录请求的控制器,并在其根据用户输入的登录信息选择使用哪种DAO。例如,以下代码显示了一个名为LoginController的登录控制器: ```java @RestController @RequestMapping("/login") public class LoginController { private final UserJdbcDao userJdbcDao; private final UserMyBatisDao userMyBatisDao; private final UserRepository userRepository; @Autowired public LoginController(UserJdbcDao userJdbcDao, UserMyBatisDao userMyBatisDao, UserRepository userRepository) { this.userJdbcDao = userJdbcDao; this.userMyBatisDao = userMyBatisDao; this.userRepository = userRepository; } @PostMapping public ResponseEntity<?> login(@RequestBody LoginRequest loginRequest) { User user; if (isEmail(loginRequest.getUsername())) { user = userMyBatisDao.findByEmailAndPassword(loginRequest.getUsername(), loginRequest.getPassword()); } else if (isPhone(loginRequest.getUsername())) { user = userRepository.findByPhoneAndPassword(loginRequest.getUsername(), loginRequest.getPassword()); } else { user = userJdbcDao.findByUsernameAndPassword(loginRequest.getUsername(), loginRequest.getPassword()); } if (user == null) { return ResponseEntity.status(HttpStatus.UNAUTHORIZED).build(); } else { return ResponseEntity.ok(user); } } private boolean isEmail(String str) { // check if str is a valid email } private boolean isPhone(String str) { // check if str is a valid phone number } } ``` 在上面的代码,LoginController使用了@Autowired注解注入了UserJdbcDao、UserMyBatisDao和UserRepository。然后,它使用isEmail()和isPhone()方法来判断用户输入的登录信息是用户名、邮箱还是手机号,并根据不同的情况选择使用不同的DAO。 当然,这只是一个简单的示例,您需要根据您的具体需求进行修改和完善。但是,希望这可以为您提供一些帮助。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值