0

I have a situation where I want to retrieve data, but before it is returned I want to change it without saving/persisting.

Here is my rest controller:

@RestController @RequestMapping("api/drawing-releases") @CrossOrigin("*") public class DrawingReleaseRestController { @Autowired private DrawingReleaseService service; @RequestMapping(method = RequestMethod.GET, value = "/{id}") @JsonView(View.DrawingReleaseView.class) public ResponseEntity<DrawingRelease> getWithId(@PathVariable int id) throws EntityNotFoundException { return new ResponseEntity<>(service.getByID(id),HttpStatus.OK); } } 

Here is the service implementation:

@Service public class DrawingReleaseServiceImpl extends DrawingFunctions implements DrawingReleaseService { /** * Logging Manager */ private static final Logger LOGGER=LogManager.getLogger(); @Autowired private DrawingReleaseRepository repository; @Override public DrawingRelease getByID(int id) throws EntityNotFoundException { Optional<DrawingRelease> opt = repository.findById(id); ... // manipulate the data here ... return opt.get(); } } 

Intitially I had the @Transactional annotation on the service. By removing that and not having it on the getByID method, I was first thinking that the session would open and close with the repository as indicated by the answer here.

That did not work, and I saw in the comments that "the session lasts for the entire duration of HTTP request processing." So, in the service I added

@Autowired private EntityManager em; 

and then in the getByID method I added

em.close(); 

before I made any changes. However, any changes I make are still being persisted.

Is there any way that I can make unsaved changes in my service layer? I suppose I could create some POJOs that mirror the entities (but aren't entities) and then copy the data and return those objects, but it doesn't seem like I should have to do something like that.

2 Answers 2

3

You say you want to get an Entity and then change the data and then return it without the entity being persisted but IMHO you shouldn't be using the entity for this. Why are you changing the data and what is the user going to do with it since it no longer represents what's in the database. What other changes are going to be made or what other assumptions (this is a database object) are going to be invalid?

If you are using a database object to derive a different object you should have a different class for this purpose. This is common and is called a Data Transfer Object (DTO) and they can be created from spring-data-jpa directly using projection. Your Dto object would take an entity as a constructor and fill out whatever properties it wants to from the entity. The Dto is not a persistent object so there are no issues around it being saved.

Much clearer and more understandable design and consistent with SOLID Principles and code structure.

Sign up to request clarification or add additional context in comments.

2 Comments

Maybe I should look into that more. As to why I want to do this--I have a drawing which can have a parts list. Any drawing can be used on a parts list for another drawing. On its own, a drawing can have parts 1, 2, and 3. If that drawing is part of another parts list, say at line 12, then I want it to show as 12, 12-1, 12-2, and 12-3. On another drawing, it might be on the parts list at line 15, so 15-1, 15-2, etc. I still want it to be saved in the database as items 1, 2, and 3, but shown as something else depending on the context.
Right, exactly. Separate your Problem Domain from your Persistence Domain. You don't want to modify information in the part because of how the drawing is using it, especially since every drawing would be using it differently. Check out some design patterns around this concept. I don't want to run off and start suggesting but definitely don't change the entity like that for that reason.
1

Yes, you can detach the entity from the persistence context: https://docs.oracle.com/javaee/7/api/javax/persistence/EntityManager.html#detach-java.lang.Object-

5 Comments

I detached the top level object, but it still persisted the lower level object. If I detach the lower level object, then I get a PersistentObjectException: detached entity passed to persist. Any ideas on that?
It looks like I'm getting the detached entity exception if I make a call to any repository, even if the repository is unrelated to the detached entity. Is that to be expected, and is there a way around that?
spring-data-jpa uses separate entity-managers for each repository and it manages the connection on its own so trying to get complicated with JPA and using spring-data-jpa is going to be an exercise in frustration. You should decide whether you want to use JPA or spring-data-jpa and focus your thinking around one or the other.
@K.Nicholas I'm not really following you. What would be the way to focus on one of them?
By top level and lower level I assume you mean parent and child? Or inheritance? It's not clear what your issue is since you are assuming we know your code. In short, spring-data-jpa is NOT jpa. It's an abstraction layer on top of jpa. I'm saying you need to understand that first before attempting to use spring-data-jpa incorrectly. Secondly, and I think more importantly, see answer below.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.