4

In Spring data neo44 we have just repository.save(entity), but for example when my UserEntity's property(email) changed, i dont know how to update the same.

I tried also with neo4j template, but save entity with existing node id caused the below rollback.

org.springframework.dao.InvalidDataAccessApiUsageException: New value must be a Set, was: class java.util.ArrayList; nested exception is java.lang.IllegalArgumentException: New value must be a Set, was: class java.util.ArrayList
    at org.springframework.data.neo4j.support.Neo4jExceptionTranslator.translateExceptionIfPossible(Neo4jExceptionTranslator.java:43)
    at org.springframework.dao.support.ChainedPersistenceExceptionTranslator.translateExceptionIfPossible(ChainedPersistenceExceptionTranslator.java:58)
    at org.springframework.dao.support.DataAccessUtils.translateIfNecessary(DataAccessUtils.java:213)
    at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:163)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
    at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:204)

How we can update node or nodeentity?

public void updateUserNode(UserEntity user) {  
    try{ 
    UserEntity updatedUser = this.getUserByUserId(user.getUserId());//finding node with user id///
    updatedUser.setEmail(user.getEmail());
    updatedUser.setImageId(user.getImageId());
    updatedUser.setFirstname(user.getFirstname());
    updatedUser.setLastname(user.getLastname());
    //System.out.println("Deleting ");
    //userRepository.delete(del);
    System.out.println("UPDATING ");     
    // with existing Id, you can not save it again/, or update
    updatedUser = userRepository.save(updatedUser);
    }catch(Exception e){
      e.printStackTrace();
    }
    //return 
  }
Unni Kris
  • 3,081
  • 4
  • 35
  • 57
Armen Arzumanyan
  • 1,939
  • 3
  • 30
  • 56

3 Answers3

3

You have to embed the .save() within a transaction.

As an example:

final org.neo4j.graphdb.Transaction tx = this.neoTemplate.getGraphDatabaseService().beginTx();
try {
    updatedUser = userRepository.save(updatedUser);
    tx.success();
} finally {
    tx.finish();
}
Markus Schulte
  • 4,171
  • 3
  • 47
  • 58
  • Do you mean what save also can update entity if it have graph id? – Armen Arzumanyan Mar 18 '13 at 13:39
  • Do you mean what entity by save also can be updated when passed graph id? Actually Spring takes transaction, my spring bean is transactional and success do saving. – Armen Arzumanyan Mar 18 '13 at 13:41
  • I don't understand your question (I am using spring-data-neo4j in standaloen mode, so without spring framework). Anyhow, have you looked at http://static.springsource.org/spring-data/data-neo4j/docs/2.2.0.RELEASE/reference/htmlsingle/#d0e454 already? There are examples for using spring-data-neo4j – Markus Schulte Mar 18 '13 at 15:38
  • 1
    Yes I read a documentation, but my problem is what where you already created entities and relations and when user change his email which is the entity property, how can I update @Node entity. save operation fails. – Armen Arzumanyan Mar 19 '13 at 06:10
2

In your UserEntity domain object, are you storing any relationships? Be sure they are declared as Set<T> and not as Iterable<T>:

From: http://static.springsource.org/spring-data/data-graph/snapshot-site/reference/html/#reference:programming_model:relationships:relatedto

"It is also possible to have fields that reference a set of node entities (1:N). These fields come in two forms, modifiable or read-only. Modifiable fields are of the type Set, and read-only fields are Iterable, where T is a @NodeEntity-annotated class."

I suspect your default constructor is instantiating an ArrayList...

Community
  • 1
  • 1
Matt Wielbut
  • 2,584
  • 25
  • 29
  • NodeEntity public class UserEntity implements Serializable { private static final long serialVersionUID = 1L; public static final String FRIEND = "FRIEND"; GraphId private Long id; Indexed(unique = true) private Long userId; private String email; Fetch RelatedTo(elementClass = UserEntity.class, type = FRIEND, direction = Direction.OUTGOING) private List friendsList; – Armen Arzumanyan Mar 19 '13 at 21:11
  • I have only @Fetch @RelatedTo(elementClass = UserEntity.class, type = FRIEND, direction = Direction.OUTGOING) private List friendsList; – Armen Arzumanyan Mar 19 '13 at 21:12
  • Yes, that's your problem. Lists don't make sense in the context of relationship as they are always un-ordered in a graph. http://en.wikipedia.org/wiki/Graph_(mathematics)#Graph Please replace List with Set: `@Fetch @RelatedTo(elementClass = UserEntity.class, type = FRIEND, direction = Direction.OUTGOING) private Set friendsList;` – Matt Wielbut Mar 21 '13 at 09:34
  • Hi, Thanks, I replaced List to Set and all ok now, just in frontend I fill data from Set to ArrayList, because I need iterable type. Thanks – Armen Arzumanyan Mar 24 '13 at 19:31
1

Since you're using SDN you should not ever be in need to manually start/commit any Transactions.

Suppose your User class looks like this

@NodeEntity(label="User)
public class User extends DomainObject{
    @Property(name = "email")
    private String email;

    //getter and setter
}

and your UserRepository is similar to this:

public interface UserRepository extends GraphRepository<User> {

    //maybe this is already right at hand by SDN and thus redundant?
    @Query("MATCH (u:User {email:{email}}")
    public User findByEmail(@Param("email") String email)
}

Then you may use a @Transactional on a UserService class:

@Component
@Transactional
public class UserService {

    @Autowired
    private UserRepository userRepository;

    public void updateEmail(String email) {
        User user = userRepository.findByEmail(email);
        if (user == null) return; //or throw...
        user.setEmail(email);
        userRepository.save(user);
    }
}
Christoph Möbius
  • 1,352
  • 1
  • 12
  • 18