********************
Person.java主对像
********************
package blog.hibernate.domain;
public class Person {
private int id;
private String name;
private IdCard idCard;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public IdCard getIdCard() {
return idCard;
}
public void setIdCard(IdCard idCard) {
this.idCard = idCard;
}
}
**************
Person.hbm.xml
**************
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="blog.hibernate.domain">
<class name="Person" table="Person">
<id name="id" column="PERSON_ID">
<generator class="native"></generator>
</id>
<property name="name" column="PERSON_NAME"></property>
<one-to-one name="idCard"></one-to-one>
</class>
</hibernate-mapping>
********************
IdCard.java从对象
*******************
package blog.hibernate.domain;
public class IdCard {
private int id;
private String name;
private Person person;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Person getPerson() {
return person;
}
public void setPerson(Person person) {
this.person = person;
}
}
*************
IdCard.hbm.xml
*************
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="blog.hibernate.domain">
<class name="IdCard" table="IDCARD">
<id name="id" column="CARD_ID">
<generator class="foreign">
<param name="property">person</param>
</generator>
</id><!-- IdCard使用的主键来自主对像Person-->
<property name="name" column="CARD_NAME" type="string"></property>
<one-to-one name="person" constrained="true" ></one-to-one>
<!-- constrained="true" 是为外键加约束,这在一对一中只能从对象使用,主对像是不能使用的 -->
</class>
</hibernate-mapping>
*****************
hibernate.cfg.xml
*****************
<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<property name="hibernate.connection.driver_class">org.gjt.mm.mysql.Driver</property>
<property name="hibernate.connection.url">jdbc:mysql://localhost:3306/LazyOfOne2One</property><!-- ///表示连接本机的数据库//localhost:3306 -->
<property name="hibernate.connection.username">root</property>
<property name="hibernate.connection.password">1234</property>
<property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
<property name="hibernate.hbm2ddl.auto">create</property>
<property name="hibernate.show_sql">true</property>
<mapping resource="blog/hibernate/domain/Person.hbm.xml"/>
<mapping resource="blog/hibernate/domain/IdCard.hbm.xml"/>
</session-factory>
</hibernate-configuration>
******************
HibernateUtil.java
*******************
package blog.hibernate;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;
public final class HibernateUtil {
private static SessionFactory sessionFactory;
private HibernateUtil(){}
static{
Configuration cfg = new Configuration();
sessionFactory = cfg.configure("hibernate.cfg.xml").buildSessionFactory();
}
public static SessionFactory getSessionFactory(){
return sessionFactory;
}
public static Session getSession(){
return sessionFactory.openSession();
}
public static Object get(Class clazz,int Id) throws Exception {
Session session = null;
Object object = null;
try {
session = getSession();
object = session.get(clazz, Id);
//object = session.load(class, userId);
return object;
} catch (HibernateException e) {
Logger.getLogger(HibernateUtil.class.getName()).log(Level.SEVERE, null, e);
throw e;
}finally{
session.close();
}
}
public static void add(Object object) throws Exception {
Session session = null;
Transaction tx = null;
try {
session = getSession();
tx = session.beginTransaction();// 相当于tx =session.getTransaction();tx.begin();
session.save(object);
tx.commit();
} catch (HibernateException e) {
if (tx != null) {
tx.rollback();
}
throw e;
} finally {
if (session != null) {
session.close();
}
}
}
public static void update(Object object) throws Exception {
Session session = null;
Transaction tx = null;
try {
session = getSession();
tx = session.beginTransaction();// 相当于tx =session.getTransaction();tx.begin();
session.update(object);
tx.commit();
} catch (HibernateException e) {
if (tx != null) {
tx.rollback();
}
throw e;
} finally {
if (session != null) {
session.close();
}
}
}
public static void delete(Object object) throws Exception {
Session session = null;
Transaction tx = null;
try {
session = getSession();
tx = session.beginTransaction();// 相当于tx =session.getTransaction();tx.begin();
session.delete(object);
tx.commit();
} catch (HibernateException e) {
if (tx != null) {
tx.rollback();
}
throw e;
} finally {
if (session != null) {
session.close();
}
}
}
}
junit test : One2One.java
*****************
package junit.test;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.hibernate.Session;
import org.junit.BeforeClass;
import org.junit.Test;
import blog.hibernate.HibernateUtil;
import blog.hibernate.domain.IdCard;
import blog.hibernate.domain.Person;
public class JuintTest {
@BeforeClass
public static void setUpBeforeClass() throws Exception {
}
@Test
public void test() {
add();
query1();
query2();
query3();
}
public void add() {
IdCard idCard = new IdCard();
idCard.setName("Lily");
Person person = new Person();
person.setName("Lily");
idCard.setPerson(person);
// 必须通过idCard的setter去设置idCard与person的关联,
// 而不能通过person的setter去设置他们的关联
// 因为idCard的主键id是通过idCard的属性person得到的
try {
HibernateUtil.add(person);
HibernateUtil.add(idCard);
} catch (Exception e) {
e.printStackTrace();
}
}
public void query1() {
Person person = null;
try {
person = (Person) HibernateUtil.get(Person.class, 1);
System.out.println(person.getIdCard().getName());
} catch (Exception ex) {
Logger.getLogger(JuintTest.class.getName()).log(Level.SEVERE, null, ex);
}
}
public void query2() {
try {
System.out.println("**********************");
IdCard idCard = (IdCard) HibernateUtil.get(IdCard.class, 1);
System.out.println(idCard.getPerson().getName());
} catch (Exception ex) {
Logger.getLogger(JuintTest.class.getName()).log(Level.SEVERE, null, ex);
}
System.out.println("**********************");
}
public void query3() {
Session session = null;
try {
session = HibernateUtil.getSession();
IdCard idCard = (IdCard) session.get(IdCard.class, 1);
System.out.println(idCard.getPerson().getName());
} catch (Exception ex) {
Logger.getLogger(JuintTest.class.getName()).log(Level.SEVERE, null, ex);
} finally {
if (session != null) {
session.close();
}
}
}
}
总结:
lazy 表示什时候抓取
fetch 表示用什么方式抓取
一般来说
lazy 有两种状态 "proxy"(default,意思是使用懒加载,用的是代理) 和 "false" (意思是不使用懒加载)
fetch 有两种状态 "select"(default) 和 "join"
所以lazy 和 fetch 的组合一共有四种:
(a)、lazy = "proxy" (default) fetch = "select" (default)
(b)、lazy = "false" fetch = "select" (default)
(c)、lazy = "proxy" (default) fetch = "join"
(d)、lazy = "false" fetch = "join"
1、主对像:
查询主对像与lazy 和 fetch 无关。
因为查询主对像不使用懒加载,用关联查询(left outer join)将主从对象一并查出。
//查询主对像
Hibernate:
select
person0_.PERSON_ID as PERSON1_0_1_,
person0_.PERSON_NAME as PERSON2_0_1_,
idcard1_.CARD_ID as CARD1_1_0_,
idcard1_.CARD_NAME as CARD2_1_0_
from
Person person0_
left outer join
IDCARD idcard1_
on person0_.PERSON_ID=idcard1_.CARD_ID
where
person0_.PERSON_ID=?
Lily
2、从对象:
打印输出:
(a)、
lazy = "proxy"(default) fetch = "select"(default)
**********************
//查询从对像,通过从对像打印主对象的信息(session关闭后再打印)
Hibernate:
select
idcard0_.CARD_ID as CARD1_1_0_,
idcard0_.CARD_NAME as CARD2_1_0_
from
IDCARD idcard0_
where
idcard0_.CARD_ID=?
org.hibernate.LazyInitializationException: could not initialize proxy - no Session
at org.hibernate.proxy.AbstractLazyInitializer.initialize(AbstractLazyInitializer.java:132)
at org.hibernate.proxy.AbstractLazyInitializer.getImplementation(AbstractLazyInitializer.java:174)
at org.hibernate.proxy.pojo.javassist.JavassistLazyInitializer.invoke(JavassistLazyInitializer.java:190)
at blog.hibernate.domain.Person_$$_javassist_0.getName(Person_$$_javassist_0.java)
at junit.test.JuintTest.query(JuintTest.java:64)
at junit.test.JuintTest.test(JuintTest.java:20)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:44)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:41)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20)
at org.junit.runners.BlockJUnit4ClassRunner.runNotIgnored(BlockJUnit4ClassRunner.java:79)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:71)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:49)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:193)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:52)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:191)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:42)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:184)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:28)
at org.junit.runners.ParentRunner.run(ParentRunner.java:236)
at junit.framework.JUnit4TestAdapter.run(JUnit4TestAdapter.java:39)
at org.apache.tools.ant.taskdefs.optional.junit.JUnitTestRunner.run(JUnitTestRunner.java:518)
at org.apache.tools.ant.taskdefs.optional.junit.JUnitTestRunner.launch(JUnitTestRunner.java:1052)
at org.apache.tools.ant.taskdefs.optional.junit.JUnitTestRunner.main(JUnitTestRunner.java:906)
**********************
//查询从对像,通过从对像打印主对象的信息(在同一个session里)
Hibernate:
select
idcard0_.CARD_ID as CARD1_1_0_,
idcard0_.CARD_NAME as CARD2_1_0_
from
IDCARD idcard0_
where
idcard0_.CARD_ID=?
Hibernate:
select
person0_.PERSON_ID as PERSON1_0_1_,
person0_.PERSON_NAME as PERSON2_0_1_,
idcard1_.CARD_ID as CARD1_1_0_,
idcard1_.CARD_NAME as CARD2_1_0_
from
Person person0_
left outer join
IDCARD idcard1_
on person0_.PERSON_ID=idcard1_.CARD_ID
where
person0_.PERSON_ID=?
Lily
(b)、
lazy = "false" fetch = "select"(default)
**********************
//查询从对像,通过从对像打印主对象的信息(session关闭后再打印)
Hibernate:
select
idcard0_.CARD_ID as CARD1_1_0_,
idcard0_.CARD_NAME as CARD2_1_0_
from
IDCARD idcard0_
where
idcard0_.CARD_ID=?
Hibernate:
select
person0_.PERSON_ID as PERSON1_0_1_,
person0_.PERSON_NAME as PERSON2_0_1_,
idcard1_.CARD_ID as CARD1_1_0_,
idcard1_.CARD_NAME as CARD2_1_0_
from
Person person0_
left outer join
IDCARD idcard1_
on person0_.PERSON_ID=idcard1_.CARD_ID
where
person0_.PERSON_ID=?
**********************
//查询从对像,通过从对像打印主对象的信息(在同一个session里)
Hibernate:
select
idcard0_.CARD_ID as CARD1_1_0_,
idcard0_.CARD_NAME as CARD2_1_0_
from
IDCARD idcard0_
where
idcard0_.CARD_ID=?
Hibernate:
select
person0_.PERSON_ID as PERSON1_0_1_,
person0_.PERSON_NAME as PERSON2_0_1_,
idcard1_.CARD_ID as CARD1_1_0_,
idcard1_.CARD_NAME as CARD2_1_0_
from
Person person0_
left outer join
IDCARD idcard1_
on person0_.PERSON_ID=idcard1_.CARD_ID
where
person0_.PERSON_ID=?
Lily
(c)、
lazy = "proxy"(default) fetch = "join"
**********************
//查询从对像,通过从对像打印主对象的信息(session关闭后再打印)
Hibernate:
select
idcard0_.CARD_ID as CARD1_1_1_,
idcard0_.CARD_NAME as CARD2_1_1_,
person1_.PERSON_ID as PERSON1_0_0_,
person1_.PERSON_NAME as PERSON2_0_0_
from
IDCARD idcard0_
inner join
Person person1_
on idcard0_.CARD_ID=person1_.PERSON_ID
where
idcard0_.CARD_ID=?
**********************
//查询从对像,通过从对像打印主对象的信息(在同一个session里)
Hibernate:
select
idcard0_.CARD_ID as CARD1_1_1_,
idcard0_.CARD_NAME as CARD2_1_1_,
person1_.PERSON_ID as PERSON1_0_0_,
person1_.PERSON_NAME as PERSON2_0_0_
from
IDCARD idcard0_
inner join
Person person1_
on idcard0_.CARD_ID=person1_.PERSON_ID
where
idcard0_.CARD_ID=?
Lily
(d)、
lazy = "false" fetch = "join"
**********************
//查询从对像,通过从对像打印主对象的信息(session关闭后再打印)
Hibernate:
select
idcard0_.CARD_ID as CARD1_1_1_,
idcard0_.CARD_NAME as CARD2_1_1_,
person1_.PERSON_ID as PERSON1_0_0_,
person1_.PERSON_NAME as PERSON2_0_0_
from
IDCARD idcard0_
inner join
Person person1_
on idcard0_.CARD_ID=person1_.PERSON_ID
where
idcard0_.CARD_ID=?
**********************
//查询从对像,通过从对像打印主对象的信息(在同一个session里)
Hibernate:
select
idcard0_.CARD_ID as CARD1_1_1_,
idcard0_.CARD_NAME as CARD2_1_1_,
person1_.PERSON_ID as PERSON1_0_0_,
person1_.PERSON_NAME as PERSON2_0_0_
from
IDCARD idcard0_
inner join
Person person1_
on idcard0_.CARD_ID=person1_.PERSON_ID
where
idcard0_.CARD_ID=?
Lily
(a)、默认情况:
使用懒加载,查询从对象只查询IdCard一张表,要是要通过从对象访问主对像则需要在同一个session里去访问,否则会报懒加载异常(报无法初始化代理--没有session异常)。
当在同一个session里通过从对象访问主对像时会进行关联查询(left outer join),将主从对象一并查出来。
(b)、不使用懒加载,查询从对象时直接查询IdCard表,再通过关联查询(left outer join)将主从对象一并查出。
(c)、使用懒加载,但是fetch = "join"所以会使用内连接(inner join)将主从对象一并查出。
(d)、不使用懒加载,但是fetch = "join"所以会使用内连接(inner join)将主从对象一并查出。