Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix for issue 2211 #2289

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open

Conversation

ajaypaul-ibm
Copy link
Contributor

This PR contains a fix for issue #2211. The query now correctly includes all primary keys instead of just one.

@rfelcman
Copy link
Contributor

Sorry this fix can't be accepted as tests
EclipseLink PR build / Test on JDK 21 (pull_request) continuous-integration/jenkins/pr-merge are not passing please search test log outputs and modify Your code.

@ajaypaul-ibm ajaypaul-ibm force-pushed the 2211 branch 3 times, most recently from 1c8cdbf to a604ea8 Compare November 8, 2024 09:09
Copy link
Contributor

@rfelcman rfelcman left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm missing there tests. See mainly JUnitJPQLFunctionsTest.java or with this alias generation JUnitJPQLJakartaDataNoAliasTest.java

@ajaypaul-ibm
Copy link
Contributor Author

Hi @rfelcman
We have a few questions regarding this issue and have sent you an email with the details. Whenever you have a chance, could you kindly take a look?
Thank you very much for your time and help!

@ajaypaul-ibm
Copy link
Contributor Author

ajaypaul-ibm commented Nov 12, 2024

Hi @rfelcman I went through the mail. Is @IdClass is not supported in EclipseLink?

@rfelcman
Copy link
Contributor

Hi @rfelcman I went through the mail. Is @IdClass is not supported in EclipseLink?

Of course @IdClass it's supported in EclipseLink. Simply search code. You will find there a lot of examples in the tests. It just doesn't work with JPQL function ID() with multiple @Ids.

@ajaypaul-ibm
Copy link
Contributor Author

Hi @rfelcman I have send an mail can you please check it out ?

@ajaypaul-ibm
Copy link
Contributor Author

ajaypaul-ibm commented Dec 9, 2024

Hi @rfelcman
I was able to identify the location in EclipseLink where accessors are being processed. Specifically, when an entity with @IdClass is encountered, it seems to fall into the last else case here: MetadataDescriptor.java#L1542.

To handle this scenario, I attempted to add logic to check if the entity is using @IdClass. Below is an example of the extra else if block I added:

boolean isIdClass = accessor.getJavaClass().isAnnotationPresent("jakarta.persistence.IdClass", accessor.getClassAccessor());
else if (isIdClass) {
    if (accessor.isId()) {
        // Logic to handle @IdClass goes here
    }
}

However, I’m unsure of the specific logic that needs to go inside the if block to correctly process an entity with @IdClass.
Could you provide any hints or guidance on how to proceed?
Thank you for your help.

@rfelcman
Copy link
Contributor

Hi @rfelcman I was able to identify the location in EclipseLink where accessors are being processed. Specifically, when an entity with @IdClass is encountered, it seems to fall into the last else case here: MetadataDescriptor.java#L1542.

To handle this scenario, I attempted to add logic to check if the entity is using @IdClass. Below is an example of the extra else if block I added:

boolean isIdClass = accessor.getJavaClass().isAnnotationPresent("jakarta.persistence.IdClass", accessor.getClassAccessor());
else if (isIdClass) {
    if (accessor.isId()) {
        // Logic to handle @IdClass goes here
    }
}

However, I’m unsure of the specific logic that needs to go inside the if block to correctly process an entity with @IdClass. Could you provide any hints or guidance on how to proceed? Thank you for your help.

I think, that MetadataDescriptor.java is too generic. Try


And another area where fix should be targeted is org.eclipse.persistence.internal.jpa.metadata.accessors.mappings.EmbeddedIdAccessor or org.eclipse.persistence.internal.jpa.metadata.accessors.mappings.DerivedIdClassAccessor

@rfelcman
Copy link
Contributor

I'm missing Unit/integration test like
https://github.com/eclipse-ee4j/eclipselink/pull/2278/files

@rfelcman
Copy link
Contributor

@ajaypaul-ibm
Copy link
Contributor Author

Hi @rfelcman I have added unit test case . Please check

Copy link
Contributor

@rfelcman rfelcman left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

After resolve code comments please rebase this PR against latest master and update copyright years in the file headers.

String idAttributeName = getIdAttributeNameByField(descriptor.getMappings(), primaryKeyFields.get(0));
StateFieldPathExpression stateFieldPathExpression = new StateFieldPathExpression(expression.getParent(), variableText + "." + idAttributeName);
expression.setStateFieldPathExpression(stateFieldPathExpression);
if (!isEmbeddable(descriptor.getMappings())) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe this part should be refactored into

        if (isEmbeddable(descriptor.getMappings())) {
            String idAttributeName = getIdAttributeNameByField(descriptor.getMappings(), primaryKeyFields.get(0));
            StateFieldPathExpression stateFieldPathExpression = new StateFieldPathExpression(
                    expression.getParent(), variableText + "." + idAttributeName);
            expression.setStateFieldPathExpression(stateFieldPathExpression);
            // Continue with created StateFieldPathExpression
            // It handle by ObjectBuilder booth @Id/primary key types (simple/composite)
            expression.getStateFieldPathExpression().accept(this);
        } else {
            for (DatabaseField primaryKeyField : primaryKeyFields) {
                String idAttributeName = getIdAttributeNameByField(descriptor.getMappings(), primaryKeyField);
                StateFieldPathExpression stateFieldPathExpression = new StateFieldPathExpression(
                        expression.getParent(), variableText + "." + idAttributeName);
                expression.setStateFieldPathExpression(stateFieldPathExpression);
                // Continue with created StateFieldPathExpression
                // It handle by ObjectBuilder booth @Id/primary key types (simple/composite)
                expression.getStateFieldPathExpression().accept(this);
            }
        }

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Another comment: Maybe mentioned code should be optimized to remove some duplicitous calls.

@@ -630,7 +631,7 @@ private void visitAbstractSelectClause(AbstractSelectClause expression) {
multipleSelects = false;
expression.getSelectExpression().accept(this);

if (multipleSelects) {
if (multipleSelects || (expression.getSelectExpression() instanceof IdExpression)) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(expression.getSelectExpression() instanceof IdExpression) is not correct pattern in this context. There should be new method with

    @Override
    public void visit(IdExpression expression) {
        multipleSelects = true;
        ...
    }

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@rfelcman What should be the content of this method ?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't know, check other public void visit( as examples.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@rfelcman Do you mean to check whether the expression is an instance of IdExpression inside visit() method ?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@rfelcman Do you mean to check whether the expression is an instance of IdExpression inside visit() method ?

Yes. Main reason is eliminate || (expression.getSelectExpression() instanceof IdExpression) by new public void visit(IdExpression expression) { method which is called automaticaly by visitor pattern.

.getResultList();

// Ensure the result size is greater than 0
assertTrue("The result size should be greater than 0", !keys.isEmpty());
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This test is not enough. Please add there asserts for a values.

@ajaypaul-ibm
Copy link
Contributor Author

@rfelcman Shall I make the changes and update the PR ?

@rfelcman
Copy link
Contributor

@rfelcman Shall I make the changes and update the PR ?

Yes this is why PR technology exists plus hooked test calls which will verify modified code.

@rfelcman
Copy link
Contributor

I don't see any changes in the code -> no any reason to review it again.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants