/** * Throws {@link org.hibernate.PropertyValueException} if there are any unresolved * entity insert actions that depend on non-nullable associations with * a transient entity. This method should be called on completion of * an operation (after all cascades are completed) that saves an entity. * * @throws org.hibernate.PropertyValueException if there are any unresolved entity * insert actions; {@link org.hibernate.PropertyValueException#getEntityName()} * and {@link org.hibernate.PropertyValueException#getPropertyName()} will * return the entity name and property value for the first unresolved * entity insert action. */ public void checkNoUnresolvedActionsAfterOperation() throws PropertyValueException { if ( isEmpty() ) { LOG.trace( "No entity insert actions have non-nullable, transient entity dependencies." ); } else { final AbstractEntityInsertAction firstDependentAction = dependenciesByAction.keySet().iterator().next(); logCannotResolveNonNullableTransientDependencies( firstDependentAction.getSession() ); final NonNullableTransientDependencies nonNullableTransientDependencies = dependenciesByAction.get( firstDependentAction ); final Object firstTransientDependency = nonNullableTransientDependencies.getNonNullableTransientEntities().iterator().next(); final String firstPropertyPath = nonNullableTransientDependencies.getNonNullableTransientPropertyPaths( firstTransientDependency ).iterator().next(); throw new TransientPropertyValueException( "Not-null property references a transient value - transient instance must be saved before current operation", firstDependentAction.getSession().guessEntityName( firstTransientDependency ), firstDependentAction.getEntityName(), firstPropertyPath ); } }
private void importBatch(List<Long> entityIds) throws PropertyValueException { preload(entityIds, getMigrationInformation()); try { MapSqlParameterSource entityIdsParameterSource = new MapSqlParameterSource(); entityIdsParameterSource.addValue(getMigrationInformation().getParameterIds(), entityIds); AutowireCapableBeanFactory autowire = applicationContext.getAutowireCapableBeanFactory(); AbstractResultRowMapper<? extends Map<Owning, Owned>> rowMapper = getMigrationInformation().newRowMapper(entityIds.size(), DEFAULT_VALUES_PER_KEY); autowire.autowireBean(rowMapper); autowire.initializeBean(rowMapper, rowMapper.getClass().getSimpleName()); prepareRowMapper(rowMapper, entityIds); getNamedParameterJdbcTemplate().query(getMigrationInformation().getSqlRequest(), entityIdsParameterSource, rowMapper); for (Map.Entry<Owning, Owned> entry : rowMapper.getResults().entrySet()) { Owning entity = entry.getKey(); getMigrationInformation().addToAssociation(entity, entry.getValue()); if (getEntityService() != null) { getEntityService().update(entity); } else { entityManagerUtils.getEntityManager().persist(entity); } } } catch (RuntimeException | ServiceException | SecurityServiceException e) { getLogger().error("Error during the persistence of {} items. {} cancelled creations.", getMigrationInformation().getAssociationName(), entityIds.size(), e); ProcessorMonitorContext.get().getDoneItems().addAndGet(-1 * entityIds.size()); } }
@Transactional public void saveOrUpdate(T object) { try { getSession().saveOrUpdate(object); } catch (ConstraintViolationException | PropertyValueException | IdentifierGenerationException exception) { throw new IllegalArgumentException(exception); } }
@SuppressWarnings("unchecked") protected T get(Serializable id) { try { return (T) getSession().get(getModelClass(), id); } catch (ConstraintViolationException | PropertyValueException exception) { throw new IllegalArgumentException(exception); } }
/** * Check nullability of the class persister properties * * @param values entity properties * @param persister class persister * @param isUpdate whether it is intended to be updated or saved * * @throws PropertyValueException Break the nullability of one property * @throws HibernateException error while getting Component values */ public void checkNullability( final Object[] values, final EntityPersister persister, final boolean isUpdate) throws HibernateException { /* * Typically when Bean Validation is on, we don't want to validate null values * at the Hibernate Core level. Hence the checkNullability setting. */ if ( checkNullability ) { /* * Algorithm * Check for any level one nullability breaks * Look at non null components to * recursively check next level of nullability breaks * Look at Collections contraining component to * recursively check next level of nullability breaks * * * In the previous implementation, not-null stuffs where checked * filtering by level one only updateable * or insertable columns. So setting a sub component as update="false" * has no effect on not-null check if the main component had good checkeability * In this implementation, we keep this feature. * However, I never see any documentation mentioning that, but it's for * sure a limitation. */ final boolean[] nullability = persister.getPropertyNullability(); final boolean[] checkability = isUpdate ? persister.getPropertyUpdateability() : persister.getPropertyInsertability(); final Type[] propertyTypes = persister.getPropertyTypes(); for ( int i = 0; i < values.length; i++ ) { if ( checkability[i] && values[i]!= LazyPropertyInitializer.UNFETCHED_PROPERTY ) { final Object value = values[i]; if ( !nullability[i] && value == null ) { //check basic level one nullablilty throw new PropertyValueException( "not-null property references a null or transient value", persister.getEntityName(), persister.getPropertyNames()[i] ); } else if ( value != null ) { //values is not null and is checkable, we'll look deeper final String breakProperties = checkSubElementsNullability( propertyTypes[i], value ); if ( breakProperties != null ) { throw new PropertyValueException( "not-null property references a null or transient value", persister.getEntityName(), buildPropertyPath( persister.getPropertyNames()[i], breakProperties ) ); } } } } } }
/** * Check nullability of the class persister properties * * @param values entity properties * @param persister class persister * @param isUpdate wether it is intended to be updated or saved * @throws org.hibernate.PropertyValueException Break the nullability of one property * @throws HibernateException error while getting Component values */ public void checkNullability( final Object[] values, final EntityPersister persister, final boolean isUpdate) throws PropertyValueException, HibernateException { /* * Algorithm * Check for any level one nullability breaks * Look at non null components to * recursively check next level of nullability breaks * Look at Collections contraining component to * recursively check next level of nullability breaks * * * In the previous implementation, not-null stuffs where checked * filtering by level one only updateable * or insertable columns. So setting a sub component as update="false" * has no effect on not-null check if the main component had good checkeability * In this implementation, we keep this feature. * However, I never see any documentation mentioning that, but it's for * sure a limitation. */ final boolean[] nullability = persister.getPropertyNullability(); final boolean[] checkability = isUpdate ? persister.getPropertyUpdateability() : persister.getPropertyInsertability(); final Type[] propertyTypes = persister.getPropertyTypes(); for ( int i = 0; i < values.length; i++ ) { if ( checkability[i] && values[i]!=LazyPropertyInitializer.UNFETCHED_PROPERTY ) { final Object value = values[i]; if ( !nullability[i] && value == null ) { //check basic level one nullablilty throw new PropertyValueException( "not-null property references a null or transient value", persister.getEntityName(), persister.getPropertyNames()[i] ); } else if ( value != null ) { //values is not null and is checkable, we'll look deeper String breakProperties = checkSubElementsNullability( propertyTypes[i], value ); if ( breakProperties != null ) { throw new PropertyValueException( "not-null property references a null or transient value", persister.getEntityName(), buildPropertyPath( persister.getPropertyNames()[i], breakProperties ) ); } } } } }
private void importBatch(List<Long> entityIds) throws PropertyValueException { List<T> entitiesList = Lists.newArrayList(); Map<Long, T> entitiesMap = Maps.newHashMapWithExpectedSize(entityIds.size()); preload(entityIds, getMigrationInformation()); try { MapSqlParameterSource entityIdsParameterSource = new MapSqlParameterSource(); entityIdsParameterSource.addValue(getMigrationInformation().getParameterIds(), entityIds); AutowireCapableBeanFactory autowire = applicationContext.getAutowireCapableBeanFactory(); RowMapper<?> rowMapper; Class<? extends AbstractResultRowMapper<?>> rowMapperClass = getMigrationInformation().getRowMapperClass(); if (AbstractMapResultRowMapper.class.isAssignableFrom(rowMapperClass)) { rowMapper = rowMapperClass.getConstructor(Map.class).newInstance(entitiesMap); } else if (AbstractListResultRowMapper.class.isAssignableFrom(rowMapperClass)) { rowMapper = rowMapperClass.getConstructor(List.class).newInstance(entitiesList); } else { throw new IllegalStateException(String.format("Type de rowmapper non reconnu %1$s", rowMapperClass.getSimpleName())); } autowire.autowireBean(rowMapper); autowire.initializeBean(rowMapper, rowMapper.getClass().getSimpleName()); prepareRowMapper(rowMapper, entityIds); getNamedParameterJdbcTemplate().query(getMigrationInformation().getSqlRequest(), entityIdsParameterSource, rowMapper); Collection<T> entities; if (AbstractMapResultRowMapper.class.isAssignableFrom(rowMapperClass)) { entities = entitiesMap.values(); } else if (AbstractListResultRowMapper.class.isAssignableFrom(rowMapperClass)) { entities = entitiesList; } else { throw new IllegalStateException(String.format("Type de rowmapper non reconnu %1$s", rowMapperClass.getSimpleName())); } for (T entity : entities) { if (getEntityService() != null) { getEntityService().create(entity); } else { entityManagerUtils.getEntityManager().persist(entity); } } } catch (RuntimeException | InstantiationException | IllegalAccessException | InvocationTargetException | NoSuchMethodException | ServiceException | SecurityServiceException e) { getLogger().error("Erreur lors de la persistence d'un paquet de {}. {} créations annulées.", getMigrationInformation().getEntityClass().getSimpleName(), entityIds.size(), e); ProcessorMonitorContext.get().getDoneItems().addAndGet(-1 * entityIds.size()); } }
public static void rethrowJdbcAsDatastoreAndConstraintAsItself( final HibernateException he, final Log log, final String message, final int logErrorMask ) throws DatastoreException, MAConstraintViolationException { final String internalMess = concMess( message, he ); if (he instanceof JDBCConnectionException || he instanceof GenericJDBCException || he instanceof SQLGrammarException) { if ((logErrorMask & JDBC_IS_ERROR) != 0) { log.error( internalMess, he ); } throw new DatastoreException( internalMess, he ); } else if (he instanceof ConstraintViolationException) { if ((logErrorMask & CONSTRAINT_IS_ERROR) != 0) { log.error( internalMess, he ); } throw new MAConstraintViolationException( internalMess, he ); } else if (he instanceof LockAcquisitionException) { log.error( internalMess, he ); throw new DatastoreException( internalMess, he ); } else if (he instanceof QuerySyntaxException) { log.error( internalMess, he ); throw new DatastoreException( internalMess, he ); } else if (he instanceof IdentifierGenerationException) { log.error( internalMess, he ); throw new DatastoreException( internalMess, he ); } else if (he instanceof PropertyValueException) { log.error( internalMess, he ); throw new DatastoreException( internalMess, he ); } else { log.error( internalMess, he ); throw new DatastoreException( internalMess, he ); } }
@Test public void testPolicy() { final Identity ident = getOrCreateIdentity("anIdentity"); final Identity ident2 = baseSecurityManager.createAndPersistIdentity("gugus2", null, AUTHENTICATION_PROVIDER_OLAT, "uuu2", Encoder.encrypt("ppp")); final SecurityGroup secg = baseSecurityManager.createAndPersistSecurityGroup(); final SecurityGroup secg2 = baseSecurityManager.createAndPersistSecurityGroup(); baseSecurityManager.addIdentityToSecurityGroup(ident, secg); // resourceable type final OLATResourceable or1 = OresHelper.createOLATResourceableInstance("Forum", new Long("111")); // simulate some user gui clicks DBFactory.getInstance().closeSession(); // resourceable (type and key) final OLATResourceable or2 = OresHelper.createOLATResourceableInstance("Forum", new Long("123")); baseSecurityManager.createAndPersistPolicy(secg2, Constants.PERMISSION_ACCESS, or1); Policy policy = baseSecurityManager.createAndPersistPolicy(secg, "read", or2); // instance // resource assertNotNull(policy); assertNotNull(policy.getSecurityGroup()); assertNotNull(policy.getSecurityGroup().getKey()); assertTrue(policy.getSecurityGroup().getKey().equals(secg.getKey())); policy = baseSecurityManager.createAndPersistPolicy(secg, "read", or1); // type resource assertNotNull(policy); // assert we have instance access if we own the type policy assertTrue(baseSecurityManager.isIdentityPermittedOnResourceable(ident, "read", or2)); assertTrue(baseSecurityManager.isIdentityPermittedOnResourceable(ident, "read", or1)); assertFalse(baseSecurityManager.isIdentityPermittedOnResourceable(ident, "write", or1)); assertFalse(baseSecurityManager.isIdentityPermittedOnResourceable(ident2, "read", or1)); assertTrue(baseSecurityManager.isIdentityPermittedOnResourceable(ident, "read", or2)); assertFalse(baseSecurityManager.isIdentityPermittedOnResourceable(ident, "blub", or2)); DBFactory.getInstance().closeSession(); // test on deleting a securitygroup that is still referenced by a policy // (referential integrity) boolean r = true; try { baseSecurityManager.deleteSecurityGroup(secg); DBFactory.getInstance().closeSession(); } catch (final Exception e) { if (((DBRuntimeException) e).getCause() instanceof PropertyValueException) { r = true; } } DBFactory.getInstance().closeSession(); assertTrue(r); }
@Test public void testPolicy() { final Identity ident = getOrCreateIdentity("anIdentity"); final Identity ident2 = baseSecurityManager.createAndPersistIdentity("gugus2", null, AUTHENTICATION_PROVIDER_OLAT, "uuu2", Encoder.bCryptEncode("ppp")); final SecurityGroup secg = baseSecurityManager.createAndPersistSecurityGroup(); final SecurityGroup secg2 = baseSecurityManager.createAndPersistSecurityGroup(); baseSecurityManager.addIdentityToSecurityGroup(ident, secg); // resourceable type final OLATResourceable or1 = OresHelper.createOLATResourceableInstance("Forum", new Long("111")); // simulate some user gui clicks DBFactory.getInstance().closeSession(); // resourceable (type and key) final OLATResourceable or2 = OresHelper.createOLATResourceableInstance("Forum", new Long("123")); baseSecurityManager.createAndPersistPolicy(secg2, Constants.PERMISSION_ACCESS, or1); Policy policy = baseSecurityManager.createAndPersistPolicy(secg, "read", or2); // instance // resource assertNotNull(policy); assertNotNull(policy.getSecurityGroup()); assertNotNull(policy.getSecurityGroup().getKey()); assertTrue(policy.getSecurityGroup().getKey().equals(secg.getKey())); policy = baseSecurityManager.createAndPersistPolicy(secg, "read", or1); // type resource assertNotNull(policy); // assert we have instance access if we own the type policy assertTrue(baseSecurityManager.isIdentityPermittedOnResourceable(ident, "read", or2)); assertTrue(baseSecurityManager.isIdentityPermittedOnResourceable(ident, "read", or1)); assertFalse(baseSecurityManager.isIdentityPermittedOnResourceable(ident, "write", or1)); assertFalse(baseSecurityManager.isIdentityPermittedOnResourceable(ident2, "read", or1)); assertTrue(baseSecurityManager.isIdentityPermittedOnResourceable(ident, "read", or2)); assertFalse(baseSecurityManager.isIdentityPermittedOnResourceable(ident, "blub", or2)); DBFactory.getInstance().closeSession(); // test on deleting a securitygroup that is still referenced by a policy // (referential integrity) boolean r = true; try { baseSecurityManager.deleteSecurityGroup(secg); DBFactory.getInstance().closeSession(); } catch (final Exception e) { if (((DBRuntimeException) e).getCause() instanceof PropertyValueException) { r = true; } } DBFactory.getInstance().closeSession(); assertTrue(r); }
/** * Persist the changes to the entities in the SaveWorkState that is passed in. * This implements the abstract method in SaveProcessor. * After the completion of this method the saveWorkState.toSaveResult method may be called the will * return a SaveResult instance. * This method both persists the entities and creates the collection of KeyMappings, * which map the temporary keys to their real generated keys. * Note that this method sets session.FlushMode = FlushMode.MANUAL, so manual flushes are required. * @param saveWorkState */ @Override protected void saveChangesCore(SaveWorkState saveWorkState) { _session = _sessionFactory.openSession(); _session.setFlushMode(FlushMode.MANUAL); Transaction tx = _session.getTransaction(); boolean hasExistingTransaction = tx.isActive(); if (!hasExistingTransaction) tx.begin(); try { // Relate entities in the saveMap to other entities, so Hibernate can save the FK values. _fixer = new RelationshipFixer(saveWorkState, _session); _fixer.fixupRelationships(); // At this point all entities are hooked up but are not yet in the session. setSaveState(SaveState.AfterFixup); // Allow subclass to process entities before we save them saveWorkState.beforeSaveEntities(); List<EntityInfo> saveOrder = _fixer.sortDependencies(); processSaves(saveOrder); // At this point all entities are hooked up and in the session, and // all tempIds have been replaced with real ids. // Final chance to process entities before we save them - all entities // have been added to the session. setSaveState(SaveState.BeforeCommit); saveWorkState.beforeCommit(_session); _session.flush(); refreshFromSession(saveWorkState); if (!hasExistingTransaction) tx.commit(); // so that serialization of saveResult doesn't have issues. _fixer.removeRelationships(); } catch (EntityErrorsException eee) { if (tx.isActive()) tx.rollback(); throw eee; } catch (PropertyValueException pve) { // Hibernate can throw this if (tx.isActive()) tx.rollback(); EntityError entityError = new EntityError("PropertyValueException", pve.getEntityName(), null, pve.getPropertyName(), pve.getMessage()); throw new EntityErrorsException(entityError); } catch (Exception ex) { if (tx.isActive()) tx.rollback(); String msg = "Save exception: "; if (ex instanceof JDBCException) { msg += "SQLException: " + ((JDBCException) ex).getSQLException().getMessage(); } else { msg += ex.getMessage(); // most hibernate exceptions appear here } if (_possibleErrors.size() > 0) { msg += ". Possible errors: " + _possibleErrors.toString() + " "; } throw new RuntimeException(msg, ex); } finally { // if (!hasExistingTransaction) tx.Dispose(); _session.close(); } }
/** * Throws {@link org.hibernate.PropertyValueException} if there are any unresolved entity insert actions that depend * on non-nullable associations with a transient entity. This method should be called on completion of an operation * (after all cascades are completed) that saves an entity. * * @throws org.hibernate.PropertyValueException if there are any unresolved entity insert actions; * {@link org.hibernate.PropertyValueException#getEntityName()} and * {@link org.hibernate.PropertyValueException#getPropertyName()} will return the entity name and property value for * the first unresolved entity insert action. */ public void checkNoUnresolvedActionsAfterOperation() throws PropertyValueException { unresolvedInsertions.checkNoUnresolvedActionsAfterOperation(); }