0

I have two entities, User and Operation and both entities have a join among them:

@Entity
public class User implements Serializable {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long userId;

    @Basic
    private String username;

    private String password;

    //Getters and Setters
}

@Entity
public class Operation implements Serializable {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long userId;

    @ManyToOne
    @JoinColumn(name = "user_id")
    User user;

    //Getters and Setters

}

Both Entities has a Repository too.

In my context the User entity is loadded in Session scope (HttpSession) when user (operator) has been logged. For each operation of user on system the app register that operation throug the Operation Repository.

My question is: How can I set User entity (getting on session) to operation before the register in Database?

Is possible override the Repository method?

EDIT 1:

The operation is saved through the web interface using HTTP POST method. I need to keep using the URI to save. Like:

URI: http: // localhost: 9874 / operations DATA: { "name": "operation-name" }

Thanks!

Community
  • 1
  • 1
Rafael Gomes Francisco
  • 2,193
  • 1
  • 15
  • 16

2 Answers2

3

You can create a pre save event handler in which you can set the association: you can then make a standard Spring Data Rest post to http://localhost:9874/operations and there is no need for a custom repository or controller.

http://docs.spring.io/spring-data/rest/docs/current/reference/html/#_writing_an_annotated_handler

@RepositoryEventHandler 
public class OperationEventHandler {

  @HandleBeforeSave
  public void handleOperationSave(Operation operation) {

  }
}

You say the user is stored in the session. I take it then you are not using Spring Security? If you are then you can get the current user using a static call:

SecurityContextHolder.getContext().getAuthentication();

otherwise you would need try and wire the HttpServletRequest to your event handler or use the static wrapper call as outlined in the answers to these questions:

Spring: how do I inject an HttpServletRequest into a request-scoped bean?

From this you can get the HttpSession.

The following shows wiring in the HttpServletRequest in exactly this scenario

Spring Data Rest - How to receive Headers in @RepositoryEventHandler

so your handler looks something like:

@RepositoryEventHandler 
public class OperationEventHandler {

  @Autowired
  private HttPServletRequest request;

  @HandleBeforeSave
  public void handleOperationSave(Operation operation) {

      User user = (User)request.getSession().getAttribute("userKey");
      operation.setUser(user); 
  }
}
Community
  • 1
  • 1
Alan Hay
  • 22,665
  • 4
  • 56
  • 110
  • Thanks Alan for good answer! Yes, i'm using SB Security. Sorry by doesn't say that... However, it's works very very well for me but i had add one thing... Was needed add annotation @Component in OperationEventHandler... Other thing, if I call .save() method from a repository manually this handler will be called too? – Rafael Gomes Francisco Apr 26 '17 at 03:32
  • 1
    No. It is SDR specific. If you don't need to inject anything you could use a standard JPA Event Listener which should work in both situations. http://www.objectdb.com/java/jpa/persistence/event – Alan Hay Apr 26 '17 at 08:09
0

Create a Custom Repository interface and write a implementation for that. for example.

public interface OperationRepositoryCustom {

  <T extends Operation> T saveCustomized(Operation operation);
}

Your implementation class would look like this.

public class OperationRepositoryImpl implements OperationRepositoryCustom{
  //You can autowire OperationRepository and other dependencies 

  @Autowired
  OperationRepository operationRepository;  

  @Override
  public Operation saveCustomized(Operation operation) {
      //put your code to update operation with user and save it by calling operationRepository.save(). 
  }
}

be aware of the naming convention, that Your custom implementation needs to have the same name like your repository + Impl. So if your repository interface is called OperationRepository, your Custom repository interface should be OperationRepositoryCustom and impl should be named OperationRepositoryImpl

Hope it helps

pvpkiran
  • 25,582
  • 8
  • 87
  • 134