商务网站建设的应用,外链查询,淄博网站制作定制技术,科技动态前言
JPA#xff08;Java Persistence API#xff09;和MyBatis Plus是两种不同的持久化框架#xff0c;它们具有不同的特点和适用场景。
JPA是Java官方的持久化规范#xff0c;它提供了一种基于对象的编程模型#xff0c;可以通过注解或XML配置来实现对象与数据库的映射…前言
JPAJava Persistence API和MyBatis Plus是两种不同的持久化框架它们具有不同的特点和适用场景。
JPA是Java官方的持久化规范它提供了一种基于对象的编程模型可以通过注解或XML配置来实现对象与数据库的映射关系。JPA的优点是可以对数据库进行更高级的操作如查询、更新、删除等同时也支持事务管理和缓存机制能够更好地支持复杂的业务逻辑。
MyBatis Plus (MPP) 是在MyBatis基础上进行封装的增强版本它提供了更简单易用的API和更高效的性能。MyBatis Plus通过XML或注解的方式来配置数据库映射关系并提供了丰富的查询、更新、删除操作的方法。相对于JPAMyBatis Plus配置简单、易于上手同时也灵活性较高能够更好地满足项目的特定需求。
如果只是针对单表的增删改查两者十分相似本质上都算ORM框架那么到底什么时候适合用JPA什么时候用MyBatisPlus下面做下这两者的详细对比。
POM依赖
JPA
dependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-data-jpa/artifactId
/dependencyMPP
dependencygroupIdcom.baomidou/groupIdartifactIdmybatis-plus-boot-starter/artifactId
/dependencyEntity定义
JPA
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
import javax.persistence.GeneratedValue;Entity
Table(name dept)
public class Dept {IdColumn(name id)GeneratedValue(strategy GenerationType.AUTO)private Long id;Column(name code)private String code;Column(name name)private String name;
}MPP
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;TableName(value dept)
public class Dept {TableId(value id, type IdType.AUTO)private Long id;TableField(value code)private String code;TableField(value name)private String name;
}DAO定义
基础CRUD
JPA
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;Repository
public interface DeptRepository extends JpaRepositoryDept, Long {
}MPP
import org.apache.ibatis.annotations.Mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;Mapper
public interface DeptMapper extends BaseMapperDept {
}基类主要方法
方法JpaRepositoryBaseMapper插入一条记录save(T entity)insert(T entity)插入多条记录saveAll(Iterable entities)insertBatchSomeColumn(List entityList)根据 ID 删除deleteById(ID id)deleteById(Serializable id)根据实体(ID)删除delete(T entity)deleteById(T entity)根据条件删除记录-delete(Wrapper queryWrapper)删除根据ID或实体 批量删除deleteAllById(Iterable? extends ID ids)deleteBatchIds(Collection? idList)根据 ID 修改save(T entity)updateById(T entity)根据条件更新记录-update(Wrapper updateWrapper)根据 ID 查询findById(ID id)selectById(Serializable id)查询根据ID 批量查询findAllById(Iterable ids)selectBatchIds(Collection? extends Serializable idList)根据条件查询一条记录-selectOne(Wrapper queryWrapper)根据条件判断是否存在记录exists(Example example)exists(Wrapper queryWrapper)根据条件查询总记录数count(Example example)selectCount(Wrapper queryWrapper)根据条件查询全部记录findAll(Example example, Sort sort)selectList(Wrapper queryWrapper)根据条件查询分页记录findAll(Example example, Pageable pageable)selectPage(P page, Wrapper queryWrapper)
Example、Specification VS Wrapper
JPA使用Example和Specification 类来实现范本数据的查询而MPP使用QueryWrapper来设置查询条件
JPA Example
Dept dept new Dept();
dept.setCode(100);
dept.setName(Dept1);// select * from dept where code 100 and name Dept1;
ListDept deptList deptRepository.findAll(Example.of(dept)); 默认是生成的条件都是 “”如果要设置其他比较符需要使用ExampleMatcher
Dept dept new Dept();
dept.setCode(100);
dept.setName(Dept1);// select * from dept where code like 100% and name like %Dept1%;
ListDept deptList deptRepository.findAll(Example.of(dept, ExampleMatcher.matching().withMatcher(code, ExampleMatcher.GenericPropertyMatchers.startsWith()).withMatcher(name, ExampleMatcher.GenericPropertyMatchers.contains()))); Example仅能实现对字符串类型的匹配模式如果要设置其他类型的字段可以实现JpaSpecificationExecutor接口来完成
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.stereotype.Repository;Repository
public interface DeptRepository extends JpaRepositoryDept, Long, JpaSpecificationExecutorDept {
}增加以上接口后会增加以下查询方法
findOne(Specification spec)findAll(Specification spec)findAll(Specification spec, Pageable pageable)count(Specification spec)exists(Specification spec)
使用示例
Dept dept new Dept();
dept.setCode(100);
dept.setName(Dept1);// select * from dept where code like 100% and name like %Dept1%;
SpecificationDept spec new SpecificationDept() {Overridepublic Predicate toPredicate(RootDept root, CriteriaQuery? query, CriteriaBuilder cb) {ListPredicate predicates new ArrayList();// 模糊查询前缀匹配if (dept.getCode() ! null !dept.getCode().isEmpty()) {predicates.add(cb.like(root.get(code), dept.getCode() %));}// 模糊查询if (dept.getName() ! null !dept.getName().isEmpty()) {predicates.add(cb.like(root.get(code), % dept.getCode() %));}return query.where(predicates.toArray(new Predicate[predicates.size()])).getRestriction();}
};
ListDept deptList deptRepository.findAll(Example.of(dept)); 除了equal、notEqual, 针对日期、数字类型还有gt、ge、lt、le等常用比较符。
自定义接口
JPA
JPA支持接口规范方法名查询一般查询方法以 find、findBy、read、readBy、get、getBy为前缀JPA在进行方法解析的时候会把前缀取掉然后对剩下部分进行解析。例如
Repository
public interface DeptRepository extends JpaRepositoryDept, Long {// 调用此方法时会自动生成 where code ? 的条件Dept getByCode(String code);
}常用的方法命名有
关键字方法命名sql where字句DistinctfindDistinctByLastnameAndFirstnameselect distinct … where x.lastname ?1 and x.firstname ?2AndfindByNameAndPwdwhere name ? and pwd ?OrfindByNameOrSexwhere name ? or sex?Is,EqualsfindById, findByIdIs, findByIdEqualswhere id ?BetweenfindByIdBetweenwhere id between ? and ?LessThanfindByIdLessThanwhere id ?LessThanEqualsfindByIdLessThanEqualswhere id ?GreaterThanfindByIdGreaterThanwhere id ?GreaterThanEqualsfindByIdGreaterThanEqualswhere id ?AfterfindByIdAfterwhere id ?BeforefindByIdBeforewhere id ?IsNullfindByNameIsNullwhere name is nullisNotNull,NotNullfindByNameNotNullwhere name is not nullLikefindByNameLikewhere name like ?NotLikefindByNameNotLikewhere name not like ?StartingWithfindByNameStartingWithwhere name like ‘?%’EndingWithfindByNameEndingWithwhere name like ‘%?’ContainingfindByNameContainingwhere name like ‘%?%’OrderByfindByIdOrderByXDescwhere id? order by x descNotfindByNameNotwhere name ?InfindByIdIn(Collection? c)where id in (?)NotInfindByIdNotIn(Collection? c)where id not in (?)TruefindByEnabledTuewhere enabled trueFalsefindByEnabledFalsewhere enabled falseIgnoreCasefindByNameIgnoreCasewhere UPPER(name)UPPER(?)First,TopfindFirstByOrderByLastnameAscorder by lastname limit 1FirstN,TopNfindTop3ByOrderByLastnameAscorder by lastname limit 3
MPP
MyBatisPlus没有JPA那样可以根据接口的方法名自动组装查询条件但是可以利用Java8的接口默认实现来达到同样的目的只不过需要编写少量的代码
import org.apache.ibatis.annotations.Mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;Mapper
public interface DeptMapper extends BaseMapperDept {default Dept getByCode(String code) {return selectOne(Wrappers.DeptlambdaWrapper().eq(Dept::getCode, code));}
}自定义SQL
JPA支持通过Query注解和XML的形式实现自定义SQL而MyBatis支持通过Select、Delete、Update、Script注解和XML的形式实现自定义SQL。
JPA
JPA的自定义SQL分为JPQL(Java Persistence Query Language Java 持久化查询语言)和原生SQL两种。 JPQL:
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;Repository
public interface DeptRepository extends JpaRepositoryDept, Long {Query(value select d from Dept d where d.code ?1)Dept getByCode(String code);ModifyingQuery(value delete from Dept d where d.code :code)int deleteByCode(Param(code) String code);
}原生SQL
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;Repository
public interface DeptRepository extends JpaRepositoryDept, Long {Query(value SELECT * FROM dept WHERE name ?1, countQuery SELECT count(*) FROM dept WHERE name ?1, nativeQuery true)PageDept findByName(Param(name) String name, Pageable pageable);
}XML形式 /resource/META-INFO/orm.xml
named-query nameDept.getByCodequery select d from Dept d where d.code ?1/query
/named-query
named-native-query nameDept.deleteByCodequery DELETE FROM dept WHERE code ?1/query
/named-native-queryMyBatis
JPA的自定义SQL分为注解形式和XML形式 注解形式:
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.metadata.IPage;Mapper
public interface DeptMapper extends BaseMapperDept {Select(value SELECT * FROM dept WHERE code #{code})Dept getByCode(Param(code) String code);Delete(DELETE FROM dept WHERE code #{code})int deleteByCode(Param(code) String code);Select(value SELECT * FROM dept WHERE name #{name})IPageDept findByName(Param(name) String name, IPageDept page);
}XML形式 /resource/mapper/DeptMapper.xml
select id getByCode, resultType DeptSELECT * FROM dept WHERE code #{code}
/select
delete id deleteByCodeDELETE FROM dept WHERE code #{code}
/select
select id findByNameSELECT * FROM dept WHERE name #{name}
/select