前几日其实已经总结了一下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 的简单含义。