HI!  No, I have not committed any portion of this at all, and do not indent
to any time this week.  I need to do a code review, and discuss this with
team mates.  I might want to commit this next week if all goes well with
the code review, would that work?

Thanks,

Heath

On Sun, Feb 14, 2016 at 3:27 AM, Mark Struberg <[email protected]> wrote:

> Heath, did you already commit parts of that? Is this feature now half-in
> or are you just working on it?
> If not, do you have a timeframe?
> Should we wait for it or can I go on with the release (and do another
> 2.4.2 a month later)?
>
> txs and LieGrue,
> strub
>
>
>
> > Am 12.02.2016 um 05:18 schrieb Heath Thomann (JIRA) <[email protected]>:
> >
> >
> >    [
> https://issues.apache.org/jira/browse/OPENJPA-2631?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=15144007#comment-15144007
> ]
> >
> > Heath Thomann commented on OPENJPA-2631:
> > ----------------------------------------
> >
> > For posterity's sake, and given this was a complex issue to debug/fix,
> I'd like to document some of the steps I took to debug this....sorry, it
> might be a bit awkward but better than nothing should I/we ever need to
> revisit this issue.  :)  This debug assumes knowledge of the attached
> test.  The issue occurs here:
> >
> >    public void appendTo(Select sel, ExpContext ctx, ExpState state,
> >        SQLBuffer sql, int index) {
> >        ParamExpState pstate = (ParamExpState) state;
> >        if (pstate.otherLength > 1)
> >            sql.appendValue(((Object[]) pstate.sqlValue)[index],
> <------ line 149
> >                pstate.getColumn(index), this);
> >
> > Note that I added a system out in this 'if' block, then I ran the
> OpenJPA JUnit bucket.  I found that ONLY one test method ever hits this
> 'if' statement.....so it seems this 'if' block is very rarely executed
> (which I suppose explains why we have yet to see this issue).  Anyway, in
> the debugger I notice that 'pstate.otherLength' was 2, which is the size of
> the number of columns in my PK (SubjectKey), yet 'pstate.sqlValue'
> contained 'Subject' (the entity in the attacked test).  So I suspected that
> this code expected to get at the column values of the PK (SubjectKey), not
> the entity (Subject) itself.  So I walked backwards to see where
> 'otherLength' and 'sqlValue' where set.  I found that here in Param:
> >
> >    public void calculateValue(Select sel, ExpContext ctx, ExpState state,
> >        Val other, ExpState otherState) {
> >        super.calculateValue(sel, ctx, state, other, otherState);
> >        Object val = getValue(ctx.params);
> >        ParamExpState pstate = (ParamExpState) state;
> >        if (other != null && !_container) {
> >            pstate.sqlValue = other.toDataStoreValue(sel, ctx,
> otherState, val);
> >            pstate.otherLength = other.length(sel, ctx, otherState);
> >
> >
> > other.toDataStoreValue calls to ClassMapping.toDataStoreValue....here is
> that code (note the javadoc):
> >
> >    /**
> >     * Return the given column value(s) for the given object. The given
> >     * columns will be primary key columns of this mapping, but may be in
> >     * any order. If there is only one column, return its value. If there
> >     * are multiple columns, return an object array of their values, in
> the
> >     * same order the columns are given.
> >     */
> >    public Object toDataStoreValue(Object obj, Column[] cols, JDBCStore
> store) {
> >        Object ret = (cols.length == 1) ? null : new Object[cols.length];
> >
> >        // in the past we've been lenient about being able to translate
> objects
> >        // from other persistence contexts, so try to get sm directly from
> >        // instance before asking our context
> >        OpenJPAStateManager sm;
> >        if (ImplHelper.isManageable(obj)) {
> >               PersistenceCapable pc =
> ImplHelper.toPersistenceCapable(obj,
> >                    getRepository().getConfiguration());
> >            sm = (OpenJPAStateManager) pc.pcGetStateManager();
> >            if (sm == null) {
> >               ret = getValueFromUnmanagedInstance(obj, cols, true);
> >
> >
> > In my scenario 'sm' is null so we take the block to 'ret =
> getValueFromUnmanagedInstance'.  Again, note that I added a system out in
> this 'if' block, then I ran the OpenJPA test bucket and only one test
> method ever hits this 'if' statement (again, nearly dead code).  :)  When I
> ran my test, I notice that 'ret' is assigned 'Subject' after a call to
> 'getValueFromUnmanagedInstance, not the PK values as promised by the
> javadoc listed above.  So I set off to figure out how to get the PKs
> columns from Subject, and their values.  To do this, I thought "if we
> execute this query as a 'find' instead, how does that path extract the PK
> columns and values."  When running in a debugger, I saw that we go into
> this code in SelectImpl.where:
> >
> > join = mapping.assertJoinable(toCols[i]);
> > val = pks[mapping.getField(join.getFieldIndex()).
> >    getPrimaryKeyIndex()];
> > val = join.getJoinValue(val, toCols[i], store);
> >
> > For a finder, this is where we get the PK of SubjectKey and get its
> individual values of the SubjectKey.....this is where I took my idea for
> the fix attached to this JIRA.
> >
> > Thanks,
> >
> > Heath
> >
> >
> >> ClassCastException occurs when an equals comparison query is executed
> on an entity with an @EmbeddedId that contains more than one field.
> >>
> -----------------------------------------------------------------------------------------------------------------------------------------
> >>
> >>                Key: OPENJPA-2631
> >>                URL: https://issues.apache.org/jira/browse/OPENJPA-2631
> >>            Project: OpenJPA
> >>         Issue Type: Bug
> >>         Components: criteria, query, sql
> >>   Affects Versions: 2.1.2, 2.2.3, 2.4.1
> >>           Reporter: Heath Thomann
> >>           Assignee: Heath Thomann
> >>        Attachments: OPENJPA-2631-2.1.x.patch, OPENJPA-2631-2.1.x.test
> >>
> >>
> >> Take the following entity:
> >> @Entity
> >> public class Subject implements Serializable {
> >>      @EmbeddedId
> >>      private SubjectKey key;
> >> .......
> >> Where SubjectKey is as follows:
> >> @Embeddable
> >> public class SubjectKey implements Serializable {
> >>      private Integer subjectNummer;
> >>      private String subjectTypeCode;
> >> ......
> >> As you can see we have a composite primary key.  With this, take this
> query:
> >> TypedQuery<Subject> query = em.createQuery("select s from Subject s
> where s = :subject", Subject.class);
> >> query.setParameter("subject", s);
> >> Subject s2 = query.getSingleResult();
> >> This query will yield the following exception:
> >> java.lang.ClassCastException:
> org.apache.openjpa.persistence.embed.compositepk.SubjectKey cannot be cast
> to
> >> [Ljava.lang.Object;]
> >> at org.apache.openjpa.jdbc.kernel.exps.Param.appendTo(Param.java:149)
> >> If we execute a corresponding 'em.find' of Subject, this exception
> doesn't occur.  Furthermore, if you execute the same query for an entity
> with an @EmbeddedId that only contains one field, all will work as
> expected.  The issue here is with an equals query where the entity contains
> an @EmbeddableId with more than two fields.
> >> While investigating/debugging this issue, I've found further issues
> when creating the query using CriteriaBuilder; both with an @Embeddable and
> @IdClass composite PKs.  I will leave it as an exercise for the reader to
> view the attached test case to see how each issue can occur.  Each test
> method details what issue it recreated before the fixes to this issue.  I'm
> also attaching a patch with a proposed fix for the issues.
> >> Thanks,
> >> Heath Thomann
> >
> >
> >
> > --
> > This message was sent by Atlassian JIRA
> > (v6.3.4#6332)
>
>

Reply via email to