一、Session对象

    1.Hibernate最重要的对象,只用使用hibernate与数据库操作,都用到这个对象2.该对象维护了一个Connection对象。代表了与数据库连接的会话。3.该对象实质上是对Connection对象的包装,在Connection对象基础之上,封装了一些方法。4.使用hibernate操作数据库时,执行更新操作(增、删、改)必须在事务中进行。  

1.1 session对象的创建

     Session  session= new Configuration().configure().addClass(DeveloperEnTity.class).addClass(ProjectEntity.class).buildSessionFactory().openSession();

1.2 session对象的作用

     Session代表的是Hibernate与数据库的链接对象,是与数据库交互的桥梁。        它是从持久化服务中剥离出来的一个非常重要的API接口。Session的内部维护了一个Connection对象。它实质上是对Connection对象的包装,在Connection基础上进行了加强。他的主要功能是负责执行被持久化对象的CRUD操作。

1.3 session对象的生命周期(Session对象只能定义为局部变量)

//读取配置文件,创建SessionFactory的工厂。该工厂在java应用中是单实例。Confiuration cf=new Configuration();cf.configure();SessionFactpry sf=cf.buildSessionFactory;//获取sessionSession session=sf.openSession();//开启事务session.beginTransiction();......//事务提交session.getTransaction().commit();//关闭sessionsession.close();
Hibernate中Session对象是非线程安全的 ,不能定义成全局变量, 只能定义成局部变量。因此session作用时间短。session的声明周期:sf.openSession()   session的创建session.close()    session的销毁

1.4 session对象内部维护的session缓存

 session对象内部维护了一个缓存对象,其作用就是提高程序的效率。它随着session对象的创建而存在,随着session对象的关闭而销毁。

1.5 session对象的生命周期与session缓存的安全问题

 session对象内部维护了一个一级缓存。首先session对象是线程非安全的。如果我们在创建session对象时,把sesison对象作为成员变量。那么,由于session是非线程安全的,那么sesson对象内部维护的一级缓存也是线程非安全的。所以我们在创建session对象,都会把它作为局部变量。局部变量,自带线程安全属性。 

二、Session对象API – 事务

2.1 开启事务以及提交事务

     使用hibernate执行新增或修改操作时,必须要在事务环境下执行。session.beginTransaction(); 开启一个事务; hibernate要求所有的与数据库的操作必须有事务的环境,否则报错!   ...session.getTransaction().commit();提交事务。

2.2 事务的作用流程

     public static void main(String[] args) {UserEntity user=new UserEntity();user.setId(1212);session.beginTransaction();System.out.println("...1");session.save(user);System.out.println("...2");session.flush();System.out.println("...3");session.getTransaction().commit();System.out.println("...4");}

三、Session对象API – 更新操作(更新/新增/删除)

 更新:session.delete(obj); 删除一个对象session.save(obj);   保存一个对象session.update(emp);  更新一个对象session.saveOrUpdate(emp);  保存或者更新的方法:没有设置主键,执行保存;有设置主键,执行更新操作; 如果设置主键不存在报错!
public class Demo2 {private  static SessionFactory sf;static {Configuration cf=new Configuration();cf.configure();sf=cf.buildSessionFactory();}@Testpublic void testUpdate() {//创建对象UserEntity u=new UserEntity();u.setId("366cbb16-7c1ce-4b23-9b5a-bd34a0583d20");u.setName("666");u.setBirth(new Date());//1.创建会话连接Session session = sf.openSession();//1.如果数据库有该主键,则更新,如果没有,则新增
//      Transaction tr = session.beginTransaction();
//      session.saveOrUpdate(u);
//      tr.commit();//2.如果数据有该主键,则更新。如果没有,则报错Transaction tr = session.beginTransaction();session.update(u);tr.commit();}

3.1 save()

 注意事项:1.对象被保存后,对象的ID会自动赋值。2.对象设置主键,在save方法保存之后,会被自动刷新成数据库中的存储的主键。(对象单独设置的主键无效)
>>> 3.1.1 对象被保存后,ID会自动赋值
 public static void main(String[] args) {session.beginTransaction();//先根据ID去缓存中查找是否有该对象,如果没有就去数据库中查找。找到后放入到缓存中ProjectEntity pro=new ProjectEntity();pro.setpDesc("111");System.out.println("保存前打印:"+pro);session.save(pro);session.getTransaction().commit();System.out.println("保存后打印:"+pro);session.close();}

>>> 3.1.2 ID在save方法前设置,保存无效。
public static void main(String[] args) {session.beginTransaction();//先根据ID去缓存中查找是否有该对象,如果没有就去数据库中查找。找到后放入到缓存中ProjectEntity pro=new ProjectEntity();pro.setpDesc("111");pro.setpId(111);System.out.println("保存前打印:"+pro);session.save(pro);session.getTransaction().commit();System.out.println("保存后打印:"+pro);session.close();}

3.2 update()

>>> 3.2.1 session关闭后,持久化对象变游离对象
     关闭session。重新打开的时候。不会执行update语句。  因为news对象是查询出来了。放在session缓存中。然后关闭了。又重新打开了一个session中。但是新打开的session中没有news对象。所以修改对象不会执行update。需要显示的调用update方法。
 @org.junit.Testpublic void testUpdate(){News news =(News) session.get(News.class, 1);transaction.commit();session.close();session=sessionFactory.openSession();transaction=session.beginTransaction();news.setAuthor("YI");}
>>> 3.2.2 若数据表中没有对应的记录。但还调用了update方法。会抛出异常。
查询一个news对象。然后修改ID 。抛出StaleObjectStateException 异常
@org.junit.Testpublic void testUpdate(){News news =(News) session.get(News.class, 1);transaction.commit();session.close();session=sessionFactory.openSession();transaction=session.beginTransaction();news.setId(10);session.update(news);}
>>> 3.2.3 当update()方法关联一个游离对象时。如果session的缓存中已经存在相同OID的持久化对象。会抛出异常。因为在Session缓存中不能有两个相同OID的对象。
@org.junit.Testpublic void testUpdate(){News news =(News) session.get(News.class, 1);transaction.commit();session.close();session=sessionFactory.openSession();transaction=session.beginTransaction();News news2 =(News) session.get(News.class, 1);session.update(news);}

3.3 delete()

>>> 3.3.1 只要OID和数据表中一条记录对应。就删除。若OID没有对应的。抛出异常。
 public void testDelete(){News news =(News) session.get(News.class, 1);session.delete(news);System.out.println(news);}
>>> 3.3.2 由于使用delete()删除时,如果数据库中没有该数据,就会报错,常使用 经常是先查询在删除。
 public void testDelete(){News news =(News) session.get(News.class, 1);session.delete(news);System.out.println(news);}
>>> 3.3.3 删除数据时,上述操作会操作两次,也可以使用hql删除。hql删除无上述弊端。
 public void  delete(String id) {Session session = sf.getCurrentSession();session.createQuery("delete from EmpEntity where id=?").setParameter(1, id).executeUpdate();}

3.4

3.4 saveOrUpdate()

四、Session对象API - 查询操作

4.1 主键查询

4.1.1 get查询、load查询
 主键查询:session.get(Employee.class, 1);    主键查询,即时加载session.load(Employee.class, 1);   主键查询 (支持懒加载)
public class Demo2 {private  static SessionFactory sf;static {Configuration cf=new Configuration();cf.configure();sf=cf.buildSessionFactory();}/***    主键查询*/@Testpublic void testGetByKey() {Session session = sf.openSession();UserEntity user=(UserEntity) session.get(UserEntity.class, "366cbb16-7cce-4b23-9b5a-bd34a0583d20");System.out.println(user);     }

4.2 HQL查询(Query对象)

     创建Query对象Query query = session.createQuery("from UserEntity where id=12 ");设置参数query.setParameter(0,"xxx");query.setString(1,"xxx");设置分页query.setFirstResult((page-1)*count);//查询的起始行query.setMaxResults(count);//每页显示的条数   执行List<UserEntity> list = query.list(); 获取列表UserEntity user = query.uniqueResult(); 获取唯一结果Iterator<UserEntity> it = query.iterate();获取迭代器query.executeUpdate() ; 执行sql语句(hql可以执行增删改操作)
 HQL查询与SQL查询区别:SQL: (结构化查询语句)查询的是表以及字段;  不区分大小写。HQL: hibernate  query  language 即hibernate提供的面向对象的查询语言查询的是对象以及对象的属性。区分大小写。这种方式适合没有数据库基础的程序员使用。
4.1.1 基础案例
>>>>>> hibernate.cfg.xml
<!DOCTYPE hibernate-configuration PUBLIC"-//Hibernate/Hibernate Configuration DTD 3.0//EN""http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd"><hibernate-configuration><!-- 通常,一个session-factory节点代表一个数据库 --><session-factory ><!-- 1. 数据库连接配置 --><property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property><property name="hibernate.connection.url">jdbc:mysql://localhost:3306/test</property><property name="hibernate.connection.username">root</property><property name="hibernate.connection.password">root</property><!-- 数据库方法配置, hibernate在运行的时候,会根据不同的方言生成符合当前数据库语法的sql--><property name="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect</property><!-- 2. 其他相关配置 --><!-- 2.1 显示hibernate在运行时候执行的sql语句 --><property name="hibernate.show_sql">true</property><!-- 2.2 格式化sql --><property name="hibernate.format_sql">false</property><!-- 2.3 自动建表  --><property name="hibernate.hbm2ddl.auto">create</property><!-- 3. 加载所有映射 <mapping resource="org/jsoft/demo/EmpEntity.hbm.xml"/>--></session-factory>
</hibernate-configuration>
public class Demo2 {private  static SessionFactory sf;static {Configuration cf=new Configuration();cf.configure();sf=cf.buildSessionFactory();}/***  HQL查询*/@Testpublic void testHQL() {Session session = sf.openSession();//查询全部Query query = session.createQuery("from UserEntity where id=12 ");List<UserEntity> list = query.list();System.out.println(list);}
>>>>>> UserEntity.hbm.xml
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN""http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"><hibernate-mapping package="org.jsoft.f_search" ><class name="UserEntity" table="t_user"><id name="id" column="id"></id><!-- 非主键,映射 -->       <property name="age" column="age"></property><property name="birth" column="birth"  type="java.util.Date"></property></class></hibernate-mapping>
>>>>>> UserEntity.java
public class UserEntity {private int id;private String name;private int age;private Date birth;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 int getAge() {return age;}public void setAge(int age) {this.age = age;}public Date getBirth() {return birth;}public void setBirth(Date birth) {this.birth = birth;}}
>>>>>> App.java
public class App {private static Session session;static {SessionFactory sf = new Configuration().configure().addClass(UserEntity.class).buildSessionFactory();session=sf.openSession();}public static void main(String[] args) {HQL_iterator();}/*** HQL的iterator查询*/private static void HQL_iterator() {session.beginTransaction();Query qr = session.createQuery(" from UserEntity");Iterator<UserEntity> it = qr.iterate();while(it.hasNext()) {System.out.println(it.next());}}/*** HQL的list查询*/private static void HQL_list() {session.beginTransaction();Query qr = session.createQuery(" from UserEntity");List<UserEntity> list = qr.list();for(UserEntity u:list) {System.out.println(u);}}}
4.1.2 HQL语句
 HQL是面向对象的查询。其HQL语句也是面向对象的。如:select * from t_user where t_name='hlp'创建HQL语句:Query query = session.createQuery(" from UserEntity where name='hlp' ");
>>>>>> UserEntity.hbm.xml
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN""http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"><hibernate-mapping package="org.jsoft.f_search" ><class name="UserEntity" table="t_user1"><id name="id" column="id"></id><!-- 非主键,映射 -->  <property name="name" column="t_nam"></property>  <property name="age" column="t_age"></property><property name="birth" column="birth"  type="java.util.Date"></property></class></hibernate-mapping>
>>>>>> App.java
 private static void page() {//hql语句Query query = session.createQuery(" from UserEntity where name='hlp' ");int page=1;int count=4;//设置分页参数query.setFirstResult((page-1)*count);//查询的起始行query.setMaxResults(count);//每页显示的条数List<UserEntity> list = query.list();System.out.println(list);}
4.1.3 条件查询
     设置参数从0开始。
/*** HQL的条件查询.设置参数从0开始*/private static void HQL_condititon() {session.beginTransaction();Query qr = session.createQuery(" from UserEntity where id=?");qr.setParameter(0, 1);List<UserEntity> list = qr.list();System.out.println(list);}
4.1.4 分页查询
 /***    分页查询*/private static void page() {Query query = session.createQuery(" from UserEntity ");int page=1;int count=4;//设置分页参数query.setFirstResult((page-1)*count);//查询的起始行query.setMaxResults(count);//每页显示的条数List<UserEntity> list = query.list();System.out.println(list);}

4.3 Criteria查询(完全面向对象的查询)

     创建Criteria 对象Criteria criteria = session.createCriteria(UserEntity.class);设置参数criteria.add(Restrictions.eq("id", "12"));执行List<UserEntity> list = criteria.list(); 获取列表UserEntity user = criteria.uniqueResult(); 获取唯一结果
 本地SQL查询:完全面向对象的查询。这种方式适合有数据库基础的程序员使用。
public class Demo2 {private  static SessionFactory sf;static {Configuration cf=new Configuration();cf.configure();sf=cf.buildSessionFactory();}/***  Criterial查询*/@Testpublic void testCriterial() {Session session = sf.openSession();Criteria criteria = session.createCriteria(UserEntity.class);criteria.add(Restrictions.eq("id", "12"));List<UserEntity> list = criteria.list();System.out.println(list);}

4.4 原生SQL查询(SqlQuery对象 - 本地SQL查询)

     创建SQLQuery 对象SQLQuery sqlQuery = session.createSQLQuery("select * from user");设置参数sqlQuery .setParameter(0,"xxx");sqlQuery .setString(1,"xxx");设置分页sqlQuery .setFirstResult((page-1)*count);//查询的起始行sqlQuery .setMaxResults(count);//每页显示的条数 执行List<UserEntity> list = sqlQuery .list(); 获取列表UserEntity user = sqlQuery .uniqueResult(); 获取唯一结果Iterator<UserEntity> it = sqlQuery .iterate();获取迭代器sqlQuery .executeUpdate() ; 执行sql语句(可以执行增删改操作)
          复杂的查询,就要使用原生态的sql查询,也可以,就是本地sql查询的支持!(缺点: 不能跨数据库平台!)
public class Demo2 {private  static SessionFactory sf;static {Configuration cf=new Configuration();cf.configure();sf=cf.buildSessionFactory();}/***    原生SQL查询*/@Testpublic void testSql() {Session session = sf.openSession();SQLQuery sqlQuery = session.createSQLQuery("select * from user");sqlQuery.addEntity(UserEntity.class);List<UserEntity> list = sqlQuery.list();System.out.println(list);}
}

五、Session对象API - 查询操作,细节分析

5.1 list 查询和 iterator 查询的区别

5.1.1 HQL查询、Criteial查询、本地sql查询对这个方法是否支持
1.HQL查询 --  list()iterator()uniqueResult()2.Criterial查询 -- list()uniqueResult()3.本地SQL查询 --  list()iterator()uniqueResult()
 public static void main(String[] args) {// ---------------> 1.HQL//list查询Query qr = session.createQuery(" from UserEntity ");List<ProjectEntity> list = qr.list();System.out.println(list);//iteratorIterator iterate = qr.iterate();// ---------------> 2.CritealCriteria ct = session.createCriteria(UserEntity.class);List<ProjectEntity> list2 = ct.list();System.out.println(list2);//iterator ==== Criteal没有iterator方法// ---------------> 3.原生sqlSQLQuery sql = session.createSQLQuery("from t_user");List<ProjectEntity> list3 = sql.list();System.out.println(list3);//iteratorIterator iterate3 = sql.iterate();}
5.1.2 list查询 和iterator的区别
>>>>>> 一次查询与多次查询
list与iterator查询的区别?list() 一次把所有的记录都查询出来,会放入缓存,但不会从缓存中获取数据Iterator()N+1查询; N表示所有的记录总数即会先发送一条语句查询所有记录的主键(1),再根据每一个主键再去数据库查询(N)!会放入缓存,也会从缓存中取数据!
  1. 案例1
 public static void main(String[] args) {session.beginTransaction();     Query qr = session.createQuery("from ProjectEntity");List<ProjectEntity> list = qr.list();for(ProjectEntity p:list) {System.out.println(p.getpId()+" "+p.getpName());}        session.close();}


2. 案例2

 public static void main(String[] args) {session.beginTransaction();     Query qr = session.createQuery("from ProjectEntity");Iterator<ProjectEntity> it = qr.iterate();while(it.hasNext()) {ProjectEntity p = it.next();System.out.println(p.getpId()+" "+p.getpName());}session.close();}

>>>>>> 是否放入缓存、是否从缓存取数据
  list查询过程:只会生成一条sql。它会将查询的数据放入缓存中,但不会从缓存中取数据。iterator查询过程:首先会生成一条sql查询符合条件的数据ID。然后根据迭代器,即 it.next()。通过ID一条条查询。它会从缓存中数据,也会将数据放入到缓存缓存中。
public static void main(String[] args) {session.beginTransaction();      //第一次Query qr = session.createQuery("from ProjectEntity");List<ProjectEntity> list = qr.list();for(ProjectEntity p:list) {System.out.println(p.getpId()+" "+p.getpName());}System.out.println("======");//第二次Query qr2 = session.createQuery("from ProjectEntity");List<ProjectEntity> list2 = qr2.list();for(ProjectEntity p:list2) {System.out.println(p.getpId()+" "+p.getpName());}session.close();}

 iterator查询会从缓存中取数据
 public static void main(String[] args) {session.beginTransaction();     //第一次Query qr = session.createQuery("from ProjectEntity");Iterator<ProjectEntity> it = qr.iterate();while(it.hasNext()) {ProjectEntity p = it.next();System.out.println(p.getpId()+" "+p.getpName());}System.out.println("======");//第二次Query qr2 = session.createQuery("from ProjectEntity");Iterator<ProjectEntity> it2 = qr.iterate();while(it2.hasNext()) {ProjectEntity p = it2.next();System.out.println(p.getpId()+" "+p.getpName());}session.close();}

5.2 get查询和load查询的区别

     1.get会立即加载对象。返回的是类本身。2.load不会。只是去使用的时候才会执行查询语句。返回的是一个代理对象。代理对象就是别人让你做一件事。先答应下来。然后他需要的时候去帮他做。===> get立即检索。load延迟检索。
public void testGet(){News news =(News) session.get(News.class, 1);System.out.println(news);}@org.junit.Testpublic void testLoad(){News news =(News) session.load(News.class, 1);System.out.println(news);}

>>>>>> get立即检索。load延迟检索
@org.junit.Testpublic void testGet(){News news =(News) session.get(News.class, 1);
//        System.out.println(news);}@org.junit.Testpublic void testLoad(){News news =(News) session.load(News.class, 1);
//        System.out.println(news);}get方法会有查询语句。load方法不会执行查询语句。
>>>>>> get直接获取对象。load延迟获取的是代理对象
@org.junit.Testpublic void testGet(){News news =(News) session.get(News.class, 1);System.out.println(news.getClass());
//        System.out.println(news);}@org.junit.Testpublic void testLoad(){News news =(News) session.load(News.class, 1);System.out.println(news.getClass());
//        System.out.println(news);}

>>>>>> session关闭后,第一次打开load查询的对象会报错
load可能抛出一个   LazyInitializationException 异常: could not initialize proxy - no Session因为get是先加载。然后会打印出来。  load是答应了别人。
别人需要了去帮他做的时候。发现session已经关闭了。
然后抛出一个懒加载异常。
 @org.junit.Testpublic void testGet(){News news =(News) session.get(News.class, 1);session.close();System.out.println(news);}@org.junit.Testpublic void testLoad(){News news =(News) session.load(News.class, 1);session.close();System.out.println(news);}get会打印出来。load抛出一个懒加载异常。
>>>>>> 查询数据库中没有的对象。get返回一个null。load会抛出一个ObjectNotFoundException 异常
@org.junit.Testpublic void testGet(){News news =(News) session.get(News.class, 10);System.out.println(news);}@org.junit.Testpublic void testLoad(){News news =(News) session.load(News.class, 10);System.out.println(news);}

5.3 查询区别

 +++ Hibernate查询支持以下几种方式:1.主键查询2.HQL查询3.Criterial查询4.原生SQL查询。+++ HQL查询与SQL查询的区别?HQL查询查询的是对象以及属性,HQL语句区分大小写SQL查询查询的是数据库表以及字段,不区分大小写。+++ HQL查询和Criterial查询的区别?HQL查询适合具有数据库经验的开发者使用。Criterial是完全面向对象的,适合不具备数据库经验的开发者使用。+++ 原生SQL查询与非原生SQL查询的优缺点?原生SQL查询: 1.可以查询复杂的SQL语句。2.不能跨数据库,即如果底层的数据库切换了,sql语句还需要作出相应的变化。非原生SQL查询(主键查询/HQL查询/Criterial查询):1.不能查询复杂的SQL语句。2.可以跨数据库。非原生SQL查询,底层是有Hibernate生成的SQL语句,如果底层切换了数据库,代码不需要改变。用户只需配置数据库方言即可。

六、懒加载

6.1 get和load的区别

 get :及时加载。只要调用get方法立刻向数据库查询。load:默认使用懒加载,当用到数据时才向数据库查询。
>>>>>> get查询

hibernate.cfg.xml

<!DOCTYPE hibernate-configuration PUBLIC"-//Hibernate/Hibernate Configuration DTD 3.0//EN""http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd"><hibernate-configuration><!-- 通常,一个session-factory节点代表一个数据库 --><session-factory ><!-- 1. 数据库连接配置 --><property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property><property name="hibernate.connection.url">jdbc:mysql://localhost:3306/test</property><property name="hibernate.connection.username">root</property><property name="hibernate.connection.password">root</property><!-- 数据库方法配置, hibernate在运行的时候,会根据不同的方言生成符合当前数据库语法的sql--><property name="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect</property><!-- 2. 其他相关配置 --><!-- 2.1 显示hibernate在运行时候执行的sql语句 --><property name="hibernate.show_sql">true</property><!-- 2.2 格式化sql --><property name="hibernate.format_sql">false</property><!-- 2.3 自动建表  --><property name="hibernate.hbm2ddl.auto">update</property><!-- 3. 加载所有映射 <mapping resource="org/jsoft/demo/EmpEntity.hbm.xml"/>--></session-factory>
</hibernate-configuration>

Person.hbm.xml


<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN""http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"><hibernate-mapping package="org.jsoft.h_lazy" ><class name="Person" table="t_p"><id name="id" column="id"></id><!-- 非主键,映射 -->    <property name="name" column="name"></property>   <property name="age" column="age"></property></class></hibernate-mapping>

App.java


public class App {private static SessionFactory sf;static {sf=new Configuration().configure().addClass(Person.class).buildSessionFactory();}public static void  get() {Session sesison = sf.openSession();Person p=(Person) sesison.get(Person.class, 12);}}
>>>>>> load查询

hibernate.cfg.xml

<!DOCTYPE hibernate-configuration PUBLIC"-//Hibernate/Hibernate Configuration DTD 3.0//EN""http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd"><hibernate-configuration><!-- 通常,一个session-factory节点代表一个数据库 --><session-factory ><!-- 1. 数据库连接配置 --><property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property><property name="hibernate.connection.url">jdbc:mysql://localhost:3306/test</property><property name="hibernate.connection.username">root</property><property name="hibernate.connection.password">root</property><!-- 数据库方法配置, hibernate在运行的时候,会根据不同的方言生成符合当前数据库语法的sql--><property name="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect</property><!-- 2. 其他相关配置 --><!-- 2.1 显示hibernate在运行时候执行的sql语句 --><property name="hibernate.show_sql">true</property><!-- 2.2 格式化sql --><property name="hibernate.format_sql">false</property><!-- 2.3 自动建表  --><property name="hibernate.hbm2ddl.auto">update</property><!-- 3. 加载所有映射 <mapping resource="org/jsoft/demo/EmpEntity.hbm.xml"/>--></session-factory>
</hibernate-configuration>

Person.hbm.xml


<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN""http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"><hibernate-mapping package="org.jsoft.h_lazy" ><class name="Person" table="t_p"><id name="id" column="id"></id><!-- 非主键,映射 -->    <property name="name" column="name"></property>   <property name="age" column="age"></property></class></hibernate-mapping>

App.java


public class App {private static SessionFactory sf;static {sf=new Configuration().configure().addClass(Person.class).buildSessionFactory();}@Testpublic static void load() {Session session = sf.openSession();Person p=(Person) session.load(Person.class, 12);System.out.println(p);}}

6.2 懒加载

     概念:当用到数据的时候,才会总数据库查询。。否则不会查询数据库。目的:提高程序执行效率。实际意义:在项目中,我们如果使用hibernate作为底层。由于映射配置较多,当我们查询一个简单实体数据时,结果把简单实体映射的其他关联数据也查询出来了。这样肯定是浪费资源。所以懒加载的最终意义是在于集合映射时的懒加载。
6.2.1 懒加载异常
 1. Session关闭后,不能使用懒加载数据!2. 如果session关闭后,使用懒加载数据报错:org.hibernate.LazyInitializationException: could not initialize proxy - no Session
>>>>>> 懒加载异常:实例代码,运行报错
@Testpublic static void load() {Session session = sf.openSession();Person p=(Person) session.load(Person.class, 12);session.close();System.out.println(p);}

>>>>>> 懒加载异常解决方式
     如何解决session关闭后不能使用懒加载数据的问题?方式1: 先使用一下数据dept.getDeptName();方式2:强迫代理对象初始化Hibernate.initialize(dept);方式3:关闭懒加载设置lazy=false;方式4: 在使用数据之后,再关闭session! 
6.2.2 懒加载的使用与配置
 lazy 值false   关闭懒加载true    使用懒加载extra   使用懒加载,比true更智能。(在集合数据懒加载时候提升效率)在真正使用数据的时候才向数据库发送查询的sql;如果调用集合的size()/isEmpty()方法,只是统计,不真正查询数据!配置示范:<class name="Dept" table="l_dept"     lazy="true"><id name="id" column="id"><generator class="native"></generator></id><!-- 非主键,映射 -->    <property name="name" column="name"></property>   <set name="emps"  table="l_emp"    lazy="true"><key column="deptId"></key><!-- 映射外键表。class指定外键表对应的java类型。由于package指定了包,所以可以简写类名。否则,写完整类名 --><one-to-many class="Emp"></one-to-many></set>                    </class>
>>>>>> 懒加载配置
 集合标签(Set标签、List标签等都可以)可以配置懒加载:<set name="emps"  table="l_emp" lazy="true"><key column="deptId"></key><!-- 映射外键表。class指定外键表对应的java类型。由于package指定了包,所以可以简写类名。否则,写完整类名 --><one-to-many class="Emp"></one-to-many></set>        多对一标签可以配置懒加载:<many-to-one name="dept"  column="deptId" class="Dept"  lazy="true"></many-to-one>
>>>>>> 所有配置的映射默认为lazy = true
     基本映射配置和集合属性映射配置,都默认lazy =true。

hibernate.cfg.xml

<!DOCTYPE hibernate-configuration PUBLIC"-//Hibernate/Hibernate Configuration DTD 3.0//EN""http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd"><hibernate-configuration><!-- 通常,一个session-factory节点代表一个数据库 --><session-factory ><!-- 1. 数据库连接配置 --><property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property><property name="hibernate.connection.url">jdbc:mysql://localhost:3306/test</property><property name="hibernate.connection.username">root</property><property name="hibernate.connection.password">root</property><!-- 数据库方法配置, hibernate在运行的时候,会根据不同的方言生成符合当前数据库语法的sql--><property name="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect</property><!-- 2. 其他相关配置 --><!-- 2.1 显示hibernate在运行时候执行的sql语句 --><property name="hibernate.show_sql">true</property><!-- 2.2 格式化sql --><property name="hibernate.format_sql">false</property><!-- 2.3 自动建表  --><property name="hibernate.hbm2ddl.auto">update</property><!-- 3. 加载所有映射 <mapping resource="org/jsoft/demo/EmpEntity.hbm.xml"/>--></session-factory>
</hibernate-configuration>

Emp.hbm.xml

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN""http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"><hibernate-mapping package="org.jsoft.h_lazy2"  ><class name="Emp" table="l_emp" ><id name="id" column="id"><generator class="native"></generator></id><!-- 非主键,映射 --> <property name="name" column="name"></property>   <property name="age" column="age"></property> <many-to-one name="dept"  column="deptId" class="Dept"  lazy="true"></many-to-one></class></hibernate-mapping>

Dept.hbm.xml

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN""http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"><hibernate-mapping package="org.jsoft.h_lazy2"  ><class name="Dept" table="l_dept" lazy="true"><id name="id" column="id"><generator class="native"></generator></id><!-- 非主键,映射 --> <property name="name" column="name"></property>   <set name="emps"  table="l_emp" lazy="true"><key column="deptId"></key><!-- 映射外键表。class指定外键表对应的java类型。由于package指定了包,所以可以简写类名。否则,写完整类名 --><one-to-many class="Emp"></one-to-many></set>                   </class></hibernate-mapping>

实体类

public class Emp {private int id;private String name;private int age;private Dept dept;}public class Dept {private int id;private String name;private Set<Emp> emps;}

App.java


public class App {private static SessionFactory sf;static {sf=new Configuration().configure().addClass(Person.class).buildSessionFactory();}@Testpublic static void load() {Session session = sf.openSession();Person p=(Person) session.load(Person.class, 12);System.out.println(p);}}
>>>>>> 集合映射,默认为懒加载。在获取映射数据时,集合数据默认为懒加载数据。即如果不使用,则不会查询。

+++ 没有使用集合数据,只生成一条sql

public class App {private static SessionFactory sf;static {sf=new Configuration().configure().addClass(Emp.class).addClass(Dept.class).buildSessionFactory();}public static void main(String[] args) {Session session = sf.openSession();//虽然配置了集合映射,但是由于没有使用集合数据。即使是get查询,//也不会主动查询集合数据。Dept dept=(Dept) session.get(Dept.class, 1);System.out.println(dept.getName());}}


+++ 使用集合数据,生成两条sql

public class App {private static SessionFactory sf;static {sf=new Configuration().configure().addClass(Emp.class).addClass(Dept.class).buildSessionFactory();}public static void main(String[] args) {Session session = sf.openSession();Dept dept=(Dept) session.get(Dept.class, 1);System.out.println(dept.getEmps());}}

>>>>>> 集合映射,默认为懒加载。当设置为lazy=extra时,也是懒加载,只不过比lazy=true更高级。
     extra   使用懒加载,比true更智能。(在集合数据懒加载时候提升效率)在真正使用数据的时候才向数据库发送查询的sql;如果调用集合的size()/isEmpty()方法,只是统计,不真正查询数据!

+++ lazy=true。调用集合的size()/isEmpty()方法,都会查询数据明细。

Dept.hbm.xml<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN""http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"><hibernate-mapping package="org.jsoft.h_lazy2"  ><class name="Dept" table="l_dept" ><id name="id" column="id"><generator class="native"></generator></id><!-- 非主键,映射 -->   <property name="name" column="name"></property>   <set name="emps"  table="l_emp" lazy="true"><key column="deptId"></key><!-- 映射外键表。class指定外键表对应的java类型。由于package指定了包,所以可以简写类名。否则,写完整类名 --><one-to-many class="Emp"></one-to-many></set>                   </class></hibernate-mapping>

App.java

public class App {private static SessionFactory sf;static {sf=new Configuration().configure().addClass(Emp.class).addClass(Dept.class).buildSessionFactory();}public static void main(String[] args) {Session session = sf.openSession();Dept dept=(Dept) session.get(Dept.class, 1);System.out.println(dept.getEmps().isEmpty());}}

+++ lazy=extra。调用集合的size()/isEmpty()方法,不会查询数据,而是对数据统计。

Dept.hbm.xml<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN""http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"><hibernate-mapping package="org.jsoft.h_lazy2"  ><class name="Dept" table="l_dept" ><id name="id" column="id"><generator class="native"></generator></id><!-- 非主键,映射 -->   <property name="name" column="name"></property>   <set name="emps"  table="l_emp" lazy="true"><key column="deptId"></key><!-- 映射外键表。class指定外键表对应的java类型。由于package指定了包,所以可以简写类名。否则,写完整类名 --><one-to-many class="Emp"></one-to-many></set>                   </class></hibernate-mapping>

App.java

public class App {private static SessionFactory sf;static {sf=new Configuration().configure().addClass(Emp.class).addClass(Dept.class).buildSessionFactory();}public static void main(String[] args) {Session session = sf.openSession();Dept dept=(Dept) session.get(Dept.class, 1);System.out.println(dept.getEmps().isEmpty());}}

6.3 懒加载的作用
 在实际开发过程中,我们都是一个对象关联另外一个对象,如果我们查询一个对象时,把其他对象也查询出来,肯定是影响效率的,所以HIbnernate引入了懒加载特性。

六、其他细节

4.1 拼接SQL,设置参数(从0开始)

public List<UserEntity> findByName(String name) {Session session =null;Transaction tr=null;try {session = HibernateUtils.getSession();tr = session.beginTransaction();Query query = session.createQuery("from UserEntity where name=?");query.setParameter(0, name);return query.list();} catch (HibernateException e) {e.printStackTrace();}finally {tr.commit();session.close();}return null;}

4.2 分页

public List<UserEntity> getAllByPage(int page,int count) {Session session =null;Transaction tr=null;try {session = HibernateUtils.getSession();tr = session.beginTransaction();Query query = session.createQuery("from UserEntity ");//设置分页参数query.setFirstResult((page-1)*count);//查询的起始行query.setMaxResults(count);//每页显示的条数return query.list();} catch (HibernateException e) {e.printStackTrace();}finally {tr.commit();session.close();}return null;}

4.3 hibernate的一级缓存特性

4.3.1 只有当事务提交或者session关闭时,才会生成sql语句并执行。
4.3.2 只有当事务被提交,执行的sql语句才会被持久化到数据库。
4.3.3 保存方法会直接生成一条sql语句。但是修改方法会累加,只会生成一条sql。

七、CRUD 模板代码 – 综合案例

UserEntity.java
public class UserEntity {private String id;private String name;private Date birth;public String getId() {return id;}public void setId(String id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}public Date getBirth() {return birth;}public void setBirth(Date birth) {this.birth = birth;}@Overridepublic String toString() {return "UserEntity [id=" + id + ", name=" + name + ", birth=" + birth + "]";}}
src/hibernate.cfg.xml
<!DOCTYPE hibernate-configuration PUBLIC"-//Hibernate/Hibernate Configuration DTD 3.0//EN""http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd"><hibernate-configuration><!-- 通常,一个session-factory节点代表一个数据库 --><session-factory><!-- 1. 数据库连接配置 --><property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property><property name="hibernate.connection.url">jdbc:mysql://localhost:3306/jsoft</property><property name="hibernate.connection.username">root</property><property name="hibernate.connection.password">root</property><!-- 数据库方法配置, hibernate在运行的时候,会根据不同的方言生成符合当前数据库语法的sql--><property name="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect</property><!-- 2. 其他相关配置 --><!-- 2.1 显示hibernate在运行时候执行的sql语句 --><property name="hibernate.show_sql">true</property><!-- 2.2 格式化sql --><property name="hibernate.format_sql">true</property><!-- 2.3 自动建表  --><property name="hibernate.hbm2ddl.auto">update</property><!-- 3. 加载所有映射 --><mapping resource="UserEntity.hbm.xml"/></session-factory>
</hibernate-configuration>
src/org/jsoft/demo/UserEntity.hbm.xml
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN""http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"><hibernate-mapping package="org.jsoft.demo"><class name="UserEntity" table="USER"><!-- 主键 ,映射  --><id name="id" column="u_id"></id><!-- 非主键,映射 --><property name="name" column="u_name"></property><property name="birth" column="u_birth"></property></class></hibernate-mapping>
HibernateUtils.java (工具类)
public class HibernateUtils {private static SessionFactory sf;static {Configuration cf=new Configuration();cf.configure();sf = cf.buildSessionFactory();}/***  获取Sessio* @return*/public static Session getSession() {return sf.openSession();}
}
UserDao.java(CRUD)
public class UserDao {public void save(UserEntity  user) {Session session =null;Transaction tr=null;try {session = HibernateUtils.getSession();tr = session.beginTransaction();session.save(user);} catch (HibernateException e) {e.printStackTrace();}finally {tr.commit();session.close();}}public void delete(Serializable id) {Session session =null;Transaction tr=null;try {session = HibernateUtils.getSession();tr = session.beginTransaction();UserEntity user=(UserEntity) session.get(UserEntity.class, id);if(user!=null) {session.delete(user);}} catch (HibernateException e) {e.printStackTrace();}finally {tr.commit();session.close();}}public void update(UserEntity  user) {Session session =null;Transaction tr=null;try {session = HibernateUtils.getSession();tr = session.beginTransaction();session.update(user);} catch (HibernateException e) {e.printStackTrace();}finally {tr.commit();session.close();}}public UserEntity findById(String id) {Session session =null;Transaction tr=null;try {session = HibernateUtils.getSession();tr = session.beginTransaction();return (UserEntity) session.get(UserEntity.class, id);} catch (HibernateException e) {e.printStackTrace();}finally {tr.commit();session.close();}return null;}public List<UserEntity> getAll() {Session session =null;Transaction tr=null;try {session = HibernateUtils.getSession();tr = session.beginTransaction();Query query = session.createQuery("from UserEntity");return query.list();} catch (HibernateException e) {e.printStackTrace();}finally {tr.commit();session.close();}return null;}public List<UserEntity> getAllByPage(int page,int count) {Session session =null;Transaction tr=null;try {session = HibernateUtils.getSession();tr = session.beginTransaction();Query query = session.createQuery("from UserEntity ");//设置分页参数query.setFirstResult((page-1)*count);//查询的起始行query.setMaxResults(count);//每页显示的条数return query.list();} catch (HibernateException e) {e.printStackTrace();}finally {tr.commit();session.close();}return null;}public List<UserEntity> findByName(String name) {Session session =null;Transaction tr=null;try {session = HibernateUtils.getSession();tr = session.beginTransaction();Query query = session.createQuery("from UserEntity where name=?");query.setParameter(0, name);return query.list();} catch (HibernateException e) {e.printStackTrace();}finally {tr.commit();session.close();}return null;}public List<UserEntity> findByDate(Date date) {Session session =null;Transaction tr=null;try {session = HibernateUtils.getSession();tr = session.beginTransaction();Query query = session.createQuery("from UserEntity where birth > ?");query.setParameter(0, date.toString());return query.list();} catch (HibernateException e) {e.printStackTrace();}finally {tr.commit();session.close();}return null;}@Testpublic void testAll() {List<UserEntity> findByDate = findByDate(new Date());System.out.println(findByDate);}
}

八、hibernate中数据操作层的优美写法(管道式编程)

     hibernate中的对象通常是以管道的形式设计的。
public class EmpDao {private  SessionFactory  sessionFactory;public void setSessionFactory(SessionFactory sessionFactory) {this.sessionFactory = sessionFactory;}/***   新增* @param empEntity*/public void  save(EmpEntity empEntity) {sessionFactory.getCurrentSession().save(empEntity);}/***     修改* @param empEntity*/public void update(EmpEntity empEntity) {sessionFactory.getCurrentSession().update(empEntity);}/***  删除* @param emp*/public void  delete(int id) {sessionFactory.getCurrentSession().createQuery("delete from EmpEntity where id=?").setParameter(0, id).executeUpdate();}public EmpEntity findById(int id){return (EmpEntity) sessionFactory.getCurrentSession().get(EmpEntity.class, id);}
}

四、Hibernate框架的API (三)-- Session对象相关推荐

  1. Hibernate框架第二天

    ### Hibernate的持久化类 ### ---------- **什么是持久化类** 1. 持久化类:就是一个Java类(咱们编写的JavaBean),这个Java类与表建立了映射关系就可以成为 ...

  2. [原创]java WEB学习笔记94:Hibernate学习之路---session 的管理,Session 对象的生命周期与本地线程绑定...

    本博客的目的:①总结自己的学习过程,相当于学习笔记 ②将自己的经验分享给大家,相互学习,互相交流,不可商用 内容难免出现问题,欢迎指正,交流,探讨,可以留言,也可以通过以下方式联系. 本人互联网技术爱 ...

  3. 使用hibernate框架完成CRUD操作

    前言 : Hibernate框架是一个持久层技术的一个解决方案,使用很简单的配置就可以完成许多之前需要很多JDBC代码才能完成的增删改查操作 , 在这种持久层框架中 , ORM思想非常重要 在ecli ...

  4. JAVAWEB开发之Hibernate详解(三)——Hibernate的检索方式、抓取策略以及利用二级缓存进行优化、解决数据库事务并发问题

    Hibernate的检索方式  Hibernate提供了以下几种检索对象的方式: 导航对象图检索方式:根据已经加载的对象导航到其他对象. OID检索方式:按照对象的OID来检索对象. HQL检索方式: ...

  5. Hibernate框架--学习笔记(上):hibernate项目的搭建和常用接口方法、对象的使用

    一.什么是Hibernate框架: 1.Hibernate是一个操作数据库的框架,实现了对JDBC的封装: 2.Hibernate是一个ORM(对象关系映射)框架,我们在写程序时 ,用的是面向对象的方 ...

  6. Hibernate学习笔记_核心幵发接口及三种对象状态

    核心接口开发  (重点)                                                  一,  Configuration a)   AnnotationConfi ...

  7. 三两下实现NLP训练和预测,这四个框架你要知道

    作者 | 狄东林 刘元兴 朱庆福 胡景雯 编辑 | 刘元兴,崔一鸣 来源 | 哈工大SCIR(ID:HIT_SCIR) 引言 随着人工智能的发展,越来越多深度学习框架如雨后春笋般涌现,例如PyTorc ...

  8. hibernate框架(二)核心配置API

    一:核心配置分为三大部分  必须的配置 .可选的配置和引入映射文件. 1.必须的配置 连接数据库的参数:驱动类  url路径  用户名  密码  方言 <property name=" ...

  9. hibernate框架学习第二天:核心API、工具类、事务、查询、方言、主键生成策略等...

    核心API Configuration 描述的是一个封装所有配置信息的对象 1.加载hibernate.properties(非主流,早期) Configuration conf = new Conf ...

最新文章

  1. filter 在CSS用的效果
  2. 科普MinGW MinGW-W64
  3. 内核开发常备手册翻译(一)
  4. python 中使用ElementTree操作XML
  5. python-03 爬虫相关
  6. 关于module require的学习
  7. java 如何将数字倒置_每日一个小算法之整数中每位上的数字进行反转 20190810
  8. STL--map用法
  9. 门户网站的免费写手我们可怜的SEOer
  10. 学生信息管理系统(c++源代码实现)
  11. Dapper.net 入门demo 轻量级ORM框架
  12. (1)算法设计与分析_算法设计思路
  13. 最新Dynamips for工大瑞普模拟器7.2正式完全版和使用指南
  14. Python面向对象加强4.iter与next的用法,枚举器enumerate
  15. 基于哈夫曼编码的文件压缩
  16. 关于计算机的CPU的发展历史,计算机CPU的全部发展历史
  17. 操作系统实验六、死锁问题实验——单车道问题
  18. Go Flutter Desktop (二) go 二进制程序打包为 mac app(dmg)
  19. 随心(20051024)
  20. 蛋白和肽测序仪销量、收入、价格、毛利率及市场份额

热门文章

  1. 收发EtherCAT帧——ecx_recvpkt
  2. hutool导出excel
  3. Oracle Dimension in DWH
  4. Python学习出来好找工作吗?好找工作的关键是什么?
  5. 为什么不太建议你通过 Python 去找工作?
  6. 和菜鸟一起学产品之交互式设计
  7. 系统设计基础 负载均衡
  8. 图表点编辑数据无反应_word插入图表无法编辑数据
  9. 7-28 | 猴子选大王
  10. 《做有质感的民族》方文山