类org.hibernate.NonUniqueObjectException源码实例Demo

下面列出了怎么用org.hibernate.NonUniqueObjectException的API类实例代码及写法,或者点击链接到github查看源代码。

/**
 * Performs the load of an entity.
 *
 * @param event The initiating load request event
 * @param persister The persister corresponding to the entity to be loaded
 * @param keyToLoad The key of the entity to be loaded
 * @param options The defined load options
 *
 * @return The loaded entity.
 */
private CompletionStage<Object> load( LoadEvent event, EntityPersister persister, EntityKey keyToLoad, LoadType options) {
	final EventSource session = event.getSession();
	if ( event.getInstanceToLoad() != null ) {
		if ( session.getPersistenceContextInternal().getEntry( event.getInstanceToLoad() ) != null ) {
			throw new PersistentObjectException(
					"attempted to load into an instance that was already associated with the session: " +
							MessageHelper.infoString( persister, event.getEntityId(), session.getFactory() ) );
		}
		persister.setIdentifier( event.getInstanceToLoad(), event.getEntityId(), session );
	}

	return doLoad( event, persister, keyToLoad, options )
			.thenApply( optional -> {
				boolean isOptionalInstance = event.getInstanceToLoad() != null;
				if ( optional==null && ( !options.isAllowNulls() || isOptionalInstance ) ) {
					throwEntityNotFound( session, event.getEntityClassName(), event.getEntityId() );
				}
				else if ( isOptionalInstance && optional != event.getInstanceToLoad() ) {
					throw new NonUniqueObjectException( event.getEntityId(), event.getEntityClassName() );
				}
				return optional;
			} );
}
 
源代码2 项目: TomboloDigitalConnector   文件: SubjectUtils.java
public static void saveWithoutUpdate(List<Subject> subjects){
	HibernateUtil.withSession(session -> {
		session.beginTransaction();
		int saved = 0;
		for (Subject subject : subjects) {
               try{
                   session.save(subject);
                   saved++;
               }catch(NonUniqueObjectException e){
                   log.warn("Could not save subject {}, name {},", subject.getLabel(), subject.getName());
               }

			if ( saved % 50 == 0 ) {
				session.flush();
				session.clear();
			}
		}
		session.getTransaction().commit();
	});
}
 
源代码3 项目: TomboloDigitalConnector   文件: TimedValueUtils.java
public static int save(List<TimedValue> timedValues){
	return HibernateUtil.withSession((session) -> {
		int saved = 0;
		session.beginTransaction();
		for (TimedValue timedValue : timedValues){
			try{
				session.saveOrUpdate(timedValue);
				saved++;
			}catch(NonUniqueObjectException e){
				// This is happening because the TFL stations contain a duplicate ID
				log.warn("Could not save timed value for subject {}, attribute {}, time {}: {}",
						timedValue.getId().getSubject().getLabel(),
						timedValue.getId().getAttribute().getDescription(),
						timedValue.getId().getTimestamp().format(DateTimeFormatter.ISO_LOCAL_DATE_TIME),
						e.getMessage());
			}
			if ( saved % 50 == 0 ) { // because batch size in the hibernate config is 50
				session.flush();
				session.clear();
			}
		}
		session.getTransaction().commit();
		return saved;
	});
}
 
源代码4 项目: TomboloDigitalConnector   文件: TimedValueUtils.java
public static int saveWithoutUpdate(List<TimedValue> timedValues){
	return HibernateUtil.withSession((session) -> {
		int saved = 0;
		session.beginTransaction();
		for (TimedValue timedValue : timedValues){
			try{
				session.save(timedValue);
				saved++;
			}catch(NonUniqueObjectException e){
				log.warn("Could not save timed value for subject {}, attribute {}, time {}: {}",
						timedValue.getId().getSubject().getLabel(),
						timedValue.getId().getAttribute().getDescription(),
						timedValue.getId().getTimestamp().format(DateTimeFormatter.ISO_LOCAL_DATE_TIME),
						e.getMessage());
			}
			if ( saved % 50 == 0 ) { 
				session.flush();
				session.clear();
			}
		}
		session.getTransaction().commit();
		return saved;
	});
}
 
源代码5 项目: TomboloDigitalConnector   文件: FixedValueUtils.java
public static int save(List<FixedValue> fixedValues){
    return HibernateUtil.withSession((session) -> {
        int saved = 0;
        session.beginTransaction();
        for (FixedValue fixedValue : fixedValues){
            try{
                session.saveOrUpdate(fixedValue);
                saved++;
            }catch(NonUniqueObjectException e){
                // This is happening because the TFL stations contain a duplicate ID
                log.warn("Could not save fixed value for subject {}, attribute {}: {}",
                        fixedValue.getId().getSubject().getLabel(),
                        fixedValue.getId().getAttribute().getLabel(),
                        e.getMessage());
            }
            if ( saved % 50 == 0 ) { // because batch size in the hibernate config is 50
                session.flush();
                session.clear();
            }
        }
        session.getTransaction().commit();
        return saved;
    });
}
 
源代码6 项目: TomboloDigitalConnector   文件: FixedValueUtils.java
public static int saveWithoutUpdate(List<FixedValue> fixedValues){
    return HibernateUtil.withSession((session) -> {
        int saved = 0;
        session.beginTransaction();
        for (FixedValue fixedValue : fixedValues){
            try{
                session.save(fixedValue);
                saved++;
            }catch(NonUniqueObjectException e){
                log.warn("Could not save fixed value for subject {}, attribute {}: {}",
                        fixedValue.getId().getSubject().getLabel(),
                        fixedValue.getId().getAttribute().getLabel(),
                        e.getMessage());
            }
            if ( saved % 50 == 0 ) { 
                session.flush();
                session.clear();
            }
        }
        session.getTransaction().commit();
        return saved;
    });
}
 
源代码7 项目: cacheonix-core   文件: MergeTest.java
public void testPersistThenMergeInSameTxnWithVersion() {
	Session s = openSession();
	Transaction tx = s.beginTransaction();
	VersionedEntity entity = new VersionedEntity( "test", "test" );
	s.persist( entity );
	s.merge( new VersionedEntity( "test", "test-2" ) );

	try {
		// control operation...
		s.saveOrUpdate( new VersionedEntity( "test", "test-3" ) );
		fail( "saveOrUpdate() should fail here" );
	}
	catch( NonUniqueObjectException expected ) {
		// expected behavior
	}

	tx.commit();
	s.close();

	cleanup();
}
 
源代码8 项目: cacheonix-core   文件: MergeTest.java
public void testPersistThenMergeInSameTxnWithTimestamp() {
	Session s = openSession();
	Transaction tx = s.beginTransaction();
	TimestampedEntity entity = new TimestampedEntity( "test", "test" );
	s.persist( entity );
	s.merge( new TimestampedEntity( "test", "test-2" ) );

	try {
		// control operation...
		s.saveOrUpdate( new TimestampedEntity( "test", "test-3" ) );
		fail( "saveOrUpdate() should fail here" );
	}
	catch( NonUniqueObjectException expected ) {
		// expected behavior
	}

	tx.commit();
	s.close();

	cleanup();
}
 
源代码9 项目: lams   文件: StatefulPersistenceContext.java
@Override
public void checkUniqueness(EntityKey key, Object object) throws HibernateException {
	final Object entity = getEntity( key );
	if ( entity == object ) {
		throw new AssertionFailure( "object already associated, but no entry was found" );
	}
	if ( entity != null ) {
		throw new NonUniqueObjectException( key.getIdentifier(), key.getEntityName() );
	}
}
 
源代码10 项目: lams   文件: DefaultLoadEventListener.java
/**
 * Performs the load of an entity.
 *
 * @param event The initiating load request event
 * @param persister The persister corresponding to the entity to be loaded
 * @param keyToLoad The key of the entity to be loaded
 * @param options The defined load options
 *
 * @return The loaded entity.
 *
 * @throws HibernateException
 */
private Object load(
		final LoadEvent event,
		final EntityPersister persister,
		final EntityKey keyToLoad,
		final LoadEventListener.LoadType options) {

	if ( event.getInstanceToLoad() != null ) {
		if ( event.getSession().getPersistenceContext().getEntry( event.getInstanceToLoad() ) != null ) {
			throw new PersistentObjectException(
					"attempted to load into an instance that was already associated with the session: " +
							MessageHelper.infoString(
									persister,
									event.getEntityId(),
									event.getSession().getFactory()
							)
			);
		}
		persister.setIdentifier( event.getInstanceToLoad(), event.getEntityId(), event.getSession() );
	}

	final Object entity = doLoad( event, persister, keyToLoad, options );

	boolean isOptionalInstance = event.getInstanceToLoad() != null;

	if ( entity == null && ( !options.isAllowNulls() || isOptionalInstance ) ) {
		event.getSession()
				.getFactory()
				.getEntityNotFoundDelegate()
				.handleEntityNotFound( event.getEntityClassName(), event.getEntityId() );
	}
	else if ( isOptionalInstance && entity != event.getInstanceToLoad() ) {
		throw new NonUniqueObjectException( event.getEntityId(), event.getEntityClassName() );
	}

	return entity;
}
 
/**
 * Attempts to check whether the given key represents an entity already loaded within the
 * current session.
 * @param object The entity reference against which to perform the uniqueness check.
 * @throws HibernateException
 */
public void checkUniqueness(EntityKey key, Object object) throws HibernateException {
	Object entity = getEntity(key);
	if ( entity == object ) {
		throw new AssertionFailure( "object already associated, but no entry was found" );
	}
	if ( entity != null ) {
		throw new NonUniqueObjectException( key.getIdentifier(), key.getEntityName() );
	}
}
 
源代码12 项目: cacheonix-core   文件: DefaultLoadEventListener.java
/**
 * Perfoms the load of an entity.
 *
 * @return The loaded entity.
 * @throws HibernateException
 */
protected Object load(
	final LoadEvent event, 
	final EntityPersister persister, 
	final EntityKey keyToLoad, 
	final LoadEventListener.LoadType options)
throws HibernateException {

	if ( event.getInstanceToLoad() != null ) {
		if ( event.getSession().getPersistenceContext().getEntry( event.getInstanceToLoad() ) != null ) {
			throw new PersistentObjectException(
					"attempted to load into an instance that was already associated with the session: " +
					MessageHelper.infoString( persister, event.getEntityId(), event.getSession().getFactory() )
				);
		}
		persister.setIdentifier( event.getInstanceToLoad(), event.getEntityId(), event.getSession().getEntityMode() );
	}

	Object entity = doLoad(event, persister, keyToLoad, options);
	
	boolean isOptionalInstance = event.getInstanceToLoad() != null;
	
	if ( !options.isAllowNulls() || isOptionalInstance ) {
		if ( entity == null ) {
			event.getSession().getFactory().getEntityNotFoundDelegate().handleEntityNotFound( event.getEntityClassName(), event.getEntityId() );
		}
	}

	if ( isOptionalInstance && entity != event.getInstanceToLoad() ) {
		throw new NonUniqueObjectException( event.getEntityId(), event.getEntityClassName() );
	}

	return entity;
}
 
源代码13 项目: AlgoTrader   文件: HibernateUtil.java
public static boolean lock(SessionFactory sessionFactory, Object target) {

		Session session = sessionFactory.getCurrentSession();

		try {
			session.buildLockRequest(LockOptions.NONE).lock(target);
			return true;
		} catch (NonUniqueObjectException e) {
			//  different object with the same identifier value was already associated with the session
			return false;
		}
	}
 
源代码14 项目: tutorials   文件: HibernateExceptionUnitTest.java
@Test
public void givenSessionContainingAnId_whenIdAssociatedAgain_thenNonUniqueObjectException() {
    thrown.expect(isA(NonUniqueObjectException.class));
    thrown.expectMessage(
        "A different object with the same identifier value was already associated with the session");

    Session session = null;
    Transaction transaction = null;

    try {
        session = sessionFactory.openSession();
        transaction = session.beginTransaction();

        Product product1 = new Product();
        product1.setId(1);
        product1.setName("Product 1");
        session.save(product1);

        Product product2 = new Product();
        product2.setId(1);
        product2.setName("Product 2");
        session.save(product2);

        transaction.commit();
    } catch (Exception e) {
        rollbackTransactionQuietly(transaction);
        throw (e);
    } finally {
        closeSessionQuietly(session);
    }
}
 
/**
 * Prepares the save call by checking the session caches for a pre-existing
 * entity and performing any lifecycle callbacks.
 *
 * @param entity The entity to be saved.
 * @param id The id by which to save the entity.
 * @param persister The entity's persister instance.
 * @param useIdentityColumn Is an identity column being used?
 * @param context Generally cascade-specific information.
 * @param source The session from which the event originated.
 * @param requiresImmediateIdAccess does the event context require
 * access to the identifier immediately after execution of this method (if
 * not, post-insert style id generators may be postponed if we are outside
 * a transaction).
 *
 * @return The id used to save the entity; may be null depending on the
 * type of id generator used and the requiresImmediateIdAccess value
 */
protected CompletionStage<Void> reactivePerformSave(
		Object entity,
		Serializable id,
		EntityPersister persister,
		boolean useIdentityColumn,
		C context,
		EventSource source,
		boolean requiresImmediateIdAccess) {

	if ( LOG.isTraceEnabled() ) {
		LOG.tracev( "Saving {0}", MessageHelper.infoString( persister, id, source.getFactory() ) );
	}

	final EntityKey key;
	if ( !useIdentityColumn ) {
		key = source.generateEntityKey( id, persister );
		final PersistenceContext persistenceContext = source.getPersistenceContextInternal();
		Object old = persistenceContext.getEntity( key );
		if ( old != null ) {
			if ( persistenceContext.getEntry( old ).getStatus() == Status.DELETED ) {
				source.forceFlush( persistenceContext.getEntry( old ) );
			}
			else {
				return CompletionStages.failedFuture( new NonUniqueObjectException( id, persister.getEntityName() ) );
			}
		}
		persister.setIdentifier( entity, id, source );
	}
	else {
		key = null;
	}

	return reactivePerformSaveOrReplicate(
			entity,
			key,
			persister,
			useIdentityColumn,
			context,
			source,
			requiresImmediateIdAccess
	);
}
 
源代码16 项目: uyuni   文件: ActivationKeyCloneCommand.java
/**
 * Construct a ActivationKeyCloneCommand
 * @param userIn user doing the cloning
 * @param key Activation key to be cloned
 * @param cloneDescription The description of the cloned key.
 */
public ActivationKeyCloneCommand(User userIn, String key,
        String cloneDescription) {

    ActivationKeyManager akm = ActivationKeyManager.getInstance();
    ActivationKey ak = lookupKey(key, userIn);

    try {
        cak = akm.createNewActivationKey(userIn, "", cloneDescription,
                ak.getUsageLimit(), ak.getBaseChannel(), false);
        // only one akey can be Universal default
    }
    catch (ValidatorException ve) { // the user is not allowed to create AK
        throw FaultException.create(1091, "activationkey", ve.getResult());
    }
    catch (NonUniqueObjectException e) {
        throw new ActivationKeyAlreadyExistsException();
    }

    // enable/disable
    cak.setDisabled(ak.isDisabled());

    // Entitlements
    Set<ServerGroupType> cloneEnt = new HashSet<ServerGroupType>();
    cloneEnt.addAll(ak.getEntitlements());
    cak.setEntitlements(cloneEnt);

    // child channels
    Set<Channel> channels = new HashSet<Channel>();
    channels.addAll(ak.getChannels());
    cak.setChannels(channels);

    // Configuration File Deployment
    cak.setDeployConfigs(ak.getDeployConfigs());

    // packages
    for (Iterator<TokenPackage> it = ak.getPackages().iterator(); it
            .hasNext();) {
        TokenPackage temp = it.next();
        cak.addPackage(temp.getPackageName(), temp.getPackageArch());
    }

    // Configuration channels
    List<String> lcloneConfigChannels = new ArrayList<String>();
    for (Iterator<ConfigChannel> it = ak.getConfigChannelsFor(userIn)
            .iterator(); it.hasNext();) {
        lcloneConfigChannels.add(it.next().getLabel());
    }

    List<String> lcak = new ArrayList<String>();
    lcak.add(cak.getKey());
    setConfigChannels(userIn, lcak, lcloneConfigChannels);

    // Groups
    Set<ServerGroup> cloneServerGroups = new HashSet<ServerGroup>();
    cloneServerGroups.addAll(ak.getServerGroups());
    cak.setServerGroups(cloneServerGroups);

    // Contact method
    cak.setContactMethod(ak.getContactMethod());
}
 
源代码17 项目: lams   文件: AbstractSaveEventListener.java
/**
 * Prepares the save call by checking the session caches for a pre-existing
 * entity and performing any lifecycle callbacks.
 *
 * @param entity The entity to be saved.
 * @param id The id by which to save the entity.
 * @param persister The entity's persister instance.
 * @param useIdentityColumn Is an identity column being used?
 * @param anything Generally cascade-specific information.
 * @param source The session from which the event originated.
 * @param requiresImmediateIdAccess does the event context require
 * access to the identifier immediately after execution of this method (if
 * not, post-insert style id generators may be postponed if we are outside
 * a transaction).
 *
 * @return The id used to save the entity; may be null depending on the
 *         type of id generator used and the requiresImmediateIdAccess value
 */
protected Serializable performSave(
		Object entity,
		Serializable id,
		EntityPersister persister,
		boolean useIdentityColumn,
		Object anything,
		EventSource source,
		boolean requiresImmediateIdAccess) {

	if ( LOG.isTraceEnabled() ) {
		LOG.tracev( "Saving {0}", MessageHelper.infoString( persister, id, source.getFactory() ) );
	}

	final EntityKey key;
	if ( !useIdentityColumn ) {
		key = source.generateEntityKey( id, persister );
		Object old = source.getPersistenceContext().getEntity( key );
		if ( old != null ) {
			if ( source.getPersistenceContext().getEntry( old ).getStatus() == Status.DELETED ) {
				source.forceFlush( source.getPersistenceContext().getEntry( old ) );
			}
			else {
				throw new NonUniqueObjectException( id, persister.getEntityName() );
			}
		}
		persister.setIdentifier( entity, id, source );
	}
	else {
		key = null;
	}

	if ( invokeSaveLifecycle( entity, persister, source ) ) {
		return id; //EARLY EXIT
	}

	return performSaveOrReplicate(
			entity,
			key,
			persister,
			useIdentityColumn,
			anything,
			source,
			requiresImmediateIdAccess
	);
}
 
源代码18 项目: cacheonix-core   文件: AbstractSaveEventListener.java
/**
 * Ppepares the save call by checking the session caches for a pre-existing
 * entity and performing any lifecycle callbacks.
 *
 * @param entity The entity to be saved.
 * @param id The id by which to save the entity.
 * @param persister The entity's persister instance.
 * @param useIdentityColumn Is an identity column being used?
 * @param anything Generally cascade-specific information.
 * @param source The session from which the event originated.
 * @param requiresImmediateIdAccess does the event context require
 * access to the identifier immediately after execution of this method (if
 * not, post-insert style id generators may be postponed if we are outside
 * a transaction).
 *
 * @return The id used to save the entity; may be null depending on the
 *         type of id generator used and the requiresImmediateIdAccess value
 */
protected Serializable performSave(
		Object entity,
		Serializable id,
		EntityPersister persister,
		boolean useIdentityColumn,
		Object anything,
		EventSource source,
		boolean requiresImmediateIdAccess) {

	if ( log.isTraceEnabled() ) {
		log.trace(
				"saving " +
						MessageHelper.infoString( persister, id, source.getFactory() )
		);
	}

	EntityKey key;
	if ( !useIdentityColumn ) {
		key = new EntityKey( id, persister, source.getEntityMode() );
		Object old = source.getPersistenceContext().getEntity( key );
		if ( old != null ) {
			if ( source.getPersistenceContext().getEntry( old ).getStatus() == Status.DELETED ) {
				source.forceFlush( source.getPersistenceContext().getEntry( old ) );
			}
			else {
				throw new NonUniqueObjectException( id, persister.getEntityName() );
			}
		}
		persister.setIdentifier( entity, id, source.getEntityMode() );
	}
	else {
		key = null;
	}

	if ( invokeSaveLifecycle( entity, persister, source ) ) {
		return id; //EARLY EXIT
	}

	return performSaveOrReplicate(
			entity,
			key,
			persister,
			useIdentityColumn,
			anything,
			source,
			requiresImmediateIdAccess
	);
}
 
源代码19 项目: sakai   文件: ContextMappingDAOTest.java
@Test(expected = NonUniqueObjectException.class)
public void testAddAdd() {
    dao.add("uuid", "componentId", "contextId1");
    dao.add("uuid", "componentId", "contextId2");
}
 
源代码20 项目: sakai   文件: ContextMappingDAOTest.java
@Test(expected = NonUniqueObjectException.class)
public void testAddAdd() {
    dao.add("uuid", "componentId", "contextId1");
    dao.add("uuid", "componentId", "contextId2");
}
 
源代码21 项目: spacewalk   文件: ActivationKeyCloneCommand.java
/**
 * Construct a ActivationKeyCloneCommand
 * @param userIn user doing the cloning
 * @param key Activation key to be cloned
 * @param cloneDescription The description of the cloned key.
 */
public ActivationKeyCloneCommand(User userIn, String key,
        String cloneDescription) {

    ActivationKeyManager akm = ActivationKeyManager.getInstance();
    ActivationKey ak = lookupKey(key, userIn);

    try {
        cak = akm.createNewActivationKey(userIn, "", cloneDescription,
                ak.getUsageLimit(), ak.getBaseChannel(), false);
        // only one akey can be Universal default
    }
    catch (ValidatorException ve) { // the user is not allowed to create AK
        throw FaultException.create(1091, "activationkey", ve.getResult());
    }
    catch (NonUniqueObjectException e) {
        throw new ActivationKeyAlreadyExistsException();
    }

    // enable/disable
    cak.setDisabled(ak.isDisabled());

    // Entitlements
    Set<ServerGroupType> cloneEnt = new HashSet<ServerGroupType>();
    cloneEnt.addAll(ak.getEntitlements());
    cak.setEntitlements(cloneEnt);

    // child channels
    Set<Channel> channels = new HashSet<Channel>();
    channels.addAll(ak.getChannels());
    cak.setChannels(channels);

    // Configuration File Deployment
    cak.setDeployConfigs(ak.getDeployConfigs());

    // packages
    for (Iterator<TokenPackage> it = ak.getPackages().iterator(); it
            .hasNext();) {
        TokenPackage temp = it.next();
        cak.addPackage(temp.getPackageName(), temp.getPackageArch());
    }

    // Configuration channels
    List<String> lcloneConfigChannels = new ArrayList<String>();
    for (Iterator<ConfigChannel> it = ak.getConfigChannelsFor(userIn)
            .iterator(); it.hasNext();) {
        lcloneConfigChannels.add(it.next().getLabel());
    }

    List<String> lcak = new ArrayList<String>();
    lcak.add(cak.getKey());
    setConfigChannels(userIn, lcak, lcloneConfigChannels);

    // Groups
    Set<ServerGroup> cloneServerGroups = new HashSet<ServerGroup>();
    cloneServerGroups.addAll(ak.getServerGroups());
    cak.setServerGroups(cloneServerGroups);
}
 
源代码22 项目: aw-reporting   文件: SqlReportEntitiesPersister.java
/**
 * Persists all the given entities into the DB configured in the {@code SessionFactory}. Specify
 * the following system properties backoff.delay
 */
@Override
@Transactional
@Retryable(
    value = {LockAcquisitionException.class},
    maxAttemptsExpression = "#{ @systemProperties['retryBackoff'] ?: 20}",
    backoff =
        @Backoff(
            delayExpression = "#{ @systemProperties['retryDelay'] ?: 100}",
            maxDelayExpression = "#{ @systemProperties['retryMaxDelay'] ?: 50000 }",
            multiplierExpression = "#{ @systemProperties['retryMultiplier'] ?: 1.5}"))
public void persistReportEntities(List<? extends Report> reportEntities) {
  int batchFlush = 0;
  Session session = sessionFactory.getCurrentSession();
  FlushMode previousFlushMode = session.getHibernateFlushMode();
  session.setHibernateFlushMode(FlushMode.MANUAL);

  try {
    for (Report report : reportEntities) {
      report.setRowId();

      session.saveOrUpdate(report);
      batchFlush++;

      if (batchFlush == config.getBatchSize()) {
        session.flush();
        session.clear();
        batchFlush = 0;
      }
    }

    if (batchFlush > 0) {
      session.flush();
      session.clear();
    }
  } catch (NonUniqueObjectException ex) {
    // Github issue 268 & 280
    //   https://github.com/googleads/aw-reporting/issues/268
    //   https://github.com/googleads/aw-reporting/issues/280
    //
    // Currently we allow specifying report definitions which do not include all primary key
    // fields. This leads to cryptic hibernate errors without providing a reasonable
    // resolution strategy.
    //
    // This fix explains where to find the list of primary key fields, but does not address
    // the underlying issue of allowing non-unique rows to be downloaded in the first place.
    //
    // Ideally we would guarantee uniqueness of rows without the user having to specify the
    // PK fields.
    // However, this would be a substantial migration for the AWReporting user base.
    // Instead, we just log a (hopefully) useful error message.
    // Also note that the error message assumes that reportEntities was not empty, because
    // otherwise the exception would not have been thrown.
    logger.error(
        "Duplicate row detected. This is most likely because your report definition does not "
            + "include the primary key fields defined in {}.setRowId(). "
            + "Please add the missing fields and try again.",
        reportEntities.get(0).getClass().getName());
    throw ex;
  } finally {
    session.setHibernateFlushMode(previousFlushMode);
  }
}
 
 类所在包
 同包方法