jpa 的动态插入和动态更新

使用JPA的时候,当我们插入数据的时候,我们不仅可以自己在model类里面赋初值,还可以使用数据库表的default值。希望大家通过以下对JPA学习,能对大家有帮助。

  让我们开始进行JPA学习吧。首先,我们在model类里面为column设置数据库default值,以前使用Hibernate的时候的做法是添加sql-type,例如:
<property name="viewDate" not-null="false"type="java.util.Date"> 


 
  <columnname="viewDate" sql-type="datetime; defaultgetdate()"/> 
</property>

在JPA里面使用columnDefinition代替sql-type:
 
  @Column(columnDefinition="datetime default getdate()")
 
  @Temporal(javax.persistence.TemporalType.TIMESTAMP)
 
   private DateviewDate;

那么,当我们的generateDdl设为true的时候,可以在数据库生成表,而且viewDate字段会带一个默认值getdate(),当我们的sql语句不带viewDate字段的时候,就会使用到getdate()去取数据库的系统时间。

以前Hibernate的做法是添加dynamic-insert="true"和dynamic-update="true"。但是JPA好像没有这个功能。如果你的JPA的Privider
是Hibernate的话可以添加如下Annotation为我们的实体提供dynamic-insert,dynamic-update,如下:
@Entity
@org.hibernate.annotations.Entity(dynamicInsert=true,dynamicUpdate=true)
public class MyEntity{
//省略其他字段
......
 
  @Column(columnDefinition="datetime default getdate()")
 
  @Temporal(javax.persistence.TemporalType.TIMESTAMP)
 
   private DateviewDate;
//注意,这里不要给viewDate一个初始值,例如viewDate = newDate();是错的。只有null才会在加入的时候,使用到dynamicInsert
//省略getter,setter
......
}

### 使用 JPA 批量插入的最佳实践 JPA 提供了一种抽象的方式来处理数据库操作,而批量插入是一种常见的需求。为了优化性能并减少资源消耗,在执行批量插入时可以遵循一些最佳实践。 #### 配置批处理大小 通过设置 `hibernate.jdbc.batch_size` 属性来启用 JDBC 的批处理功能。该属性定义每次提交到数据库的操作数量。通常建议将其值设为 10 到 50 之间[^4]。 ```properties spring.jpa.properties.hibernate.jdbc.batch_size=30 ``` #### 禁用二级缓存查询缓存 在大批量数据插入过程中,禁用 Hibernate 的二级缓存查询缓存能够显著提升性能。这是因为这些缓存在高吞吐场景下可能会成为瓶颈[^5]。 ```java spring.jpa.properties.hibernate.cache.use_second_level_cache=false spring.jpa.properties.hibernate.cache.use_query_cache=false ``` #### 清理持久化上下文 当向数据库写入大量记录时,持久化上下文中会积累许多对象实例。这可能导致内存占用过高甚至引发 OutOfMemoryError。因此,每完成一批次的数据插入后应调用 `entityManager.clear()` 方法释放内存[^6]。 ```java for (int i = 0; i < entities.size(); i++) { entityManager.persist(entities.get(i)); if (i % batchSize == 0 && i != 0) { // 当达到批次大小时刷新并清理 entityManager.flush(); entityManager.clear(); } } ``` #### 设置 ID 生成策略 对于支持自增列的数据库(如 MySQL 或 PostgreSQL),推荐使用 `IDENTITY` 作为主键生成器;而对于其他类型的数据库,则可以选择 `SEQUENCE` 或者 `TABLE` 方式。需要注意的是,如果采用序列机制,请确保其增量与批处理大小一致以提高效率[^7]。 ```java @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; ``` 或者: ```java @Id @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "sequence_generator") @SequenceGenerator(name="sequence_generator", sequenceName = "my_sequence", allocationSize=batchSize) private Long id; ``` #### 减少事务开销 尽可能在一个事务内完成所有的批量插入工作,这样不仅可以降低锁竞争还能加快速度。但是要注意控制单个事务持续时间不要太长以免影响并发访问[^8]。 ```java @Transactional public void bulkInsert(List<Entity> entities){ int batchSize = Integer.parseInt(env.getProperty("batch.size")); for(int i=0;i<entities.size();i++){ repository.save(entities.get(i)); if((i+1)%batchSize==0 || i==(entities.size()-1)){ entityManager.flush(); entityManager.clear(); } } } ``` --- 相关问题
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值