I have such code:
Session session = HibernateSessionFactory.sessionFactory.openSession();
System.out.println("------------------" + session.get(User.class, (long) 10));
System.out.println("------------------" + session.createSQLQuery("SELECT * FROM diploma.tbl_users Where id = 10").addEntity(User.class).uniqueResult());
First row return null.
The second return valid record.
But if I change places:
System.out.println("------------------" + session.createSQLQuery("SELECT * FROM diploma.tbl_users Where id = 10").addEntity(User.class).uniqueResult());
System.out.println("------------------" + session.get(User.class, (long) 10));
Both rows return correct result:
This is my hibernate session factory:
public class HibernateSessionFactory {
public static SessionFactory sessionFactory = new Configuration().configure("/META-INF/hibernate.cfg.xml")
.buildSessionFactory();
}
Why session.get(User.class, (long) 10))
return null ?
UPDATE hibernate config:
<hibernate-configuration>
<session-factory>
<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="hibernate.connection.url">jdbc:mysql://localhost:3306/diploma</property>
<property name="hibernate.connection.username">root</property>
<property name="hibernate.connection.password">password</property>
<property name="hibernate.dialect">org.hibernate.dialect.MySQL5InnoDBDialect</property>
<property name="hibernate.connection.charSet">UTF-8</property>
<property name="hibernate.hbm2ddl.auto">update</property>
<property name="show_sql">true</property>
<property name="format_sql">true</property>
.........................................
<mapping class="edu.test.entities.User" />
..................................
</session-factory>
User.java
@Entity
@Table(name = "tbl_Users")
public class User extends BaseEntity {
@NotEmpty
@Column(name = "Name")
private String name;
@NotEmpty
@Column(name = "Surname")
private String surname;
@NotEmpty
@Column(name = "Login")
private String login;
@NotEmpty
@Size(min=6, max=20)
@Column(name = "Password")
private String password;
@NotEmpty
@Column(name = "Email")
private String email;
@NotEmpty
@Column(name = "Phone")
private String phone;
@ManyToOne
@JoinColumn(name = "Role", nullable = false)
private Roles role;
// getters and setters
Id field from base entity
@MappedSuperclass
public class BaseEntity implements Serializable {
@Id
@Column(name = "id", unique = true, nullable = false)
@GeneratedValue
private Long id;
UPDATE 2
The problem was in mapping file @JoinColumn(name = "Role", nullable = false)
private Roles role;
I have specified that Role cannot be null and the record that I have tried to retrieve with id 10 have null Role foreign key. So I change nullable = true
and it works.
Hibernate implements Identity Map PoEAA pattern, where the Hibernate session plays the role of the map. When you call .addEntity()
, the loaded entities become associated with the Hibernate session.
Then when you call Hibernate session's get method it first checks the entity cache and returns a existing entity if present.
So in the first statement when you call get
the entity is not yet present in the entity map. In the second snippet the entity is being cached with .addEntity()
method.
update So the problem is that reference to the role is declared with nullable = false
, and there's no such a role in the database.
See also: http://martinfowler.com/eaaCatalog/identityMap.html