Hibernate-note01

来源:互联网 发布:ios小说阅读器 源码 编辑:程序博客网 时间:2024/05/17 02:06


ORM:实现实体类对象到数据表的映射
1.ORM框架
JPA是一个规范,java持久化API。在这个规范下产生了很多框架,
由sun发布一个企业级开发组件EJB(企业级javaBean)的一部分,EJB--MessageBean ,JPA,
有状态无状态的一种bean


SUN JPA 规范
openjpa ,TopLink ,Hibernate


01.Hibernate--
02.mybatis----
03.OpenJPA----




hibernate隶属于一个组织JBoss,JBoss属于RedHat的一部分
JSR220和JSR317是java里的一些草案


3.POJO(持久化类)就是以前的实体类
pojo:Plain Ordinary Java Object(无格式的Java对象)
Hibernate对pojo的要求:
• 属性要有对应的get和set方法
• 要有无参数的默认构造方法(要是有有参数的,还要加上无参数的)
• 不要使用final进行修饰


2.步骤
01. 加入Hibernate的jar包和一个jdbc的jar包
02. 创建持久化类(pojo)
03. 创建映射文件(xxx.hbm.xml)
////作用就是让一个类和表映射起来(一般和pojo放在一个包中,放在一个取名叫.pojo的包中
eg:User.hbm.xml)


---找到hibernate-core-4.2.0final.jar → org.hibernate,
在这个包的最下面有一个hibernate/hibernate-mapping-3.0.dtd
找到
<!DOCTYPE hibernate-mapping PUBLIC 
   "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
   "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
   拷贝到user.hbm.xml中
04. 创建Hibernate配置文件(hibernate.cfg.xml)
---找到hibernate-core-4.2.0final。jar → org.hibernate,
在这个包的最下面有一个hibernate-configuration-3.0.dtd
找到
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
拷贝到hibernate.cfg.xml中

05. 运行




3.user.hbm.xml配置介绍<!--  -->
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC 
   "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
   "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">


<hibernate-mapping package="com.kaishengit.pojo">
<!--这里package若是写了,下面就class的name就不用写包名了 -->
<!--但是若是没写package属性,下面的就要写完全限定名-->


<class name="User" table="t_user"><!--类名和包名-->


<!--主键列<id>,只要name的都是类,column的是表的列的名  -->
<id name="id" column="id">
<!--数据库中要告诉主键的生成策略,主键比较特殊-->
<generator class="native"></generator>
</id>


<!--其他列用propertiy,当name和column值相等的时候,
  column="name"可以省略-->
<property name="name" column="name"></property>
<property name="age"></property>
</class>


</hibernate-mapping>




生成策略:native表示--主动增长
 uuid:--uuid
 序列:


4.创建Hibernate配置文件(hibernate.cfg.xml)
在etc中建一个(hibernate.cfg.xml)配置文件。在


<?xml version="1.0" encoding="UTF-8"?>
<!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>
<!-- //这个和web中session没有一点关系,凑巧名字一样了
//关于property,在hibernate-release-4.2.0.Final中 → project → etc → hibernate.properties
//在这个里面都是hibernate的配置项,在mysql中
-->
<!-- ## MySQL
#hibernate.dialect org.hibernate.dialect.MySQLDialect//方言表示自动识别,一般用这个
#hibernate.dialect org.hibernate.dialect.MySQLInnoDBDialect//方言 
#hibernate.dialect org.hibernate.dialect.MySQLMyISAMDialect//方言
#hibernate.connection.driver_class com.mysql.jdbc.Driver
#hibernate.connection.url jdbc:mysql:///test
#hibernate.connection.username gavin
#hibernate.connection.password -->




<!-- ///配置数据库连接 -->
<property name="connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="connection.url">jdbc:mysql:///hibernate_demo</property>
<property name="connection.username">root</property>
<property name="connection.password">root</property>
<!-- 方言,这个是表示不同的数据库,的设置不同-->
<property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
<!-- 
#################################
### Hibernate Connection Pool ###
#################################
hibernate.connection.pool_size 1 
//在开发中一定不能用这句话,这个是效率很低的一个。所以我们可以用DBCP或者C3P0
//因为后来hibernate提示DBCP有未知的问题,不让用所以就用C3P0
###########################
### C3P0 Connection Pool###
###########################
#hibernate.c3p0.max_size 2
#hibernate.c3p0.min_size 2
#hibernate.c3p0.timeout 5000
#hibernate.c3p0.max_statements 100
#hibernate.c3p0.idle_test_period 3000
#hibernate.c3p0.acquire_increment 2
#hibernate.c3p0.validate false
-->

<!-- 数据连接池 -->
<property name="hibernate.c3p0.max_size">2</property>
<property name="hibernate.c3p0.min_size">2</property>
<property name="hibernate.c3p0.timeout">5000</property>
<property name="hibernate.c3p0.max_statements">100</property>
<property name="hibernate.c3p0.idle_test_period">3000</property>
<property name="hibernate.c3p0.acquire_increment">2</property>
<property name="hibernate.c3p0.validate">false</property>

<!-- 其他配置,这里的都属于其他配置了-->
<!-- ##############################
### Miscellaneous Settings ###
##############################
## print all generated SQL to the console
#hibernate.show_sql true
//show_sql,就是在控制台打印出来一句sql语句
## format SQL in log and console

hibernate.format_sql true//这个就是让sql语句的每个单词输出在一行 -->


<property name="hibernate.show_sql">true</property>


<!--这个在dtd配置文件中没有的一个项,这个指的是把当前的配置项session放在一个thread线程中 -->
<property name="hibernate.current_session_context_class">thread</property>

<!-- 映射文件的配置,这里resource指的是磁盘的目录,所以是"/"不是"."-->
<mapping resource="com/kaishengit/pojo/User.hbm.xml"/>
</session-factory>
</hibernate-configuration>


在这个里面数据库用了C3P0,就记得要导入C3P0的两个包,在hibernate-release-4.2.0.Final→lib→optical中,
还要导入jdbc的包


5.使用Hibernate
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.service.ServiceRegistryBuilder;


import pojo.User;//建立一个实体类和映射文件中的对应,要有get/set


public class HibernateTest01 {
public static void main(String[] args) {
Configuration cfg = new Configuration().configure();//不调用configure()的时候会报错
//这个是4.0以后加入的一个东西,4.0之前不用管
ServiceRegistry serviceRegistry= new
ServiceRegistryBuilder().applySettings(cfg.getProperties()).buildServiceRegistry(); 
SessionFactory factory=cfg.buildSessionFactory(serviceRegistry);
Session session=factory.getCurrentSession();
//
Transaction tran=session.beginTransaction();
//以后代码只能放在这里面,不放在事务范围之内会报错。
User user =new User();
user.setAge(23);
user.setName("jack");

session.save(user);
tran.commit();
}
}


6.提取,修改成单例模式,因为事务之前的部分,只需要一次
SessionFactory sessionFactory每用一次,都会建一个数据库连接池所以整成单例的


public class HibernateUtil {
private static SessionFactory sessionFactory = builderSessionFactory();


private static SessionFactory builderSessionFactory() {
Configuration cfg = new Configuration().configure();//不调用configure()的时候会报错
//这个是4.0以后加入的一个东西,4.0之前不用管
ServiceRegistry serviceRegistry= new
ServiceRegistryBuilder().applySettings(cfg.getProperties()).buildServiceRegistry(); 

return cfg.buildSessionFactory(serviceRegistry);
}
public static SessionFactory getSessionFactory() {
return sessionFactory;
}
public static Session getSession() {
return getSessionFactory().getCurrentSession();
}


}


7.根据主键来查找对象
Hibernate: select user0_.id as id1_0_0_, user0_.name as name2_0_0_, user0_.age as age3_0_0_ from t_user user0_ where user0_.id=?


hibernate:冬眠。可以看到hibernate的查询语句,都会有很多的别名,是为了防止重复


Transaction tran=session.beginTransaction();
//以后代码只能放在这里面,不放在事务范围之内会报错。

//查找所有的对象,需要写hql,非常类似sql语句,
String hql="from User";
//这里面不需要写select和哪个列,只需要写from,后面跟类名,不是表名,因为hibernate操作的都是对象

Query query=session.createQuery(hql);//创建一个对象把hql传进去
List<User> userlist=query.list();//因为query.list()不是泛型集合所以有警告
for(User user:userlist){
System.out.println("id:"+user.getId());

}


/*//删除对象,在hibernate中都是以对象为操作,所以它和jdbc中删除是以主键不同。
//这个删除是以对象来删除,并且它需要先查找然后再删除
User user=(User) session.get(User.class, 4);
session.delete(user);
*/

/*//修改对象,先找到要修改的对象,02把对象的属性改一下即可,在提交的时候
//hibernate能感知到对象发生了变化,hibernate会直接同步
User user=(User) session.get(User.class, 3);
user.setAge(43);
user.setName("rose");*/

/*
//根据主键查询
User user=(User) session.get(User.class, 3);

System.out.println(user.getName());*/
//保存对象
/*User user =new User();
user.setAge(23);
user.setName("jack");

session.save(user);*/
tran.commit();


8.持久化对象的生命周期(持久化对象--就是这个pojo)
《已经学过的有生命周期的servlet,session,action,servlet.context,application。》


三个阶段:
瞬态(自由态):持久化对象的自由态,指的是对象在内存中存在,但是在数据库中并没有数据与其关联。
          比如Student student =new Student(),这里的student对象就是一个自由态的持久化对象。
         eg://保存对象
User user =new User();
user.setAge(23);
user.setName("jack");
一个对象如果没有和任何的session的API进行关联,没有进行session的方法就是自由态。
自由态这些对象做的所有操作和hibernate没有关系,只不过在内存中而已
没有经过session保存,
一旦经过session后就是持久态。


持久态:
指的是持久化对象处于由Hibernate管理的状态,这种状态下持久化对象的变化将会被同步到数据库中
在session.save(user);这句话之后就进入了持久态


user.setName("kkkk");
这时候就执行了两条sql语句,insert和update


tran.commit();
一旦事务进行了提交或回滚后就进入到了游离态,假如提交后再执行下句
user.setName("pppp");


托管态(游离态):
处于持久态的对象,在其对应的Session实例关闭后,此时对象进入游离态。也就是说Session实例
是持久态对象的宿主环境,一旦宿主环境失效,那么持久态对象进入游离状态。


9.三种状态的转化图(熟记)结婚论




10.延迟加载
//延迟加载/懒加载load,特点就是什么时候用,什么时候加载,必须要在session关闭前进行


• get和load方法都是利用对象的主键值获取相应的对象,并可以使对象处于持久状态。
• load方法获取对象时不会立即执行查询操作,而是在第一次使用对象是再去执行查询操作。如果查询的对象在数
据库中不存在,load方法返回值不会为null,在第一次使用时抛出org.hibernate.ObjectNotFoundException异
常。
• 使用get方法获取对象时会立即执行查询操作,并且对象在数据库中不存在时返回null值。
但是load有两个缺点:
load是延迟加载,但是它的缺点:
 01.关闭事务之后,再用它,会出现一个org.hibernate.LazyInitializationException
User user = (User) session.load(User.class, 3);
tran.commit();
System.out.println(user.getName());
 02.当load查询的不存在,就是说上面的id=3不存在,会报org.hibernate.ObjectNotFoundException


10.save和persist方法:
persist是jpa里面规定的一个方法,jpa中是没有save方法的但是其实都是保存


01.两个返回值类型不一样,persist是void
save是id的值


•save和persist方法都是将持久化对象保存到数据库中
• sava方法成功执行后,返回持久化对象的ID
• persist方法成功执行后,不会返回持久化对象的ID,persist方法是JPA中推荐使用的方法




11.save和update方法,看那个图-------9图
• save方法是将自由态的对象带入到持久态进行保存
• update方法是将游离态的对象带回到持久态进行保存


User user=(User) session.get(User.class, 3);//get进入持久态
tran.commit();
user.setAge(58);//游离态
Session session2=HibernateUtil.getSession();
session2.getTransaction();
//update之前都是游离态
session2.update(user);
//在commit之前update之后是持久态
session2.getTransaction().commit();




12.update和saveOrUpdate方法:
saveOrUpdate方法不仅能把自由态带到持久态,也能把游离态带到持久态
• 如果一个对象是游离态或持久态,对其执行update方法后会将对象的修改同步到数据库中,如果该对象是自由态,
则执行update方法是没有作用的
• 在执行saveOrUpdate方法时该方法会自动判断对象的状态,如果为自由态则执行save操作,如果为游离态或持
久态则执行update操作


这个就是不管你是自由态还是游离态都让你自己去判断。
Transaction tran = session.beginTransaction();
// 以后代码只能放在这里面,不放在事务范围之内会报错。

User user = new User();
user.setName("jijin");//自由态
session.saveOrUpdate(user);//save,insert
tran.commit();
user.setName("nihaoa");//游离态
Session session2 = HibernateUtil.getSession();
session2.beginTransaction();

session2.saveOrUpdate(user);//update


session2.getTransaction().commit();


13.update和merge方法
merge方法没有出现在图上,它和saveOrUpdate的作用是一样的,但他不改变对象的状态
 •如果持久化对象在数据库中存在,使用merge操作时进行同步操作。如果对象在数据库不存在,merge对象则进
   行保存操作
 • 如果对象是游离状态,经过update操作后,对象转换为持久态。但是经过merge操作后,对象状态依然是游离态

User user = new User();
user.setName("jijin");//自由态
session.merge(user);//save,insert
tran.commit();
user.setName("nihaoa");//自由态
Session session2 = HibernateUtil.getSession();
session2.beginTransaction();

session2.merge(user);//save,insert


session2.getTransaction().commit();
console:
这个就执行的是两个insert
Hibernate: insert into t_user (name, age) values (?, ?)
Hibernate: insert into t_user (name, age) values (?, ?)




User user = new User();
user.setName("jijin");//自由态
session.save(user);持久态
tran.commit();
user.setName("nihaoa");//游离态
Session session2 = HibernateUtil.getSession();
session2.beginTransaction();

session2.merge(user);//update


session2.getTransaction().commit();
//
console:
Hibernate: insert into t_user (name, age) values (?, ?)
Hibernate: select user0_.id as id1_0_0_, user0_.name as name2_0_0_, 
            user0_.age as age3_0_0_ from t_user user0_ where user0_.id=?
Hibernate: update t_user set name=?, age=? where id=?


//因为merge不管状态,当一个对象有id的时候,所以他会判断一下,他会根据id去找一下,
//他能找到,所以会认为它是游离态,所以执行update


14.saveOrUpdate和merge方法
saveOrUpdate方法和merge方法的区别在于如果session中存在两个主键值相同的对象,进行saveOrUpdate操作
时会有异常抛出。这时必须使用merge进行操作。
session.beginTransaction();
User user=new User();
user.setId(120);//这个就是错误的
user.setUserName("aaaaaaaa");
user.setUserPwd("123123");
User user2=(User)session.get(User.class,120);
session.saveOrUpdate(user);//ERROR,这个时候,在一个session空间中有两个id=120的
//值,用saveOrUpdate,会报错。但是用merge时候就可以通过
session.getTransaction().commit();


15.clear方法和flush方法
clear方法是将Session中对象全部清除,当前在Session中的对象由持久态转换为游离态。flush方法则是将持久态对
象的更改同步到数据库中。
  01.clear:
User user = (User) session.load(User.class, 3);
session.clear();
user.setAge(56);
tran.commit();


这个就是clear之后,user进入游离态。
但是只有持久态的对象,发生变化,才会被同步到数据库中,所以只会执行一个select不会执行update


  02.flush方法和状态没有关系
User user = (User) session.load(User.class, 3);
user.setName("jijin");
session.flush();


tran.commit();
若是没有flush()执行的时候会是先执行一个select,然后执行改变,只有在commit之后,
才会执行一个update
但是有了flush,就会flush执行之后就立即同步到数据库。




note:只有持久态的对象,发生变化,才会被同步到数据库中










































0 0