1.项目中遇到了批量插入的操作,但是使用saveAll,数据量5000条而已,速度感人,用户体验贼差,哈哈,现在将解决方法记录一下。
2.创建springboot项目
3.引入pom依赖
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="/POM/4.0.0" xmlns:xsi="http:///2001/XMLSchema-instance"
xsi:schemaLocation="/POM/4.0.0 /xsd/maven-4.0.">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId></groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId></groupId>
<artifactId>jpa</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>spingboot-jpa</name>
<description>Demo project for Spring Boot</description>
<properties>
<>1.8</>
</properties>
<dependencies>
<dependency>
<groupId></groupId>
<artifactId>spring-boot-starter-data-jdbc</artifactId>
</dependency>
<dependency>
<groupId></groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId></groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.48</version>
</dependency>
<dependency>
<groupId></groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId></groupId>
<artifactId>fastjson</artifactId>
<version>1.2.47</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId></groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
spring:
datasource:
driver-class-name:
url: jdbc:mysql://127.0.0.1:3306/test?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8&useSSL=true
username: root
password: 123456
jpa:
properties:
hibernate:
hbm2ddl:
auto: update
dialect: .MySQL5InnoDBDialect
format_sql: true
# 开启批量插入
jdbc:
batch_size: 500
batch_versioned_data: true
order_inserts: true
order_updates: true
show-sql: true
5.实体类
package ;
import ;
import ;
import ;
import ;
import ;
import ;
import ;
import ;
import ;
/**
* @author 小石潭记
* @date 2020/10/4 14:14
* @Description: ${todo}
*/
@Entity
@Data
public class User implements Serializable {
@Id
@GeneratedValue
private Long id;
@Column(nullable = false, unique = true)
private String userName;
@Column(nullable = false)
private String passWord;
@Column(nullable = false, unique = true)
private String email;
@Column(nullable = true, unique = true)
private String nickName;
@Column(nullable = false)
private String regTime;
public User(String userName, String passWord, String email, String nickName, String regTime) {
= userName;
= passWord;
= email;
= nickName;
= regTime;
}
public User() {
}
}
package ;
import ;
import ;
import ;
import ;
import ;
import ;
import ;
import ;
/**
* @author 小石潭记
* @date 2020/10/4 14:15
* @Description: ${todo}
* 1. 使用jpa的 CrudRepository 基本查询
* 2. 使用jpa的 PagingAndSortingRepository 分页查询和排序
* 3. 使用jpa的 Repository 自定义声明式查询方法
*
public interface PersonQueryRepo extends Repository<Person, Long> {
// declare query method
// 声明式查询方法
// 1. count 计数
long countByName(String name);
// 2. get/find/stream/query/read 查询
Person readFirstByAge(int age);
// 3. delete/remove 删除
@Transactional
int deleteById(long id);
}
* 4. 使用jpa的 JpaRepository 使用hql、jpql或sql查询,@Query等注解
public interface PersonHqlDao extends JpaRepository<Person, Long> {
// 使用hql 或者 jpql 查询
@Query("from Person where name = ?1 order by id desc")
List<Person> listByName(String name);
// 前几种方法中均未介绍update操作,要完成update操作,可使用以下方法
// 更新时需要加上 @Transactional 和 @Modifying
@Transactional
@Modifying // QueryExecutionRequestException: Not supported for DML operations
@Query("update Person set name=?2 where id=?1")
int updateNameById(long id, String name);
}
*/
@Repository
public interface UserRepository extends PagingAndSortingRepository<User, Long> {
List<User> findByUserNameOrEmail(@Param("userName")String userName, @Param("email")String email);
User findByUserName(@Param("userName") String userName);
@Transactional
@Modifying // QueryExecutionRequestException: Not supported for DML operations
@Query("update User set user_name=?2 where id=?1")
int updateUserNameById(long id, @Param("userName")String userName);
}
package ;
import ;
import ;
import .slf4j.Slf4j;
import ;
import ;
import ;
import ;
import ;
import ;
import ;
import ;
/**
* @author 小石潭记
* @date 2020/10/4 17:03
* @Description: ${todo}
*/
@Service
@Transactional
@Slf4j
public class UserService {
@PersistenceContext
private EntityManager entityManager;
@Autowired
private JdbcTemplate jdbcTemplate;
/**
* 批量插入
*
* @param list 实体类集合
* @param <T> 表对应的实体类
*/
public <T> void batchInsert(List<T> list) {
if (!(list)) {
for (int i = 0; i < (); i++) {
((i));
if (i % 50 == 0) {
();
();
}
}
();
();
}
}
/**
* 批量更新
*
* @param list 实体类集合
* @param <T> 表对应的实体类
*/
public <T> void batchUpdate(List<T> list) {
if (!(list)) {
for (int i = 0; i < (); i++) {
((i));
if (i % 50 == 0) {
();
();
}
}
();
();
}
}
public void saveBatch(List<User> list) {
/*String sql="insert into user " +
"(user_name)" +
" values (?)";
List<Object[]> batchArgs=new ArrayList<Object[]>();
for (int i = 0; i < (); i++) {
(new Object[]{(i)});
}
(sql, batchArgs);*/
StringBuilder insert = new StringBuilder("INSERT INTO `user` (`user_name`, `pass_word`, `nick_name`," +
"`email`,`reg_time`) VALUES ");
for (int i = 0; i < (); i++) {
("(")
.append("'")
.append((i).getUserName())
.append("'")
.append(",")
.append("'")
.append((i).getPassWord())
.append("'")
.append(",")
.append("'")
.append((i).getNickName())
.append("'")
.append(",")
.append("'")
.append((i).getEmail())
.append("'")
.append(",")
.append("'")
.append((i).getRegTime())
.append("'")
.append(")");
if (i < () - 1) {
(",");
}
}
String sql = (String) (insert);
("SQL语句:{}", (insert));
try {
(sql);
} catch (Exception e) {
("sql解析错误", ());
}
}
}
8.控制器
package ;
import ;
import ;
import ;
import .slf4j.Slf4j;
import ;
import ;
import ;
import ;
import ;
import ;
import ;
/**
* @author 小石潭记
* @date 2020/10/4 14:25
* @Description: ${todo}
*/
@RestController
@Slf4j
public class UserController {
@Autowired
private UserRepository repository;
@Autowired
private UserService service;
@GetMapping("/save")
public void save(){
List<User> list = new ArrayList<>();
for (int i = 0; i < 500; i++) {
User user = new User();
("小石潭记" + i);
(user);
}
long start = ();
("开始保存", start);
// 500 条数据花费9s
(list);
long end = ();
("耗时{}s", (end-start) / 1000);
}
@GetMapping("/saveAll")
public void saveAll(){
List<User> list = new ArrayList<>();
for (int i = 0; i < 500; i++) {
User user = new User();
("frank" + i);
(user);
}
long start = ();
("开始保存", start);
// 500 条数据花费13s yml开启批量操作9s
(list);
long end = ();
("耗时{}s", (end-start) / 1000);
}
/**
* 使用原生的jdbcTemplate批量插入数据 速度比上面的两个都快
*/
@GetMapping("/saveBatch")
public void saveBatch(){
List<User> list = new ArrayList<>();
// 耗时1792ms 速度很快了
for (int i = 0; i < 5000; i++) {
User user = new User();
("frank" + i);
(i + "");
("小石潭记" + i);
("password" + i);
(user);
}
long start = ();
("开始保存", start);
(list);
long end = ();
("耗时{}", end-start);
}
@GetMapping("/user-info")
public List<User> getUserInfo(String userName, String email) {
User user = (userName);
("查询的user,{}", user);
List<User> byUserNameOrEmail = (userName, email);
("查询的byUserNameOrEmail,{}", byUserNameOrEmail);
Iterable<User> iterable = ();
List<User> list = new ArrayList<>();
(single->{(single);});
return list;
}
@GetMapping("/update-user")
public int updateUserName(String id, String userName) {
long userId = (id);
return (userId, userName);
}
}
9.启动类
package ;
import ;
import ;
import ;
import ;
import ;
/**
* @EnableJpaRepositories(basePackages = “”) //扫描 @Repository 注解;
* @ComponentScan(basePackages = “”) //扫描 @Controller、@Service 注解;
* @EntityScan(basePackages = “”) //扫描 @Entity 注解;
*/
@SpringBootApplication
public class SpingbootJpaApplication {
public static void main(String[] args) {
(, args);
}
}
经过测试,使用saveAll500条数据花费9s时间,yml开启批量插入:500 条数据花费13s yml开启批量操作9s,使用jdbcTemplate插入数据,5000条数据花费1792ms,速度快了很多。
代码地址