每个Repository都需要实现JpaRepository
@Repository
public interface UUserRepository extends JpaRepository {
@Override
UUser save(UUser user);
@Override
List findAll();
UUser findByUserName(String userName);
Optional findById(Integer id);
void deleteById(Integer id);
//删除表中所有数据,谨慎使用
void deleteAll();
}
@Repository
public interface UUserRepository extends JpaRepository {
/本地查询 nativeQuery=true 表示使用原生sql,表名、字段名跟数据库一致
@Query(value="select * from u_user where nickname like %?1 and status =?2" ,nativeQuery=true)
List findByUserNameAAndStatus(String name, Integer status);
//@Query执行delete和update语句一样,需要添加@Modifying注解,使用时在Repository或者更上层需要@Transactional注解。
/**
* 支持更新类的Query语句
* 使用 @Modifying 修改标识
* 返回值应该是int,表示更新语句所影响的行数
* @param id
* @param newName
* @return
*/
@Modifying
@Transactional(rollbackFor = Exception.class)
@Query(value="update UUser u set u.email=:newEmail where u.id =:nn")
int updateUserEmail(@Param("nn") Integer id, @Param("newEmail") String newName);
}
分页还需实现JpaSpecificationExecutor接口,只需在serviceImpl中传入所需参数即可
service层具体实现代码如下:一个是无查询条件分页返回,一个是有限制条件的分页返回。其中*jpa的页面数量是从0开始的*,这里需要注意一下,或者写个工具类统一处理
@Service
public class UUserServiceImpl implements UUserService{
@Autowired
UUserRepository userRepository;
@Override
public Page findUserNoCriteria(Integer page, Integer size) {
//springboot 2.0之前的写法设置排序字段为ID 降序
// Pageable pageable = new PageRequest(page, size, Sort.Direction.DESC, "id");
//springboot 2.0之后的推荐写法
Sort sort = new Sort(Sort.Direction.ASC, "id");
Pageable pageable = PageRequest.of(page-1, size, sort);
return userRepository.findAll(pageable);
}
@Override
public Page findUserCriteria(Integer page, Integer size, UUser userQuery) {
// Specification specification1 = (Specification) (root, query, criteriaBuilder) -> {
// List list = new ArrayList<>();
// // 第一个userId为CloudServerDao中的字段,第二个userId为参数
// Predicate p1 = criteriaBuilder.equal(root.get("userId"),userId);
// list.add(p1);
// if (!key.equals(null)) {
// // 此处为查询serverName中含有key的数据
// Predicate p2 = criteriaBuilder.like(root.get("serverName"),"%"+key+"%" );
// list.add(p2);
// }
// return criteriaBuilder.and(list.toArray(new Predicate[0]));
// };
Specification specification = new Specification() {
@Override
public Predicate toPredicate(Root root, CriteriaQuery criteriaQuery, CriteriaBuilder criteriaBuilder) {
List predicates = new ArrayList();
if(!StringUtils.isEmpty(userQuery.getUserName())) {
predicates.add(criteriaBuilder.like(root.get("nickName"), "%" + userQuery.getUserName() + "%"));
}
if(null != userQuery.getStatus()){
predicates.add(criteriaBuilder.equal(root.get("status"), userQuery.getStatus()));
}
if(null != userQuery.getId()){
predicates.add(criteriaBuilder.greaterThan(root.get("id"), userQuery.getId()));
}
return criteriaBuilder.and(predicates.toArray(new Predicate[predicates.size()]));
}
};
//设置排序字段为ID 升序 页码从0开始
Pageable pageable = PageRequest.of(page-1, size, Sort.Direction.ASC, "id");
return userRepository.findAll(specification,pageable);
}
也可在repository中自己实现批量删除
//批量删除
void deleteInBatch(Iterable userList);
//sql实现批量删除
@Modifying
@Transactional
@Query(value="delete from UUser u where u.id in (:ids) ")
int deleteByIds(@Param("ids")List ids);
@Service
public class UUserServiceImpl implements UUserService{
@Autowired
UUserRepository userRepository;
@Override
public List saveAllUser(List userList) {
return userRepository.saveAll(userList);
}
@Override
public int deleteByIds(List ids) {
return userRepository.deleteByIds(ids);
}
@Override
public void deleteInBatch(List userList) {
userRepository.deleteInBatch(userList);
}
}
使用jdbcTemplet 来实现,JdbcTemplate,执行批处理操作,如batchUpdate方法
也可通过@PersistenceContext注解 注入EntityManager对象 然后自己写QL语句,用EntityManager对象来做持久化操作就好了
@PersistenceContext
private EntityManager em;
https://blog.csdn.net/wangshfa/article/details/27323297
整合如下
service层
/**
* 通过EntityManager来实现批量插入
* @param userList
*/
void batchInsert(List userList);
/**
* 通过EntityManager来实现批量更新
* @param userList
*/
void batchUpdate(List userList);
serviceImpl层
@Transactional
@Override
public void batchInsert(List userList) {
for (int i = 0; i < userList.size(); i++) {
em.persist(userList.get(i));
if (i % 30 == 0) {
em.flush();
em.clear();
}
}
// jdbcTemplate批量插入操作
// String sql = "insert u_user(nickname,email,status) values(?,?)";
// jdbcTemplate.batchUpdate(sql, new BatchPreparedStatementSetter() {
// public void setValues(PreparedStatement ps, int i) throws SQLException {
// String name = userList.get(i).getUserName();
// String email = userList.get(i).getEmail();
// int status = userList.get(i).getStatus();
// ps.setString(1, name);
// ps.setString(2, email);
// ps.setInt(3, status);
// }
//
// public int getBatchSize() {
// return userList.size();
// }
// });
}
@Transactional
@Override
public void batchUpdate(List userList) {
for (int i = 0; i < userList.size(); i++) {
em.merge(userList.get(i));
if(i % 30 == 0){
em.flush();
em.clear();
}
}
// jdbcTemplate批量更新操作
// String sql = "update u_user set status=? where nickname=?";
// jdbcTemplate.batchUpdate(sql, new BatchPreparedStatementSetter() {
// public void setValues(PreparedStatement ps, int i) throws SQLException {
// int status = userList.get(i).getStatus();
// String name = userList.get(i).getUserName();
// ps.setInt(1, status);
// ps.setString(2, name);
// }
// public int getBatchSize() {
// return userList.size();
// }
// });
}
待完善
service层
package com.fei.springboot.demo.service;
import com.fei.springboot.demo.entity.UUser;
import org.springframework.data.domain.Page;
import java.util.List;
import java.util.Optional;
/**
* jpa的增删改查 分页等
* https://www.jianshu.com/p/14cd90f32d4d
* @author hpf
* @create 2019-05-18 16:15
*/
public interface UUserService {
/**
* 没有查询条件的分页
* @param page
* @param size
* @return Page
*/
Page findUserNoCriteria(Integer page, Integer size);
/**
* 带查询条件的分页
* @param page
* @param size
* @param userQuery
* @return Page
*/
Page findUserCriteria(Integer page, Integer size, UUser userQuery);
/**
* 根据主键id查询
* @param id
* @return Optional
*/
Optional findByID(Integer id);
/**
* 保存用户到数据库
* @param user
* @return user
*/
UUser saveUser(UUser user);
/**
* 批量保存用户
* @param userList
* @return List
*/
List saveAllUser(List userList);
/**
* 根据id来更新邮箱信息
* @param id
* @param newEmail
* @return 更新的数量
*/
int updateUserEmail(Integer id, String newEmail);
/**
* 根据主键id来删除数据
* @param id
*/
void deleteUserById(Integer id);
/**
* 根据主键id集合来批量删除
* @param ids
* @return
*/
int deleteByIds(List ids);
/**
* 根据对象集合来批量删除
* @param userList
*/
void deleteInBatch(List userList);
/**
* 通过EntityManager来实现批量插入
* @param userList
*/
void batchInsert(List userList);
/**
* 通过EntityManager来实现批量更新
* @param userList
*/
void batchUpdate(List userList);
}
serviceImpl实现层
package com.fei.springboot.demo.service.impl;
import com.fei.springboot.demo.entity.UUser;
import com.fei.springboot.demo.repository.jpa.UUserRepository;
import com.fei.springboot.demo.service.UUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
/**
* @author hpf
* 数据库连接中设置,批量速度会快点rewriteBatchedStatements=true
* @date 2019-05-18 16:16
*/
@Service
public class UUserServiceImpl implements UUserService{
@Autowired
UUserRepository userRepository;
@PersistenceContext
private EntityManager em;
@Autowired
private JdbcTemplate jdbcTemplate;
@Override
public Page findUserNoCriteria(Integer page, Integer size) {
//springboot 2.0之前的写法设置排序字段为ID 降序
// Pageable pageable = new PageRequest(page, size, Sort.Direction.DESC, "id");
//springboot 2.0之后的推荐写法
Sort sort = new Sort(Sort.Direction.ASC, "id");
Pageable pageable = PageRequest.of(page-1, size, sort);
return userRepository.findAll(pageable);
}
@Override
public Page findUserCriteria(Integer page, Integer size, UUser userQuery) {
// Specification specification1 = (Specification) (root, query, criteriaBuilder) -> {
// List list = new ArrayList<>();
// // 第一个userId为CloudServerDao中的字段,第二个userId为参数
// Predicate p1 = criteriaBuilder.equal(root.get("userId"),userId);
// list.add(p1);
// if (!key.equals(null)) {
// // 此处为查询serverName中含有key的数据
// Predicate p2 = criteriaBuilder.like(root.get("serverName"),"%"+key+"%" );
// list.add(p2);
// }
// return criteriaBuilder.and(list.toArray(new Predicate[0]));
// };
Specification specification = new Specification() {
@Override
public Predicate toPredicate(Root root, CriteriaQuery criteriaQuery, CriteriaBuilder criteriaBuilder) {
List predicates = new ArrayList();
if(!StringUtils.isEmpty(userQuery.getUserName())) {
predicates.add(criteriaBuilder.like(root.get("nickName"), "%" + userQuery.getUserName() + "%"));
}
if(null != userQuery.getStatus()){
predicates.add(criteriaBuilder.equal(root.get("status"), userQuery.getStatus()));
}
if(null != userQuery.getId()){
predicates.add(criteriaBuilder.greaterThan(root.get("id"), userQuery.getId()));
}
return criteriaBuilder.and(predicates.toArray(new Predicate[predicates.size()]));
}
};
//设置排序字段为ID 升序 页码从0开始
Pageable pageable = PageRequest.of(page-1, size, Sort.Direction.ASC, "id");
return userRepository.findAll(specification,pageable);
}
@Override
public Optional findByID(Integer id) {
return userRepository.findById(id);
}
@Override
public UUser saveUser(UUser user) {
return userRepository.save(user);
}
@Override
public List saveAllUser(List userList) {
return userRepository.saveAll(userList);
}
@Override
public int updateUserEmail(Integer id, String newEmail) {
return userRepository.updateUserEmail(id,newEmail);
}
@Override
public void deleteUserById(Integer id) {
userRepository.deleteById(id);
}
@Override
public int deleteByIds(List ids) {
return userRepository.deleteByIds(ids);
}
@Override
public void deleteInBatch(List userList) {
userRepository.deleteInBatch(userList);
}
@Transactional
@Override
public void batchInsert(List userList) {
for (int i = 0; i < userList.size(); i++) {
em.persist(userList.get(i));
if (i % 30 == 0) {
em.flush();
em.clear();
}
}
// jdbcTemplate批量插入操作
// String sql = "insert u_user(nickname,email,status) values(?,?)";
// jdbcTemplate.batchUpdate(sql, new BatchPreparedStatementSetter() {
// public void setValues(PreparedStatement ps, int i) throws SQLException {
// String name = userList.get(i).getUserName();
// String email = userList.get(i).getEmail();
// int status = userList.get(i).getStatus();
// ps.setString(1, name);
// ps.setString(2, email);
// ps.setInt(3, status);
// }
//
// public int getBatchSize() {
// return userList.size();
// }
// });
}
@Transactional
@Override
public void batchUpdate(List userList) {
for (int i = 0; i < userList.size(); i++) {
em.merge(userList.get(i));
if(i % 30 == 0){
em.flush();
em.clear();
}
}
// jdbcTemplate批量更新操作
// String sql = "update u_user set status=? where nickname=?";
// jdbcTemplate.batchUpdate(sql, new BatchPreparedStatementSetter() {
// public void setValues(PreparedStatement ps, int i) throws SQLException {
// int status = userList.get(i).getStatus();
// String name = userList.get(i).getUserName();
// ps.setInt(1, status);
// ps.setString(2, name);
// }
// public int getBatchSize() {
// return userList.size();
// }
// });
}
}
repository
package com.fei.springboot.demo.repository.jpa;
import com.fei.springboot.demo.entity.UUser;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
import java.util.Optional;
/**
* 分页还需实现JpaSpecificationExecutor接口
* @author hpf
* @create 2019-05-10 21:32
*/
@Repository
public interface UUserRepository extends JpaRepository,JpaSpecificationExecutor {
@Override
UUser save(UUser user);
@Override
List findAll();
UUser findByUserName(String userName);
Optional findById(Integer id);
//本地查询 nativeQuery=true 表示使用原生sql,表名、字段名跟数据库一致
@Query(value="select * from u_user where nickname like %?1 and status =?2" ,nativeQuery=true)
List findByUserNameAAndStatus(String name, Integer status);
//@Query执行delete和update语句一样,需要添加@Modifying注解,使用时在Repository或者更上层需要@Transactional注解。
/**
* 支持更新类的Query语句
* 使用 @Modifying 修改标识
* 返回值应该是int,表示更新语句所影响的行数
* @param id
* @param newName
* @return
*/
@Modifying
@Transactional(rollbackFor = Exception.class)
@Query(value="update UUser u set u.email=:newEmail where u.id =:nn")
int updateUserEmail(@Param("nn") Integer id, @Param("newEmail") String newName);
void deleteById(Integer id);
//删除表中所有数据,谨慎使用
void deleteAll();
void deleteInBatch(Iterable userList);
@Modifying
@Transactional
@Query(value="delete from UUser u where u.id in (:ids) ")
int deleteByIds(@Param("ids")List ids);
}
entity类
package com.fei.springboot.demo.entity;
import com.alibaba.fastjson.annotation.JSONField;
import javax.persistence.*;
import java.io.Serializable;
import java.util.Date;
import java.util.List;
/**
* 权限测试中用户类
* JPA提供的四种标准用法为TABLE,SEQUENCE,IDENTITY,AUTO.
* TABLE:使用一个特定的数据库表格来保存主键。
* SEQUENCE:根据底层数据库的序列来生成主键,条件是数据库支持序列。 mysql不支持此种方式
* IDENTITY:主键由数据库自动生成(主要是自动增长型) oracle不支持此种方式
* AUTO:主键由程序控制。会在数据库中生成一张hibernate_sequence表
* 在指定主键时,如果不指定主键生成策略,默认为AUTO。
*
* @author hpf
* @date 2019-05-10 21:14
*/
@Table(name = "u_user")
@Entity
//@JSONType(ignores ={"id", "createTime"})
public class UUser implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id")
private Integer id;
@JSONField(ordinal = 1)
@Column(name = "nickname")
private String userName;
@Column(name = "email")
private String email;
//不会序列化到json
@JSONField(name = "passWORD",serialize=false)
@Column(name = "pswd")
private String password;
@Column(name = "create_time")
private Date createTime;
@Column(name = "last_login_time")
private Date lastLoginTime;
@Column(name = "status")
private Integer status;
//表示此字段不被序列化。不会被映射到数据库,也不会序列化到json
@Transient
// @ElementCollection(targetClass=String.class)
private List roleList;
//数据库中没有此字段
// @ElementCollection(targetClass=String.class) 会在数据中多生成一张表
@Transient
private List permissionList;
//get set 方法
}
test类
package com.fei.springboot.demo;
import com.fei.springboot.demo.entity.UUser;
import com.fei.springboot.demo.service.UUserService;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.domain.Page;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
/**
* @author hpf
* @date 2019-05-18 16:55
*/
@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest
public class UUserServiceTest {
private static final Logger logger = LoggerFactory.getLogger(UUserServiceTest.class);
@Autowired
UUserService userService;
private static UUser user;
@BeforeClass
public static void create(){
user = new UUser();
// user.setId(1);
user.setStatus(1);
user.setUserName("inserttest");
user.setEmail("111sdad@@");
}
@Test
public void testCriteria() {
Page userNoCriteria = userService.findUserNoCriteria(1, 3);
logger.info("List user is :{}",userNoCriteria.getContent());
logger.info("total element:{},total page:{},current page number:{},current size:{}",
userNoCriteria.getTotalElements(),userNoCriteria.getTotalPages(),userNoCriteria.getPageable().getPageNumber(),userNoCriteria.getSize());
Page userCriteria = userService.findUserCriteria(1, 2, user);
logger.info("List user is :{}",userCriteria.getContent());
}
// @Transactional
@Test
public void testCurd() {
Optional userOptional = userService.findByID(3);
logger.info("findByID, userOptional is :{}",userOptional.get());
//通过一个数据库不存在的id去获取数据
Optional userOptional1 = userService.findByID(4);
// Optional.ofNullable(userOptional1)
// .map(user->user.get())
// .orElse(null);
// logger.info("findByID, userOptional is :{}",userOptional1.get());
int i = userService.updateUserEmail(2, "fei@飞.com");
logger.info("影响行数:{}",i);
//未更新数据库 则返回值为0
i = userService.updateUserEmail(4, "fei@飞.com");
logger.info("影响行数:{}",i);
UUser saveUser = userService.saveUser(user);
logger.info("saveUser is :{}",saveUser);
userService.deleteUserById(saveUser.getId());
}
@Test
public void testBatch() {
List saveUserList = new ArrayList<>();
UUser uUser = new UUser();
uUser.setUserName("test1");
uUser.setEmail("delete1");
UUser uUser2 = new UUser();
uUser2.setUserName("test2");
uUser2.setEmail("delete2");
saveUserList.add(uUser);
saveUserList.add(uUser2);
// UUser saveUser = userService.saveUser(uUser);
// UUser saveUser2 = userService.saveUser(uUser2);
List saveAllUser = userService.saveAllUser(saveUserList);
List deleteUserList = new ArrayList<>();
List userIdS = new ArrayList<>();
for (UUser uUser1 : saveAllUser) {
deleteUserList.add(uUser1);
userIdS.add(uUser1.getId());
}
//批量删除方法1
logger.info("this is delete for:{}",deleteUserList);
// userService.deleteInBatch(userList);
//批量删除方法2
logger.info("this is delete number:{}",userService.deleteByIds(userIdS));
}
}
参考链接:jpa分页
批量保存效率对比
主键策略
主键策略