一)EntityManager方法简介
1、
entityManager.
find
(Class<T> entityClass, Object primaryKey);
根据主键查找数据;如果主键格式不正确,会抛出illegalArgumentException异常;如果主键在数据库未找到数据返回null;
2、
entityManager.
persist
(Object entity);
新增数据;如果entity的主键不为空,而数据库没有该主键,会抛出异常;如果entity的主键不为空,而数据库有该主键,且entity的其他字段与数据库不同,persist后不会更新数据库;
3、
entityManager.
merge
(T entity);
将 Detached状态的Entity实例转至Managed状态;
4、
entityManager.
remove
(Object entity);
删除数据;只能将Managed状态的Entity实例删除,由此Entity实例状态变为Removed;
5、
entityManager.
clear
();
将所有的Entity实例状态转至Detached状态;
6、
entityManager.
flush
();
将所有Managed状态的Entity实例同步到数据库;
7、
entityManager.
refresh
(Object entity);
加载Entity实例后,数据库该条数据被修改,refresh该实例,能得到数据库最新的修改,覆盖原来的Entity实例;
二)EntityManager批量新增or修改
测试方式:用一个循环往一个表批量插入数据,需要先判断数据是否已经存在,然后再做新增or修改。
package com.oyj.jpa;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityTransaction;
import javax.persistence.Persistence;
import com.oyj.jpa.entity.EmployeeEntity;
public class SessionBatchAddEmployee {
public static void main(String[] args) {
// JPA批量插入
EntityManagerFactory entityManagerFactory = null;
EntityManager entityManager = null;
EntityTransaction txn = null;
try {
entityManagerFactory = Persistence.createEntityManagerFactory("myhibernate_jpa");
entityManager = entityManagerFactory.createEntityManager();
txn = entityManager.getTransaction();
txn.begin();
int batchSize = 1000; // 批次
int size = 100000; // 插入数据的数据量
Long beginTime = System.currentTimeMillis(); // 开始时间
EmployeeEntity entity = null;
EmployeeEntity en = null;
for (int i = 0; i < size; i++) {
if (i > 0 && i % batchSize == 0) {
System.out.println("第" + (i/batchSize) + "次刷新entityManager!");
entityManager.flush();
entityManager.clear();
int userid = (i+1);
// 实体类
entity = new EmployeeEntity();
entity.setUserID(userid);
entity.setUserName("userName" + userid);
entity.setSex(1);
// 当表里存在主键约束时, 需要判断数据是否已存在, 否则会报错
en = entityManager.find(EmployeeEntity.class, userid);
if (en != null) {
entityManager.merge(entity); // 修改
} else {
entityManager.persist(entity); // 新增
txn.commit();
Long endTime = System.currentTimeMillis(); // 结束时间
System.out.println("JPA批量插入or修改" + size + "数据, 执行总耗时: " + (endTime - beginTime) + "毫秒");
} catch (RuntimeException e) {
if ( txn != null && txn.isActive()) txn.rollback();
throw e;
} finally {
if (entityManager != null) {
entityManager.close();
控制台打印效果图:(用本地数据库执行,多启动几次,发现插入会变慢)
三)JDBC批量新增or修改
测试方式:用一个循环往一个表批量插入数据,需要先判断数据是否已经存在,然后再做新增or修改。
package com.oyj.jpa;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;
public class JdbcBatchAddEmployee {
public static void main(String[] args) {
batchInsert();
* JDBC批量插入
public static void batchInsert() {
Connection conn = null;
PreparedStatement ps = null;
try {
conn = getConnection();
StringBuilder builder = new StringBuilder();
builder.append("INSERT INTO employee (userid, username, sex) values(?, ?, ?)");
ps = conn.prepareStatement(builder.toString());
// 先设置不自动提交
conn.setAutoCommit(false);
int batchSize = 1000;
int size = 100000;
Long beginTime = System.currentTimeMillis(); // 开始时间
for (int i = 0; i < size; i++) {
ps.setInt(1, (i+1));
ps.setString(2, "username" + (i+1));
ps.setInt(3, 1);
ps.addBatch();
// 每多少次提交一遍
if (i > 0 && i % batchSize == 0) {
System.out.println("第" + (i/batchSize) + "次executeBatch!");
ps.executeBatch();
conn.commit();
// 最后一次执行批量操作, 当i%500不为0时, 即最后一批数据的提交
ps.executeBatch();
conn.commit();
Long endTime = System.currentTimeMillis(); // 结束时间
System.out.println("JDBC批量插入" + size + "条数据执行总耗时: " + (endTime - beginTime) + "毫秒");
} catch (SQLException e) {
System.out.println("batchInsert==>SQLException Fail!" + e);
} finally {
try {
if (ps != null) {
ps.close();
if (conn != null) {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
public static Connection getConnection() { // 获取数据库连接
Connection conn = null;
try {
if (conn == null) {
Class.forName("oracle.jdbc.driver.OracleDriver");
conn = DriverManager.getConnection("jdbc:oracle:thin:@localhost:1521:ORCL", "oysept", "oysept");
} catch (Exception e) {
System.out.println("getConnection==>SQLException Fail!" + e);
return conn;
控制台效果图打印:
EntityManager在执行批量操作时,数据量越大,执行效率越慢,执行耗时成倍数递增;影响因素较多,网络,数据库性能,数据量等问题。
JDBC批量执行快速,数据量越大,执行效率只会缓慢递增,运行速度快。
识别二维码关注个人微信公众号
本章完结,待续,欢迎转载!
本文说明:该文章属于原创,如需转载,请标明文章转载来源!
一)JPA方法简介1、entityManager.find(Class<T> entityClass, Object primaryKey);根据主键查找数据;如果主键格式不正确,会抛出illegalArgumentException异常;如果主键在数据库未找到数据返回null;2、entityManager.persist(Object entity);新增数据;如果...
有时候我们需要向数据库插入大量数据,如果一条一条插入会非常慢所以我们可以考虑批量插入其实很简单 只需要使用默认的save()方法就可以了假设现在有一个student实体类 我们需要一次插入整个学区5000名学生的信息package com.chunying.boke.bean;
* @author chunying
public class Student {
pr...
已经拥有持久化主键并和持久化建立了上下文环境
当处在托管状态的实体Bean被管理器flush了,那么就在极短暂的时间进入了持久化状态,事务提交之后,立刻变为了游离状态。
您可以把持久化状态当做实实在在的数据库记录。
③ 游离状态
拥有持久化主键,但是没有与持久化建立上下文环境
游离状态就是提交到数据库后,事务commit后实体的状态,因为事务已经提交了,此时实体
在 JPA 中,可以使用 `EntityManager` 对象的 `persist()` 方法来新增实体。如果要批量新增多个实体,可以使用以下方法:
1. 使用 `EntityManager` 对象的 `createQuery()` 方法创建一个批量插入语句,然后使用 `executeUpdate()` 方法执行该语句。例如:
```java
List<Entity> entities = ...;
entityManager.createQuery("INSERT INTO Entity (field1, field2, ...) VALUES (:field1, :field2, ...)")
.setParameter("field1", value1)
.setParameter("field2", value2)
.executeUpdate();
这种方法需要手动拼接 SQL 语句,不太方便。
2. 使用 JPA 提供的批量操作 API,例如 `javax.persistence.EntityManager#persist` 和 `javax.persistence.EntityManager#flush` 方法。例如:
```java
List<Entity> entities = ...;
for (Entity entity : entities) {
entityManager.persist(entity);
if (i % batchSize == 0) { // 每 batchSize 条数据执行一次 flush() 方法
entityManager.flush();
entityManager.clear();
这种方法比较简单,但是需要注意的是,如果新增的实体数量过大,可能会导致内存溢出。因此,一般需要限制批量操作的数量,例如每次执行 `flush()` 方法时只处理一定数量的实体。