Announcement Announcement Module
Collapse
No announcement yet.
Override save methods of SimpleJPaRepository Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Override save methods of SimpleJPaRepository

    I need to override the default save methods of SimpleJPaRepository. However I ran into an issue with generics and the fact that the save methods use <S extends T> as return type instead of just T.

    Here the overridden method:

    Code:
    public class ChemicalStructureRepositoryImpl<T extends ChemicalStructure>
            extends QueryDslJpaRepository<T, Long>
            implements ChemicalStructureRepository<T> {
    
        //...
    
        @Override
        @Transactional
        public <S extends T> S save(S structure) {
            QChemicalStructure qStructure = QChemicalStructure.chemicalStructure; //querydsl
            BooleanExpression hasSameSructureKey =
                    qStructure.structureKey.eq(structure.getStructureKey());
    
            T result = super.findOne(hasSameSructureKey);
            if (result == null) {
                structure.reset();
                em.persist(structure);
                return structure;
            } else {
                return super.save(result); // compiler error
            }
        }
    Compiler error:

    incompatible types
    required: S
    found: T
    where T,S are type-variables:
    T extends ChemicalStructure declared in class ChemicalStructureRepositoryImpl
    S extends T declared in method <S>save(S)
    First what I want to achieve with this: A ChemicalStructure is immutable. It's data can't change. So let's say user loads entity with id 1 and changes it's data. the entity with id one must stay the same. So therefore I check using unique "Business key" whether an entity identical to the changed with id 1 exist. If yes, use that one, if no create a new one.

    I created the reset method because just calling new T(args) won't work as it will have type T instead of S. reset sets id = null and any metadata fields (created, modified,...).

    however as you can see I still get compiler error when calling em.merge as also here T is returned instead of S. The only solution is see is to manually cast to S and make a doc comment you should only use T or else exception. But that seems extremely ugly?

    I could just leave it be and do the logic in a service layer? Problem is that it then can very easily be circumvented which is problematic. Example: You have a boxes of tools. Now you realize that in one box at a certain space you accidentally entered a hammer instead of a screwdriver into the system. Now you change the hammer to a screwdriver. But of course you don't want the actual hammer entity to become a screwdriver and hence all boxes using a hammer now contain a screwdriver. I want to do exactly what I outlined above.

    Alternative suggestion? What am I missing or how else can I override save?
    Last edited by beginner_; Oct 25th, 2012, 01:25 AM.
Working...
X