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