-->
These old forums are deprecated now and set to read-only. We are waiting for you on our new forums!
More modern, Discourse-based and with GitHub/Google/Twitter authentication built-in.

All times are UTC - 5 hours [ DST ]



Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 4 posts ] 
Author Message
 Post subject: first select causes next select to change behavior
PostPosted: Wed Jun 25, 2008 2:46 am 
Senior
Senior

Joined: Sun Jun 11, 2006 10:41 am
Posts: 164
Hibernate version:
3.2.6

Test Code
Code:
        Device d;
        List<Device> list;
        em.createQuery("select cfg from DeviceConfig cfg").getResultList();
        list = em.createQuery("select d from Device d").getResultList();
        d = list.iterator().next();
        System.out.println("Found device of class: " + d.getClass().getName());
        if (d instanceof PosDevice) System.out.println("This is a POS device"); else System.out.println("This is NOT a POS device!!!");
        System.out.println("toString=" + d.toString());


Name and version of the database you are using:
MySQL 5


Hi,
I have a problem I cannot not explain: The first select query above ("select cfg...") changes the behavior for the query below it. The code above shows the output:
Found device of class: jpa.Device$$EnhancerByCGLIB$$10162692
This is NOT a POS device!!!
toString=jpa.PosDevice@1[id=1]

If I comment out the first query, the output changes to:
Found device of class: jpa.PosDevice
This is a POS device
toString=jpa.PosDevice@1[id=1]

What is going on???

The entity model is simple:
Code:
Device <-- (lazy)1 ---- 0..1(lazy) --> DeviceConfig
   ^
PosDevice

Explanation: Device and DeviceConfig are 1 to 0..1 (i.e. a device may or may not have a config, but a config always has a device), both sides of the relationship are lazy. Device is abstract, and has a single derived class, PosDevice.

My entity code (trivial accessors omitted):
Code:
@Entity
public class DeviceConfig implements Serializable {

    public DeviceConfig() {}

    @Id
    @GeneratedValue
    @Column(name="CONFIG_ID")
    public Long getId() ...
   
    public String getConfig()...
   
    @OneToOne(fetch = FetchType.LAZY, optional=false)
    @ForeignKey(name = "FK_NETCFG_DEVICE")
    @OnDelete(action=OnDeleteAction.CASCADE)
    @JoinColumn(name="DEVICE_ID", nullable=false)
    public Device getDevice() ...

    @Override public int hashCode() ...
    @Override public boolean equals(Object object)...
    @Override public String toString() { return "jpa.DeviceConfig[id=" + id + "]"; }
}



@Entity
@Inheritance(strategy=InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name="CLASS_NAME", discriminatorType=DiscriminatorType.STRING, length=255)
public abstract class Device implements Serializable {

    public Device() {}

    @Id
    @GeneratedValue
    @Column(name="DEVICE_ID")
    public Long getId()...
   
    public String getName()...
   
    @OneToOne(cascade={CascadeType.ALL}, fetch=FetchType.LAZY, mappedBy="device")
    public DeviceConfig getDeviceConfig()...

    @Override public int hashCode()...
    @Override public boolean equals(Object object) ...
    @Override public String toString() { return super.toString() + "[id=" + id + "]"; }
}



@Entity
@DiscriminatorValue(value="jpa.PosDevice")
public class PosDevice extends Device {
    public PosDevice() {}
   
}




MySQL query trace log:
2379 Query select deviceconf0_.CONFIG_ID as CONFIG1_0_, deviceconf0_.config as config0_, deviceconf0_.DEVICE_ID as DEVICE3_0_ from DeviceConfig deviceconf0_
2379 Query select device0_.DEVICE_ID as DEVICE2_1_, device0_.name as name1_, device0_.CLASS_NAME as CLASS1_1_ from Device device0_
2379 Query select deviceconf0_.CONFIG_ID as CONFIG1_0_0_, deviceconf0_.config as config0_0_, deviceconf0_.DEVICE_ID as DEVICE3_0_0_ from DeviceConfig deviceconf0_ where deviceconf0_.DEVICE_ID=1


Debug level Hibernate log excerpt:
opened session at timestamp: 12143747211
TransactionFactory reported no active transaction; Synchronization not registered
Looking for a JTA transaction to join
successfully registered Synchronization
Adding flush() and close() synchronization
transient instance of: jpa.PosDevice
saving transient instance
saving [jpa.PosDevice#<null>]
executing insertions
processing cascade ACTION_PERSIST_SKIPLAZY for: jpa.PosDevice
done processing cascade ACTION_PERSIST_SKIPLAZY for: jpa.PosDevice
executing identity-insert immediately
Inserting entity: jpa.PosDevice (native id)
about to open PreparedStatement (open PreparedStatements: 0, globally: 0)
opening JDBC connection
insert
into
Device
(name, CLASS_NAME)
values
(?, 'jpa.PosDevice')
Hibernate:
insert
into
Device
(name, CLASS_NAME)
values
(?, 'jpa.PosDevice')
preparing statement
Dehydrating entity: [jpa.PosDevice#<null>]
binding 'p1' to parameter: 1
Natively generated identity: 1
about to close PreparedStatement (open PreparedStatements: 1, globally: 1)
closing statement
aggressively releasing JDBC connection
releasing JDBC connection [ (open PreparedStatements: 0, globally: 0) (open ResultSets: 0, globally: 0)]
processing cascade ACTION_PERSIST_SKIPLAZY for: jpa.PosDevice
cascading to persist: jpa.DeviceConfig
transient instance of: jpa.DeviceConfig
saving transient instance
saving [jpa.DeviceConfig#<null>]
executing insertions
executing identity-insert immediately
Inserting entity: jpa.DeviceConfig (native id)
about to open PreparedStatement (open PreparedStatements: 0, globally: 0)
opening JDBC connection
insert
into
DeviceConfig
(config, DEVICE_ID)
values
(?, ?)
Hibernate:
insert
into
DeviceConfig
(config, DEVICE_ID)
values
(?, ?)
preparing statement
Dehydrating entity: [jpa.DeviceConfig#<null>]
binding 'cfg' to parameter: 1
binding '1' to parameter: 2
Natively generated identity: 1
about to close PreparedStatement (open PreparedStatements: 1, globally: 1)
closing statement
aggressively releasing JDBC connection
releasing JDBC connection [ (open PreparedStatements: 0, globally: 0) (open ResultSets: 0, globally: 0)]
done processing cascade ACTION_PERSIST_SKIPLAZY for: jpa.PosDevice
transaction before completion callback
before transaction completion
before transaction completion
automatically flushing session
automatically flushing session
flushing session
processing flush-time cascades
processing cascade ACTION_PERSIST_ON_FLUSH for: jpa.PosDevice
cascading to persistOnFlush: jpa.DeviceConfig
persistent instance of: jpa.DeviceConfig
ignoring persistent instance
processing cascade ACTION_PERSIST_ON_FLUSH for: jpa.DeviceConfig
done processing cascade ACTION_PERSIST_ON_FLUSH for: jpa.DeviceConfig
processing cascade ACTION_PERSIST_ON_FLUSH for: jpa.DeviceConfig
done processing cascade ACTION_PERSIST_ON_FLUSH for: jpa.DeviceConfig
done processing cascade ACTION_PERSIST_ON_FLUSH for: jpa.PosDevice
processing cascade ACTION_PERSIST_ON_FLUSH for: jpa.DeviceConfig
done processing cascade ACTION_PERSIST_ON_FLUSH for: jpa.DeviceConfig
dirty checking collections
Flushing entities and processing referenced collections
Processing unreferenced collections
Scheduling collection removes/(re)creates/updates
Flushed: 0 insertions, 0 updates, 0 deletions to 2 objects
Flushed: 0 (re)creations, 0 updates, 0 removals to 0 collections
listing entities:
jpa.PosDevice{deviceConfig=jpa.DeviceConfig#1, name=p1, id=1}
jpa.DeviceConfig{device=jpa.Device#1, deviceId=null, config=cfg, id=1}
executing flush
registering flush begin
registering flush end
aggressively releasing JDBC connection
post flush
transaction after completion callback, status: 3
after transaction completion
after transaction completion
TransactionFactory reported no active transaction; Synchronization not registered
TransactionFactory reported no active transaction; Synchronization not registered
TransactionFactory reported no active transaction; Synchronization not registered
closing session
connection already null in cleanup : no action
opened session at timestamp: 12143747212
TransactionFactory reported no active transaction; Synchronization not registered
Looking for a JTA transaction to join
successfully registered Synchronization
Adding flush() and close() synchronization
unable to locate HQL query plan in cache; generating (select cfg from DeviceConfig cfg)
parse() - HQL: select cfg from jpa.DeviceConfig cfg
--- HQL AST ---
\-[QUERY] 'query'
\-[SELECT_FROM] 'SELECT_FROM'
+-[FROM] 'from'
| \-[RANGE] 'RANGE'
| +-[DOT] '.'
| | +-[IDENT] 'jpa'
| | \-[IDENT] 'DeviceConfig'
| \-[ALIAS] 'cfg'
\-[SELECT] 'select'
\-[IDENT] 'cfg'
throwQueryException() : no errors
select << begin [level=1, statement=select]
FromClause{level=1} : jpa.DeviceConfig (cfg) -> deviceconf0_
Resolved : cfg -> deviceconf0_.CONFIG_ID
select : finishing up [level=1, statement=select]
processQuery() : ( SELECT ( {select clause} deviceconf0_.CONFIG_ID ) ( FromClause{level=1} DeviceConfig deviceconf0_ ) )
Using FROM fragment [DeviceConfig deviceconf0_]
select >> end [level=1, statement=select]
--- SQL AST ---
\-[SELECT] QueryNode: 'SELECT' querySpaces (DeviceConfig)
+-[SELECT_CLAUSE] SelectClause: '{select clause}'
| +-[ALIAS_REF] IdentNode: 'deviceconf0_.CONFIG_ID as CONFIG1_0_' {alias=cfg, className=jpa.DeviceConfig, tableAlias=deviceconf0_}
| \-[SQL_TOKEN] SqlFragment: 'deviceconf0_.config as config0_, deviceconf0_.DEVICE_ID as DEVICE3_0_'
\-[FROM] FromClause: 'from' FromClause{level=1, fromElementCounter=1, fromElements=1, fromElementByClassAlias=[cfg], fromElementByTableAlias=[deviceconf0_], fromElementsByPath=[], collectionJoinFromElementsByPath=[], impliedElements=[]}
\-[FROM_FRAGMENT] FromElement: 'DeviceConfig deviceconf0_' FromElement{explicit,not a collection join,not a fetch join,fetch non-lazy properties,classAlias=cfg,role=null,tableName=DeviceConfig,tableAlias=deviceconf0_,origin=null,colums={,className=jpa.DeviceConfig}}
throwQueryException() : no errors
HQL: select cfg from jpa.DeviceConfig cfg
SQL: select deviceconf0_.CONFIG_ID as CONFIG1_0_, deviceconf0_.config as config0_, deviceconf0_.DEVICE_ID as DEVICE3_0_ from DeviceConfig deviceconf0_
throwQueryException() : no errors
HQL param location recognition took 0 mills (select cfg from DeviceConfig cfg)
located HQL query plan in cache (select cfg from DeviceConfig cfg)
find: select cfg from DeviceConfig cfg
named parameters: {}
about to open PreparedStatement (open PreparedStatements: 0, globally: 0)
opening JDBC connection
select
deviceconf0_.CONFIG_ID as CONFIG1_0_,
deviceconf0_.config as config0_,
deviceconf0_.DEVICE_ID as DEVICE3_0_
from
DeviceConfig deviceconf0_
Hibernate:
select
deviceconf0_.CONFIG_ID as CONFIG1_0_,
deviceconf0_.config as config0_,
deviceconf0_.DEVICE_ID as DEVICE3_0_
from
DeviceConfig deviceconf0_
preparing statement
about to open ResultSet (open ResultSets: 0, globally: 0)
processing result set
result set row: 0
returning '1' as column: CONFIG1_0_
result row: EntityKey[jpa.DeviceConfig#1]
Initializing object from ResultSet: [jpa.DeviceConfig#1]
Hydrating entity: [jpa.DeviceConfig#1]
returning 'cfg' as column: config0_
returning '1' as column: DEVICE3_0_
returning '1' as column: DEVICE3_0_
done processing result set (1 rows)
about to close ResultSet (open ResultSets: 1, globally: 1)
about to close PreparedStatement (open PreparedStatements: 1, globally: 1)
closing statement
aggressively releasing JDBC connection
releasing JDBC connection [ (open PreparedStatements: 0, globally: 0) (open ResultSets: 0, globally: 0)]
total objects hydrated: 1
resolving associations for [jpa.DeviceConfig#1]
loading entity: [jpa.Device#1]
creating new proxy for entity
done materializing entity [jpa.DeviceConfig#1]
initializing non-lazy collections
unable to locate HQL query plan in cache; generating (select d from Device d)
parse() - HQL: select d from jpa.Device d
--- HQL AST ---
\-[QUERY] 'query'
\-[SELECT_FROM] 'SELECT_FROM'
+-[FROM] 'from'
| \-[RANGE] 'RANGE'
| +-[DOT] '.'
| | +-[IDENT] 'jpa'
| | \-[IDENT] 'Device'
| \-[ALIAS] 'd'
\-[SELECT] 'select'
\-[IDENT] 'd'
throwQueryException() : no errors
select << begin [level=1, statement=select]
FromClause{level=1} : jpa.Device (d) -> device0_
Resolved : d -> device0_.DEVICE_ID
select : finishing up [level=1, statement=select]
processQuery() : ( SELECT ( {select clause} device0_.DEVICE_ID ) ( FromClause{level=1} Device device0_ ) )
Using FROM fragment [Device device0_]
select >> end [level=1, statement=select]
--- SQL AST ---
\-[SELECT] QueryNode: 'SELECT' querySpaces (Device)
+-[SELECT_CLAUSE] SelectClause: '{select clause}'
| +-[ALIAS_REF] IdentNode: 'device0_.DEVICE_ID as DEVICE2_1_' {alias=d, className=jpa.Device, tableAlias=device0_}
| \-[SQL_TOKEN] SqlFragment: 'device0_.name as name1_, device0_.CLASS_NAME as CLASS1_1_'
\-[FROM] FromClause: 'from' FromClause{level=1, fromElementCounter=1, fromElements=1, fromElementByClassAlias=[d], fromElementByTableAlias=[device0_], fromElementsByPath=[], collectionJoinFromElementsByPath=[], impliedElements=[]}
\-[FROM_FRAGMENT] FromElement: 'Device device0_' FromElement{explicit,not a collection join,not a fetch join,fetch non-lazy properties,classAlias=d,role=null,tableName=Device,tableAlias=device0_,origin=null,colums={,className=jpa.Device}}
throwQueryException() : no errors
HQL: select d from jpa.Device d
SQL: select device0_.DEVICE_ID as DEVICE2_1_, device0_.name as name1_, device0_.CLASS_NAME as CLASS1_1_ from Device device0_
throwQueryException() : no errors
HQL param location recognition took 0 mills (select d from Device d)
located HQL query plan in cache (select d from Device d)
flushing session
processing flush-time cascades
processing cascade ACTION_PERSIST_ON_FLUSH for: jpa.DeviceConfig
done processing cascade ACTION_PERSIST_ON_FLUSH for: jpa.DeviceConfig
dirty checking collections
Flushing entities and processing referenced collections
Processing unreferenced collections
Scheduling collection removes/(re)creates/updates
Flushed: 0 insertions, 0 updates, 0 deletions to 1 objects
Flushed: 0 (re)creations, 0 updates, 0 removals to 0 collections
listing entities:
jpa.DeviceConfig{device=jpa.Device#1, deviceId=1, config=cfg, id=1}
Dont need to execute flush
find: select d from Device d
named parameters: {}
about to open PreparedStatement (open PreparedStatements: 0, globally: 0)
opening JDBC connection
select
device0_.DEVICE_ID as DEVICE2_1_,
device0_.name as name1_,
device0_.CLASS_NAME as CLASS1_1_
from
Device device0_
Hibernate:
select
device0_.DEVICE_ID as DEVICE2_1_,
device0_.name as name1_,
device0_.CLASS_NAME as CLASS1_1_
from
Device device0_
preparing statement
about to open ResultSet (open ResultSets: 0, globally: 0)
processing result set
result set row: 0
returning '1' as column: DEVICE2_1_
result row: EntityKey[jpa.Device#1]
returning 'jpa.PosDevice' as column: CLASS1_1_
Initializing object from ResultSet: [jpa.PosDevice#1]
Hydrating entity: [jpa.PosDevice#1]
returning 'p1' as column: name1_
done processing result set (1 rows)
about to close ResultSet (open ResultSets: 1, globally: 1)
about to close PreparedStatement (open PreparedStatements: 1, globally: 1)
closing statement
aggressively releasing JDBC connection
releasing JDBC connection [ (open PreparedStatements: 0, globally: 0) (open ResultSets: 0, globally: 0)]
total objects hydrated: 1
resolving associations for [jpa.PosDevice#1]
loading entity: [jpa.DeviceConfig#1]
about to open PreparedStatement (open PreparedStatements: 0, globally: 0)
opening JDBC connection
select
deviceconf0_.CONFIG_ID as CONFIG1_0_0_,
deviceconf0_.config as config0_0_,
deviceconf0_.DEVICE_ID as DEVICE3_0_0_
from
DeviceConfig deviceconf0_
where
deviceconf0_.DEVICE_ID=?
Hibernate:
select
deviceconf0_.CONFIG_ID as CONFIG1_0_0_,
deviceconf0_.config as config0_0_,
deviceconf0_.DEVICE_ID as DEVICE3_0_0_
from
DeviceConfig deviceconf0_
where
deviceconf0_.DEVICE_ID=?
preparing statement
binding '1' to parameter: 1
about to open ResultSet (open ResultSets: 0, globally: 0)
processing result set
result set row: 0
returning '1' as column: CONFIG1_0_0_
result row: EntityKey[jpa.DeviceConfig#1]
done processing result set (1 rows)
about to close ResultSet (open ResultSets: 1, globally: 1)
about to close PreparedStatement (open PreparedStatements: 1, globally: 1)
closing statement
aggressively releasing JDBC connection
releasing JDBC connection [ (open PreparedStatements: 0, globally: 0) (open ResultSets: 0, globally: 0)]
total objects hydrated: 0
done entity load
done materializing entity [jpa.PosDevice#1]
initializing non-lazy collections
Found device of class: jpa.Device$$EnhancerByCGLIB$$10162692
This is NOT a POS device!!!
toString=jpa.PosDevice@1[id=1]
transaction before completion callback
before transaction completion
before transaction completion
automatically flushing session
automatically flushing session
flushing session
processing flush-time cascades
processing cascade ACTION_PERSIST_ON_FLUSH for: jpa.DeviceConfig
done processing cascade ACTION_PERSIST_ON_FLUSH for: jpa.DeviceConfig
processing cascade ACTION_PERSIST_ON_FLUSH for: jpa.PosDevice
cascading to persistOnFlush: jpa.DeviceConfig
persistent instance of: jpa.DeviceConfig
ignoring persistent instance
processing cascade ACTION_PERSIST_ON_FLUSH for: jpa.DeviceConfig
done processing cascade ACTION_PERSIST_ON_FLUSH for: jpa.DeviceConfig
processing cascade ACTION_PERSIST_ON_FLUSH for: jpa.DeviceConfig
done processing cascade ACTION_PERSIST_ON_FLUSH for: jpa.DeviceConfig
done processing cascade ACTION_PERSIST_ON_FLUSH for: jpa.PosDevice
dirty checking collections
Flushing entities and processing referenced collections
Processing unreferenced collections
Scheduling collection removes/(re)creates/updates
Flushed: 0 insertions, 0 updates, 0 deletions to 2 objects
Flushed: 0 (re)creations, 0 updates, 0 removals to 0 collections
listing entities:
jpa.PosDevice{deviceConfig=jpa.DeviceConfig#1, name=p1, id=1}
jpa.DeviceConfig{device=jpa.Device#1, deviceId=1, config=cfg, id=1}
executing flush
registering flush begin
registering flush end
aggressively releasing JDBC connection
post flush
transaction after completion callback, status: 3
after transaction completion
after transaction completion
TransactionFactory reported no active transaction; Synchronization not registered
TransactionFactory reported no active transaction; Synchronization not registered
TransactionFactory reported no active transaction; Synchronization not registered
closing session
connection already null in cleanup : no action


Top
 Profile  
 
 Post subject:
PostPosted: Thu Jun 26, 2008 5:02 am 
Hibernate Team
Hibernate Team

Joined: Thu Apr 05, 2007 5:52 am
Posts: 1689
Location: Sweden
Hi,

I think your problem is that you are using lazy loading and you cannot use instanceof on the dynamic proxy.

In your example, when executing the first query the DeviceConfig gets loaded which probably has a reference to DevicePos. A proxy for this DevicePos will be created. When you then execute the second query the proxy is returned again.

In the case of only executing the second query you are actually loading the Device instances.

You could either map the Device in DeviceConfig eagerly, or you could just modify your first query to:
Code:
select cfg from DeviceConfig cfg left foin fetch cfg.device

This will just load the Device in this particular case eagerly. Last but not least, you could use interception instead of proxying for lazy loading.

--Hardy


Top
 Profile  
 
 Post subject:
PostPosted: Fri Jun 27, 2008 12:51 pm 
Newbie

Joined: Fri Jun 27, 2008 12:44 pm
Posts: 4
I think your loading has some promblems.

_________________
MSN/Email: electronics-mac-sony@hotmail.com
http://www.electronics-mac-sony.com/


Top
 Profile  
 
 Post subject:
PostPosted: Sat Jun 28, 2008 2:18 am 
Hibernate Team
Hibernate Team

Joined: Thu Apr 05, 2007 5:52 am
Posts: 1689
Location: Sweden
wenwenguo wrote:
I think your loading has some promblems.

Which are? ;-)


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 4 posts ] 

All times are UTC - 5 hours [ DST ]


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
© Copyright 2014, Red Hat Inc. All rights reserved. JBoss and Hibernate are registered trademarks and servicemarks of Red Hat, Inc.