在使用Spring Boot和Hibernate进行开发时,遇到保存实体时出现重复条目异常(通常是org.hibernate.NonUniqueObjectException
或org.hibernate.StaleObjectStateException
),通常是由于以下几个原因造成的:
确保在业务逻辑中不会重复提交同一个实体。可以通过加锁或使用唯一标识符来避免重复提交。
@Transactional
public void saveEntity(Entity entity) {
if (entityRepository.existsById(entity.getId())) {
throw new RuntimeException("Entity already exists");
}
entityRepository.save(entity);
}
使用乐观锁或悲观锁来处理并发问题。
乐观锁:通过版本号来实现。
@Entity
public class Entity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Version
private Integer version;
// other fields and methods
}
悲观锁:在查询时使用LockModeType.PESSIMISTIC_WRITE
。
@Transactional
public void saveEntity(Entity entity) {
Entity existingEntity = entityRepository.findById(entity.getId(), LockModeType.PESSIMISTIC_WRITE);
if (existingEntity != null) {
throw new RuntimeException("Entity already exists");
}
entityRepository.save(entity);
}
在某些情况下,可能需要手动清理Session的一级缓存。
@Transactional
public void saveEntity(Entity entity) {
Session session = entityManager.unwrap(Session.class);
session.evict(entity); // 清理缓存
entityRepository.save(entity);
}
以下是一个完整的示例,展示了如何使用乐观锁来避免重复条目异常:
@Entity
public class Entity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Version
private Integer version;
// other fields and methods
}
@Repository
public interface EntityRepository extends JpaRepository<Entity, Long> {
}
@Service
public class EntityService {
@Autowired
private EntityRepository entityRepository;
@Transactional
public void saveEntity(Entity entity) {
if (entityRepository.existsById(entity.getId())) {
throw new RuntimeException("Entity already exists");
}
entityRepository.save(entity);
}
}
通过以上方法,可以有效解决Spring Boot和Hibernate在保存实体时出现的重复条目异常问题。
领取专属 10元无门槛券
手把手带您无忧上云