培训第2个月的第10天-----hibernate的3种状态(再总结)

                  前几日其实已经总结了一下hibernate的3种状态,也就是hibernate中的3种对象。hibernate的3种状态分别为瞬时态,持久态,和离线状态。今天再次总结的时候,前俩种状态也就是瞬时态,持久态的理解是没有问题的。但是到了离线状态就出现了那么一点歧义。其实我就是对这篇博客(https://www.cnblogs.com/xiaoluo501395377/p/3380270.html)的Demo做了演示和验证,并验证了我的更多的想法。例如,如果用save()方法保存一个数据,然后rollback(),那么这个对象可以查询的到吗?其实当rollback时是可以查询到保存到数据库中的临时数据的,但是要用flush()方法,我们可以得到脏数据。例如这样的Demo我测了很多,下面发测试代码。

                  可以说这篇博客花了我很多的心血(其实也就是测试的时间非常的长)当作自己的笔记,方便自己日后来看。

package com.java.Text;

import org.hibernate.Session;

import com.java.Bean.User;
import com.java.Utils.HibernateSessionFactory_i;

public class Text_new {
    /*当数据库中事务设置为inno时,说明数据库可以进行事务回滚,先用inno来测试hibernate
     *的三种状态,也就是通过事务提交的方式来看看hibernate的3种状态。
     */
	public static void main(String[] args) {
		Text_new text_new=new Text_new();
		//text_new.text_Transient1();
		//text_new.text_Transient2();
		//text_new.text_Transient3();
		//text_new.text_Transient4();
		//text_new.text_Persistent1();
		//text_new.text_Persistent2();
		//text_new.text_Detached1();
		//text_new.text_Detached2();
		text_new.text_Detached3();
	   // text_new.text_Detached4();
		//text_new.text_Detached5();
		
	}
	
	public void text_Transient1() {
		 //创建操作数据库的对象session
  	     Session session=HibernateSessionFactory_i.getSession();
  	     //开启事务
  	     session.beginTransaction();
	  	 User user = new User();
	  	 user.setUserId("1001");
	     user.setUserName("aaa");
	     user.setUserPassword("aaa");
	     //到目前为止这是一个瞬时对象,数据库和session缓存中都没有。这个对象现在在内存中(我不知道缓存和内存的关系)。
	     session.save(user);
	     //通过save方法,将对象从内存拷贝到缓存。数据库中并存在了这个对象?
	     session.clear();
	     System.out.println(session.get(User.class,"1001"));
	     //清除session中的缓存并查询数据库看看数据库中有临时数据没有
//       session.getTransaction().rollback();
	     session.getTransaction().commit();
	     
	     
	     /*Hibernate: select user0_.userid as userid0_0_, user0_.userpassword as userpass2_0_0_, user0_.username as username0_0_, user0_.usersex as usersex0_0_, user0_.userrole as userrole0_0_, user0_.usercollege as usercoll6_0_0_, user0_.usermajor as usermajor0_0_, user0_.userclass as userclass0_0_, user0_.dormitoryId as dormitor9_0_0_ from t_user user0_ where user0_.userid=?
           null。当事务回滚时,查询结果为空,说明当用save()方法时,仅仅是把对象从内存拷贝到了缓存中,不并不往
                                数据库中存临时数据。
                                当进行事务提交的时候,会把session中的瞬时对象持久化到数据库中。                    
	      * */
	     
	}
	
	public void text_Transient2() {
		
		  Session session=HibernateSessionFactory_i.getSession();
		  session.beginTransaction();
		  User user = new User();
		  user.setUserId("1001");
		  user.setUserName("aaa");
		  user.setUserPassword("aaa");
		  //到目前为止这是一个瞬时对象,数据库和session缓存中都没有。这个对象现在在内存中(我不知道缓存和内存的关系)。
		  session.save(user);
		  //通过save方法,将对象从内存拷贝到缓存。
		  System.out.println(session.get(User.class,"1001"));
		  user.setUserMajor("major");
		  //调用setUserMajor()方法只是改变了缓存中的user对象的属性。
		  System.out.println(session.get(User.class,"1001"));
	//	  session.getTransaction().commit();
		  session.getTransaction().rollback();
		  /*如果进行提交,那么save()方法肯定要被指定,发送一条插入语句,然后更改缓存中的属性,发现缓存中的和数据库中
		   *的不一致,那么就在发送一条update语句。
		   *如果进行事务回滚,那么save()和update()方法都没有执行,数据仅仅就是在缓存中,没有持久化到数据库中。
		   * */
	 
	}
	
	public void text_Transient3() {
		  Session session=HibernateSessionFactory_i.getSession();
		  session.beginTransaction();
		  User user = new User();
		  user.setUserId("1001");
		  user.setUserName("aaa");
		  user.setUserPassword("aaa");
		  session.save(user);
		  //如果是提交,那么已经发送一条语句,将这个瞬时对象持久化到数据库中。
		  System.out.println((User)session.get(User.class, "1001"));
		  //从缓存中查询数据。不发送语句。
		  user.setUserMajor("major");
		  /*已经是持久化对象,被保存在session中,即使修改在多次,也只是在缓存中进行修改,在提交的时候,
		   *不管修改多少次属性,只会在提交的时候将session中最后的对象和数据库中的比较。
		  */
		  session.flush();
		  //session.clear();
		  System.out.println((User)session.get(User.class, "1001"));
		  user.setUserMajor("major2");
		  user.setUserMajor("major3");
		  session.clear();
		  System.out.println((User)session.get(User.class, "1001"));
		 // session.getTransaction().commit();
		  session.getTransaction().rollback();
	}
	
	public void text_Transient4() {
		  Session session=HibernateSessionFactory_i.getSession();
		  session.beginTransaction();
		  User user = new User();
		  user.setUserId("1001");
		  user.setUserName("aaa");
		  user.setUserPassword("aaa");
		  session.save(user);
		  //如果进行提交,那么就是一个持久化对象了
		  user.setUserMajor("major2");
          session.update(user);
          /*其实更新方法update()我们可以简单的理解为,更新缓存中的对象,所以不管用多少次都
           *不会操作数据库,也就不会发送语句,只有在提交的时候,才会将session中的对象和数据
           *库中的对比一次。
          */
          user.setUserMajor("major3");
         // session.save(user);
          /*并且一个对象如果在数据库中存在,在调用save()方法保存相同主键的数据,那么就会发生异常。
           * Duplicate entry '1001' for key 'PRIMARY'
           * */
          session.update(user);
         
          session.getTransaction().commit();
	}
	
	public void text_Persistent1() {
		  Session session=HibernateSessionFactory_i.getSession();
		  session.beginTransaction();
	      User user = (User)session.load(User.class, "2001");
	      /*通过session.load()方法和session.get()方法查询出来的数据直接就是持久的对象,
	       *因为数据库中有这个对象,此时session中有这个对象了。
	      */
	      user.setUserName("bbb");
	     // session.getTransaction().commit();
	      //如果进行提交时,那么会有两条sql语句
	      session.getTransaction().rollback();
	      //如果进行回滚,那么只会进行查询,这毫无疑问。
	}
	
	public void text_Persistent2() {
		
		  Session session=HibernateSessionFactory_i.getSession();
		  session.beginTransaction();
          User user = (User)session.load(User.class, "2001");
          user.setUserName("123");
	      session.clear();
	      session.getTransaction().commit();
	      /*当进行提交的时候,查询是肯定的,但是由于用了clear()方法,清空了session缓存,
	       * 所以在提交的时候并没有数据和数据库中的数据进行比较,也就自然没有办法进行更新了。
	       */
	}
	
	public void text_Detached1() {
		  Session session=HibernateSessionFactory_i.getSession();
		  session.beginTransaction();
	      User user = new User();
	      user.setUserId("22");
	      //由于主键Id在数据库中存在,所以这是一个离线对象。
		  /*System.out.println(session.get(User.class, "22"));
		   *如果在离线对象用update()方法前写这句代码会出现错误,因为在进行update()时,
		   *它不知道要更新哪一个user(不知道在缓存中更新成什么样的对象)。
		   */
		  /*看看离线对象现在是在内存中,还是在缓存中?由于此时发送了sql语句,说明查询了数据库,
		   *所以离线对象仍然实在内存中,然后通过update()更新user,由于此时session
		   *缓存中没有,则将user从内存拷贝到缓存中。
		   */
	      session.update(user);
	      System.out.println(session.get(User.class, "22"));
	      /*由于用update()方法,将主键id为“22”的这个user对象拷贝到缓存中,
	       *所以在进行查询的时候,直接从缓存里取出,而不需要发送sql语句来查询数据库。
	       *此时的user已经是持久化对象了。
	       * */
	      user.setUserName("bbbb");
	      System.out.println(session.get(User.class, "22"));
	      user.setUserName("cccc");
	      //session.getTransaction().commit();
	      /*进行提交时,由于session缓存中的对象与数据库中的对象进行比较,如果不同,
	       *一个sql语句进行更新,注意更新只会执行一次,就是看缓存中最后的session
	       *和数据库中的进行比较。
	       */
	      session.getTransaction().rollback();
	}
	
	public void text_Detached2() {
		 Session session=HibernateSessionFactory_i.getSession();
		 session.beginTransaction();
         User user = new User();
         user.setUserId("2001");
	     session.update(user);
	     System.out.println(session.get(User.class, "2001"));
	     /*用update()方法,不用进行查询就可以将这个主键id变为持久化的对象。
	      *
	      */
	     user.setUserPassword("mima");
	     user.setUserName("world");
	     System.out.println(session.get(User.class, "2001"));
	     session.update(user);
	     /*其实除了第一个update()方法将离线对象变为持久化对象以外,其他后面的
	      *update()方法其实是无意义的,因为在设置属性后(也就是setXXX()方法),
	      *是自动提交的,所以并没有意义。
	      */
	     //session.getTransaction().commit();
	     session.getTransaction().rollback();
		
	}
	
	public void text_Detached3() {
		 Session session=HibernateSessionFactory_i.getSession();
		 session.beginTransaction();
         User user = new User();
         user.setUserId("3006");
         System.out.println(session.get(User.class, "3006"));
         session.save(user);
        // session.update(user);
         System.out.println(session.get(User.class, "3006"));
         user.setUserPassword("lisi");
         user.setUserName("qiaotao");
        // user.setUserId("3002");
         //不能更改主键会抛出异常   identifier of an instance of com.java.Bean.User was altered from 3001 to 3002
         System.out.println(session.get(User.class, "3006"));
         //session.save(user);
         session.getTransaction().commit();
         //session.getTransaction().rollback();
         /*只有离线对象或者持久化对象才可以直接调用update()方法,而瞬时对象如果直接调用
          *update()方法,那么在提交的时候就会发生异常,因为数据库中没有对象,它也就没有办法
          *更新,我们可以在commit之前用save()方法,这样就可以了。
          *
          * */
         
         /*如果一个对象是瞬时状态,那么不能在save()方法前调用update()方法,因为,save()将
          *瞬时对象从内存拷贝到缓存并保存到数据库中。在这之前update()已经将对象从内存放到了缓存,所
          *以,save()方法并没有要保存的对象。总之,瞬时对象,不可以先调用update方法,在使用save
          *方法,这样的话会抛出异常。
          *不知为何,语句先输出,在保存。
          */
	}
	
	public void text_Detached4() {
		 Session session=HibernateSessionFactory_i.getSession();
		 session.beginTransaction();
         User user = new User();
         user.setUserId("3002");
         session.delete(user);
        // System.out.println(session.get(User.class, "3002"));
         user.setUserPassword("wangwu");
         //System.out.println(session.get(User.class, "3002"));
         session.getTransaction().commit();
         /*在进行提交时,删除这个数据
          * */
	}
	
	public void text_Detached5() {
		 Session session=HibernateSessionFactory_i.getSession();
		 session.beginTransaction();
         User user = new User();
         user.setUserId("3001");
         user.setUserPassword("zha222");
         //如果u是离线状态就执行update操作,如果是瞬时状态就执行Save操作
         //但是注意:该方法并不常用
         session.saveOrUpdate(user);
         user.setUserPassword("333");
         session.getTransaction().commit();
	}
	
	public void text_Detached6() {
		 Session session=HibernateSessionFactory_i.getSession();
		 session.beginTransaction();
         User user = (User)session.load(User.class, 3);
         //u2是离线状态
         User u2 = new User();
         user.setUserId("3001");
         user.setUserPassword("123456789");
         session.saveOrUpdate(u2);
	}
	
	/*Hibernate有3种状态(也就是有3种状态的对象),transient(瞬时状态),persistent(持久化状态)以及
	 *detached(离线状态)。
	 *对于刚创建的一个对象,如果session中和数据库中都不存在该对象,那么该对象就是瞬时对象(Transient)。离线
	 *对象就是,数据库存在该对象,但是该对象又没有被session所托管。瞬时对象调用save方法,或者离线对象调用upd
	 *ate方法可以使该对象变成持久化对象,如果对象是持久化对象时,那么对该对象的任何修改,都会在提交事务时才会与之
	 *进行比较,如果不同,则发送一条update语句,否则就不会发送语句。
	 * 
	 * 
	 * 
	 * 其实对于所谓的提交与不提交,也就是是否将缓存中的数据持久化到数据库中。
	 * 
	 * 
	 * 注意,本实例的所有注释都是注释 注释上方的代码。
	 * 
	 * 到目前为止,只能理解到这样了,以后再看吧
	 * 
	 * */
	
}

                其实这个我一共想过3次,加一起差不多超过了10个小时,我的能力确实有限,所以我觉得在分析下去也没有什么进步,对于hibernatenate的3种状态在代码中的应用到目前为止就告一段落(自己分析sql语句有几条,sql语句是怎么个顺序实在是有那么点累),所以除非我能力有所提升,要不我再分析这个我就是狗!

                 我在来记录一下发布JavaEE项目时的问题,在配置xml文件的时候,难免会出现找不到的问题,这是我们就要注意了,是不是文件的路径不对!

                   通常一个JavaEE项目,在发布项目时,会将项目下的src目录下的所有文件都会进行编译。    .java文件被编译成  .class文件,而xml文件将还是以xml文件的类型存在。被编译后的java文件和xml文件将会被放到tomcal服务器中。

                  将src目录下的文件编译后会默认被放到例如这样的路径下:F:\Development\DevelopmentTool\apache-tomcat-9.0.4-windows-x64\apache-tomcat-9.0.4\webapps\Mybatis2_I\WEB-INF\classes。

                     其中\webappswen文件夹 当eclipse中tomcat服务器进行发布时,用于存放JavaEE项目,并且在项目的WEB-INF\classes文件夹下存放着src下被编译的文件。

                         我们在访问xml文件时,如果xml文件在src下,那么被编译后在WEB-INF\classes下,而web.xml文件在加载其他问件时默认会去WEB-INF\classes文件夹下,所以我们没有必要刻意关心web.xml文件在加载其他文件时的路径问题。但是我们会通常像下面那样,指定classpath,classpath的含义就是在tomcat服务器的当前项目下的WEB-INF\classes文件夹中,告诉java虚拟机,你就去这里找,所以这样写是没有错的。

                 但是如果想要 加载的文件不再WEB-INF\classes(classpath)文件夹怎么办呢?那么我们就指定路径,比如去WEB-INF下,那么我们就直接像下面这样指定路径。

                    今天总结两个点:一,hibernate的3种状态。二,classpath 的简单含义。

猜你喜欢

转载自blog.csdn.net/qq_41160264/article/details/82228075
今日推荐