Quantcast

keyProperty and final fields

classic Classic list List threaded Threaded
7 messages Options
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

keyProperty and final fields

Chad Retz
SQL map XML:

<insert id="addFooBar" parameterType="Foo" useGeneratedKeys="true"
keyProperty="bar.id">
    INSERT INTO Bar (Name)
    VALUES (#{bar.name})
</insert>

Bar:

class Bar {
    private Long id;
    private String name;

    //getters and setters of course...
}

Foo:

class Foo {
    private Bar bar;

    public Foo(Bar bar) {
        this.bar = bar;
    }

    //getter for bar
}

This populates the Bar.id field as would be expected. But simply
making the bar field final in Foo like so:

class Foo {
    private final Bar bar;

    public Foo(Bar bar) {
        this.bar = bar;
    }

    //getter for bar
}

does not populate bar.id. Is this a simple bug or is there something
obvious I am not aware of? It's not like MyBatis needs Foo.bar to be
mutable.

Thanks
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: keyProperty and final fields

Chad Retz
Can someone at least tell me if this is by intention before I open an
issue? It is easy to workaround of course by making the field non-
final, but it's worth fixing.

On Sep 30, 2:46 pm, Chad Retz <[hidden email]> wrote:

> SQL map XML:
>
> <insert id="addFooBar" parameterType="Foo" useGeneratedKeys="true"
> keyProperty="bar.id">
>     INSERT INTO Bar (Name)
>     VALUES (#{bar.name})
> </insert>
>
> Bar:
>
> class Bar {
>     private Long id;
>     private String name;
>
>     //getters and setters of course...
>
> }
>
> Foo:
>
> class Foo {
>     private Bar bar;
>
>     public Foo(Bar bar) {
>         this.bar = bar;
>     }
>
>     //getter for bar
>
> }
>
> This populates the Bar.id field as would be expected. But simply
> making the bar field final in Foo like so:
>
> class Foo {
>     private final Bar bar;
>
>     public Foo(Bar bar) {
>         this.bar = bar;
>     }
>
>     //getter for bar
>
> }
>
> does not populate bar.id. Is this a simple bug or is there something
> obvious I am not aware of? It's not like MyBatis needs Foo.bar to be
> mutable.
>
> Thanks
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: keyProperty and final fields

Clinton Begin
Administrator
On a non-constructor select, I would say it's normal. But are you saying that given an instance of Bar with a final id field, using it in an insert statement doesn't populate the SQL parameter?

Clinton

On Tue, Oct 5, 2010 at 1:47 PM, Chad Retz <[hidden email]> wrote:
Can someone at least tell me if this is by intention before I open an
issue? It is easy to workaround of course by making the field non-
final, but it's worth fixing.

On Sep 30, 2:46 pm, Chad Retz <[hidden email]> wrote:
> SQL map XML:
>
> <insert id="addFooBar" parameterType="Foo" useGeneratedKeys="true"
> keyProperty="bar.id">
>     INSERT INTO Bar (Name)
>     VALUES (#{bar.name})
> </insert>
>
> Bar:
>
> class Bar {
>     private Long id;
>     private String name;
>
>     //getters and setters of course...
>
> }
>
> Foo:
>
> class Foo {
>     private Bar bar;
>
>     public Foo(Bar bar) {
>         this.bar = bar;
>     }
>
>     //getter for bar
>
> }
>
> This populates the Bar.id field as would be expected. But simply
> making the bar field final in Foo like so:
>
> class Foo {
>     private final Bar bar;
>
>     public Foo(Bar bar) {
>         this.bar = bar;
>     }
>
>     //getter for bar
>
> }
>
> does not populate bar.id. Is this a simple bug or is there something
> obvious I am not aware of? It's not like MyBatis needs Foo.bar to be
> mutable.
>
> Thanks

Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: keyProperty and final fields

Chad Retz
Sorry it took so long to respond. Yes, on a simple insert, the auto
generated key only gets populated in the sub-object if the object (not
the field inside the sub-object obviously) is not final. So, it's
whether Bar is final or not that affects Bar.id being populated w/ the
auto generated key. It seems strange and I wonder whether it's an OGNL
issue w/ populating fields inside sub-objects declared as final.

On Oct 5, 3:23 pm, Clinton Begin <[hidden email]> wrote:

> On a non-constructor select, I would say it's normal. But are you saying
> that given an instance of Bar with a final id field, using it in an insert
> statement doesn't populate the SQL parameter?
>
> Clinton
>
> On Tue, Oct 5, 2010 at 1:47 PM, Chad Retz <[hidden email]> wrote:
> > Can someone at least tell me if this is by intention before I open an
> > issue? It is easy to workaround of course by making the field non-
> > final, but it's worth fixing.
>
> > On Sep 30, 2:46 pm, Chad Retz <[hidden email]> wrote:
> > > SQL map XML:
>
> > > <insert id="addFooBar" parameterType="Foo" useGeneratedKeys="true"
> > > keyProperty="bar.id">
> > >     INSERT INTO Bar (Name)
> > >     VALUES (#{bar.name})
> > > </insert>
>
> > > Bar:
>
> > > class Bar {
> > >     private Long id;
> > >     private String name;
>
> > >     //getters and setters of course...
>
> > > }
>
> > > Foo:
>
> > > class Foo {
> > >     private Bar bar;
>
> > >     public Foo(Bar bar) {
> > >         this.bar = bar;
> > >     }
>
> > >     //getter for bar
>
> > > }
>
> > > This populates the Bar.id field as would be expected. But simply
> > > making the bar field final in Foo like so:
>
> > > class Foo {
> > >     private final Bar bar;
>
> > >     public Foo(Bar bar) {
> > >         this.bar = bar;
> > >     }
>
> > >     //getter for bar
>
> > > }
>
> > > does not populate bar.id. Is this a simple bug or is there something
> > > obvious I am not aware of? It's not like MyBatis needs Foo.bar to be
> > > mutable.
>
> > > Thanks
>
>
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: keyProperty and final fields

Clinton Begin
Administrator
Ohhh.... somehow I didn't fully understand until you responded. 

But absolutely, if it's the autogenerated value you're looking for on the insert, there's no way it can be "re-set" if it's final.  

Final fields are not settable, via reflection or otherwise.  Period.  So you'll have to make it mutable.

Clinton

On Mon, Oct 11, 2010 at 12:52 PM, Chad Retz <[hidden email]> wrote:
Sorry it took so long to respond. Yes, on a simple insert, the auto
generated key only gets populated in the sub-object if the object (not
the field inside the sub-object obviously) is not final. So, it's
whether Bar is final or not that affects Bar.id being populated w/ the
auto generated key. It seems strange and I wonder whether it's an OGNL
issue w/ populating fields inside sub-objects declared as final.

On Oct 5, 3:23 pm, Clinton Begin <[hidden email]> wrote:
> On a non-constructor select, I would say it's normal. But are you saying
> that given an instance of Bar with a final id field, using it in an insert
> statement doesn't populate the SQL parameter?
>
> Clinton
>
> On Tue, Oct 5, 2010 at 1:47 PM, Chad Retz <[hidden email]> wrote:
> > Can someone at least tell me if this is by intention before I open an
> > issue? It is easy to workaround of course by making the field non-
> > final, but it's worth fixing.
>
> > On Sep 30, 2:46 pm, Chad Retz <[hidden email]> wrote:
> > > SQL map XML:
>
> > > <insert id="addFooBar" parameterType="Foo" useGeneratedKeys="true"
> > > keyProperty="bar.id">
> > >     INSERT INTO Bar (Name)
> > >     VALUES (#{bar.name})
> > > </insert>
>
> > > Bar:
>
> > > class Bar {
> > >     private Long id;
> > >     private String name;
>
> > >     //getters and setters of course...
>
> > > }
>
> > > Foo:
>
> > > class Foo {
> > >     private Bar bar;
>
> > >     public Foo(Bar bar) {
> > >         this.bar = bar;
> > >     }
>
> > >     //getter for bar
>
> > > }
>
> > > This populates the Bar.id field as would be expected. But simply
> > > making the bar field final in Foo like so:
>
> > > class Foo {
> > >     private final Bar bar;
>
> > >     public Foo(Bar bar) {
> > >         this.bar = bar;
> > >     }
>
> > >     //getter for bar
>
> > > }
>
> > > does not populate bar.id. Is this a simple bug or is there something
> > > obvious I am not aware of? It's not like MyBatis needs Foo.bar to be
> > > mutable.
>
> > > Thanks
>
>

Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: keyProperty and final fields

Clinton Begin
Administrator
PS:  This depends on the JVM version... but it's a bit unclear.  JSR 133 seems to have changed it so that we might be able to reliably change final fields... but I really don't think it's a good idea anyway.

Clinton

On Mon, Oct 11, 2010 at 12:55 PM, Clinton Begin <[hidden email]> wrote:
Ohhh.... somehow I didn't fully understand until you responded. 

But absolutely, if it's the autogenerated value you're looking for on the insert, there's no way it can be "re-set" if it's final.  

Final fields are not settable, via reflection or otherwise.  Period.  So you'll have to make it mutable.

Clinton


On Mon, Oct 11, 2010 at 12:52 PM, Chad Retz <[hidden email]> wrote:
Sorry it took so long to respond. Yes, on a simple insert, the auto
generated key only gets populated in the sub-object if the object (not
the field inside the sub-object obviously) is not final. So, it's
whether Bar is final or not that affects Bar.id being populated w/ the
auto generated key. It seems strange and I wonder whether it's an OGNL
issue w/ populating fields inside sub-objects declared as final.

On Oct 5, 3:23 pm, Clinton Begin <[hidden email]> wrote:
> On a non-constructor select, I would say it's normal. But are you saying
> that given an instance of Bar with a final id field, using it in an insert
> statement doesn't populate the SQL parameter?
>
> Clinton
>
> On Tue, Oct 5, 2010 at 1:47 PM, Chad Retz <[hidden email]> wrote:
> > Can someone at least tell me if this is by intention before I open an
> > issue? It is easy to workaround of course by making the field non-
> > final, but it's worth fixing.
>
> > On Sep 30, 2:46 pm, Chad Retz <[hidden email]> wrote:
> > > SQL map XML:
>
> > > <insert id="addFooBar" parameterType="Foo" useGeneratedKeys="true"
> > > keyProperty="bar.id">
> > >     INSERT INTO Bar (Name)
> > >     VALUES (#{bar.name})
> > > </insert>
>
> > > Bar:
>
> > > class Bar {
> > >     private Long id;
> > >     private String name;
>
> > >     //getters and setters of course...
>
> > > }
>
> > > Foo:
>
> > > class Foo {
> > >     private Bar bar;
>
> > >     public Foo(Bar bar) {
> > >         this.bar = bar;
> > >     }
>
> > >     //getter for bar
>
> > > }
>
> > > This populates the Bar.id field as would be expected. But simply
> > > making the bar field final in Foo like so:
>
> > > class Foo {
> > >     private final Bar bar;
>
> > >     public Foo(Bar bar) {
> > >         this.bar = bar;
> > >     }
>
> > >     //getter for bar
>
> > > }
>
> > > does not populate bar.id. Is this a simple bug or is there something
> > > obvious I am not aware of? It's not like MyBatis needs Foo.bar to be
> > > mutable.
>
> > > Thanks
>
>


Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: keyProperty and final fields

Chad Retz
Sorry to respond to this so late. I'm not attempting to reset a final
field. I'm trying to reset a non-final field inside of an object who
itself is a final field of an object. So setting "bar.id" in my
example is setting the id field in the bar object (and field) in the
Foo object (basically Foo.bar.id). The bar object is final, but I
don't want that set. I want one of its fields set. Hopefully this
makes sense.

Chad

On Oct 11, 1:58 pm, Clinton Begin <[hidden email]> wrote:

> PS:  This depends on the JVM version... but it's a bit unclear.  JSR 133
> seems to have changed it so that we might be able to reliably change final
> fields... but I really don't think it's a good idea anyway.
>
> Clinton
>
> On Mon, Oct 11, 2010 at 12:55 PM, Clinton Begin <[hidden email]>wrote:
>
> > Ohhh.... somehow I didn't fully understand until you responded.
>
> > But absolutely, if it's the autogenerated value you're looking for on the
> > insert, there's no way it can be "re-set" if it's final.
>
> > Final fields are not settable, via reflection or otherwise.  Period.  So
> > you'll have to make it mutable.
>
> > Clinton
>
> > On Mon, Oct 11, 2010 at 12:52 PM, Chad Retz <[hidden email]> wrote:
>
> >> Sorry it took so long to respond. Yes, on a simple insert, the auto
> >> generated key only gets populated in the sub-object if the object (not
> >> the field inside the sub-object obviously) is not final. So, it's
> >> whether Bar is final or not that affects Bar.id being populated w/ the
> >> auto generated key. It seems strange and I wonder whether it's an OGNL
> >> issue w/ populating fields inside sub-objects declared as final.
>
> >> On Oct 5, 3:23 pm, Clinton Begin <[hidden email]> wrote:
> >> > On a non-constructor select, I would say it's normal. But are you saying
> >> > that given an instance of Bar with a final id field, using it in an
> >> insert
> >> > statement doesn't populate the SQL parameter?
>
> >> > Clinton
>
> >> > On Tue, Oct 5, 2010 at 1:47 PM, Chad Retz <[hidden email]> wrote:
> >> > > Can someone at least tell me if this is by intention before I open an
> >> > > issue? It is easy to workaround of course by making the field non-
> >> > > final, but it's worth fixing.
>
> >> > > On Sep 30, 2:46 pm, Chad Retz <[hidden email]> wrote:
> >> > > > SQL map XML:
>
> >> > > > <insert id="addFooBar" parameterType="Foo" useGeneratedKeys="true"
> >> > > > keyProperty="bar.id">
> >> > > >     INSERT INTO Bar (Name)
> >> > > >     VALUES (#{bar.name})
> >> > > > </insert>
>
> >> > > > Bar:
>
> >> > > > class Bar {
> >> > > >     private Long id;
> >> > > >     private String name;
>
> >> > > >     //getters and setters of course...
>
> >> > > > }
>
> >> > > > Foo:
>
> >> > > > class Foo {
> >> > > >     private Bar bar;
>
> >> > > >     public Foo(Bar bar) {
> >> > > >         this.bar = bar;
> >> > > >     }
>
> >> > > >     //getter for bar
>
> >> > > > }
>
> >> > > > This populates the Bar.id field as would be expected. But simply
> >> > > > making the bar field final in Foo like so:
>
> >> > > > class Foo {
> >> > > >     private final Bar bar;
>
> >> > > >     public Foo(Bar bar) {
> >> > > >         this.bar = bar;
> >> > > >     }
>
> >> > > >     //getter for bar
>
> >> > > > }
>
> >> > > > does not populate bar.id. Is this a simple bug or is there
> >> something
> >> > > > obvious I am not aware of? It's not like MyBatis needs Foo.bar to be
> >> > > > mutable.
>
> >> > > > Thanks
>
>
Loading...