超牛牪犇Java之Hibernate (下)

一. 实体类的映射文件

文件名:实体类名.hbm.xml

<?xml version="1.0" encoding="UTF-8"?>
<!-- 提示去哪复制?
	Web App Library -> hibernate-core-5.2.10.Final.jar -> org.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">
    <!-- 配置表与实体类的关系 
    	name:实体类的全类名
    	table:表名
    	package:包名 填上后 下面写全类名时可以省略包名
    -->
<hibernate-mapping package="com.commander">
    <class name="实体类全限定名" table="数据库中对应的表名">
    	<!--  
    		id:表示主键
    		注意:没有主键不能使用hibernate
    		name:表示类中的成员变量名
    		column:表示这个成员变量所代表的表中的字段名
         -->
    	<id name="实体类中与数据库中对应的主键名" column="数据库中的主键名">
    		<!-- 主键的生成策略 这里用主键自增策略 -->
    		<generator class="主键生成策略(native)"></generator>
    	</id>
    	<!-- 
    		property:表示除主键以外的属性
    	 -->
    	<property name="实体类属性名" column="数据库中对应表中的字段名"></property>		
    </class>
</hibernate-mapping>

主键的分类:

规则:不能重复 不能修改

1.自然主键

表里有一个属性 符合主键的规则

就直接使用这个字段作为主键

2.代理主键

表里面没有一个字段 符合主键的规则

自己创建id 作为表的主键 这个键就叫代理主键


主键生成策略(七种)

1. identity

主键自增 使用数据库中的主键自增

插入时 打印sql时 不会插入id

2. increment

主键自增 由hibernate来管理

插入数据时 会先去数据库中查询当前最大id

然后把查出来的id+1 再插入数据

3. uuid

全球不重复的唯一标识(32位 字符串)

注意:id必须使用字符串类型

4. native(最常用的 三合一)

根据你使用数据库类型来选择使用

下面三个策略之一

所有数据库不是支持identity 就是支持序列

identity + sequence + hilo

5. hilo(高低位算法)

将主键交给hibernate处理 使用自己的算法 帮你维护主键

6. assigned

由你自己维护主键 插入数据时需要有主键

使用的代理主键

7. sequence oracle数据库默认的

二. 主配置文件

文件名: 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 >
	<!-- hibernate数据库配置 -->
		<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
		<property name="hibernate.connection.url">jdbc:mysql://localhost:3306/hibernate01</property>
		<property name="hibernate.connection.username">root</property>
		<property name="hibernate.connection.password">123456</property>
		
		<!-- 加载mysql的方言包 limit -->
		<property name="hibernate.dialect">org.hibernate.dialect.MySQL5InnoDBDialect</property>
		<!-- 开启打印sql语句 -->
		<property name="hibernate.show_sql">true</property>
		<!-- 开启格式化sql语句 -->
		<property name="hibernate.format_sql">true</property>
		<!-- 自动更新表结构 没有表会帮你创建出来表 -->
		<property name="hibernate.hbm2ddl.auto">update</property>
		<!-- 
				设置数据库隔离级别 
				默认隔离级别是4 (1|2|4|8)
				#hibernate.connection.isolation 4
				1.脏读
				2.不可重复读
				3.幻读
				隔离级别
				READ UNCOMMITED 读未提交  123		-  1
				READ COMMITED 	读已提交   23		-  2  
				REPEATABLE READ	可重复读    3		-  4
				Serializable 	串行化   都能避免	-  8
				隔离级别使用1个字节来存储的
				0001
				0010
				0100
				1000
		-->
		<property name="hibernate.connection.isolation">4</property>
		
		<!-- 自动生成表结构 
		(etc/hibernate.properties)
				 update(常用)
				 自动生成表结构 如果映射文件和数据库表不对应 将会修改你的表字段
				 但是原来表的自断不会改变 会新增字段
				 create 
				 每次运行都会创建一个新的表出来(数据丢失)
				 create-drop 
				 每次运行都会创建一个新的表出来
				 每次运行结束都会把表删了
				 validate
				每次都会验证你的表结构
				如果实体类与映射文件不同 将会抛出一个异常
		-->
		<property name="hibernate.hbm2ddl.auto">update</property>
		
		<!-- 
				注意:使用getCurrentSession方法 必须配置
				配置的是让当前的session与线程绑定
		 -->
		<property name="hibernate.current_session_context_class">thread</property>
		
		<!-- 映射数据库表对应的映射文件的路径
				路径从包名开始写 并且中间使用的是反斜杠/
		 -->
		<mapping resource="com/commander/User.hbm.xml"/>
		
	</session-factory>
</hibernate-configuration>

三. 两种从session工厂中获取session的方法

1. openSession

是创建一个全新的session

Configuration configuration = new Configuration().configure();
sessionFactory = configuration.buildSessionFactory();
Session session = sessionFactory.openSession();

2.getCurrentSession

获取的是当前使用的session

Configuration configuration = new Configuration().configure();
sessionFactory = configuration.buildSessionFactory();
Session session = sessionFactory.getCurrentSession();

注意: 使用该方法 必须在主配置文件中配置一下 在<session-factory>标签内中加上下面一条

<property name="hibernate.current_session_context_class">thread</property>

四.hibernate操作对象的三种状态

1.瞬时态

没有ID  没有跟session产生关系

2.持久态 

有ID  跟session产生了关系

3.游离态

有ID  没有跟session产生关系

hibernate在操作数据库时 就是将持久态的对象同步到数据库

比如:

@Test
public void fun1() {
	//保存一个用户
	Session session = HibernateUitl.getOpenSession();
	Transaction transaction = session.beginTransaction();
	
	User user = new User();//瞬时态
	user.setUsername("taylor");		

	session.save(user);//持久态
			
	transaction.commit();
	session.close();//游离态
}

hibernate会在你提交事务之后 把持久态的对象同步到数据库

@Test
public void fun2() {
	Session session = HibernateUitl.getOpenSession();
	Transaction transaction = session.beginTransaction();

	//使用get方法查询一个对象
	User user = session.get(User.class, 1);
	user.setUsername("swift");
			
	transaction.commit();
	session.close();
}

存储时 有两种:

缓存(读写速度快 效率高)

硬盘(读写文件 速度慢)


当你调用get方法去数据库查询时 数据库给你返回的结果集 会被hibernate封装成对象

并且会在缓存中保存一份

当你再次用get方法查询时 hibernate会先到缓存中去查找 有没有该id的对象

有就直接返回缓存中的对象

没有就使用sql语句去操作数据库查询

@Test
public void fun3() {
	Session session = HibernateUitl.getOpenSession();
	Transaction transaction = session.beginTransaction();
	
	User user1 = session.get(User.class, 1);
	User user2 = session.get(User.class, 1);
	User user3 = session.get(User.class, 1);
	User user4 = session.get(User.class, 1);
	User user5 = session.get(User.class, 1);
	System.out.println(user2 == user5);
			
	transaction.commit();
	session.close();
}

测试时只打印一次sql查询语句

快照:

用get方法查询时 

hibernate会把结果集保存到缓存中一份 也会在快照中保存一份

当你最终提交事务操作数据库的时候hibernate会对比缓存与快照中的数据

一样就不存了 反之会同步到数据库

@Test
public void fun4() {
	Session session = HibernateUitl.getOpenSession();
	Transaction transaction = session.beginTransaction();
		
	User user = session.get(User.class, 1);
	user.setUsername("taylorSwift");
	user.setUsername("mayDay");
		
	session.update(user);
			
	transaction.commit();
	session.close();
}
sql语句会打印两次 : select 和 update

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值