码迷,mamicode.com
首页 > Web开发 > 详细

Hibernate自学详细笔记

时间:2015-08-31 21:43:38      阅读:243      评论:0      收藏:0      [点我收藏+]

标签:hibernate   数据库   hql   

Hibernate配置文件
添加环境
1.Jar包
2.配置文件hibernate.cfg.xml/xxx.hbm.xml
3.使用hibernate实现增删改查
Configuration cfg = new configuration.config();
SessionFactory sessionFactory = cfg.buildSessionFactory();
Session session = sessionFactory.openSession();
Try{
Transaction  tx = session.beginTransaction().commit();
}catch(Exception e)
{
Tx.rollback();
}finally{
Session.close();
}
4.方法:save(object) / update(object) / delete(Object) / createQuery(hql) ./ get(class,id)
5.主配置文件:
数据库信息:方言、URL、驱动、用户名、密码
导入映射文件
其他的配置show_sql = true; hbm2ddl.auto = update;
6.映射配置
映射基础:无参的构造方法,get和set方法
映射普通属性name ,type, length , column ,not-null
映射的主键native,assigned,uuid,hilo等等






1  hibernate.cfg.xml
该文件配置了Hibernate需要的数据库的url以及账号和密码等等的信息
例如:
<!DOCTYPE hibernate-configuration PUBLIC
	"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
	"http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">

<!-- Generated by MyEclipse Hibernate Tools.                   -->
<hibernate-configuration>
	<session-factory>
		<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
		<property name="hibernate.connection.url">jdbc:mysql://localhost:3306/hibernate</property>
		<property name="hibernate.connection.username">root</property>
		<property name="hibernate.connection.password">mysql</property>
		<property name="dialect">org.hibernate.dialect.MySQLDialect</property>
		<property name="connection.pool_size">1</property>
		<property name="show_sql">true</property>
		<mapping resource="com/shangyanyuan/entity/User.hbm.xml"/>
	</session-factory>
</hibernate-configuration>


2  配置文件:User.hbm.xml
该文件负责对User进行映射的文件,配置了user的一些属性值和数据库中对应的属性以及相应的设置信息,如类型,是否为空。

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
                            "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
                            "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd" >
<hibernate-mapping>
	<class name = "com.shangyanyuan.entity.User" table="user">
		<id name = "id" type = "java.lang.Integer" column = "id">
			<generator class="increment"></generator>
		</id>
		<property name="username" type = "java.lang.String" column = "username" length = "20"></property>
		<property name="password" type = "java.lang.String" column = "password" length = "20"></property>
	
	</class>
</hibernate-mapping>


Name属性:对象中的属性名,这个必须要有的
Type属性:类型属性,如果不写的话Hibernate会自动的检测其类型
Column属性:对应着数据库当中的某一列。
Length属性:长度。
Not-null属性:非空属性。

如果说你现在设置好了User.hbm.xml这个文件,但是数据库当中没有该数据库,那么由这个配置文件Hibernate会自动的帮你在数据库当中生成该表。

注意:type的值如果大写的话可以这样java.lang.String(java中类型),小写的话string(Hibernate类型)即可。

图像,byte[] 的形式
在配置文件中类型对应着binary类型,最好是指定长度值。

主键:如果是int的话最好是设置为Integer类型,初始值int类型为0,而Integer则为null





3  主键生成策略:
Native 根据数据的性质自动的选择用那个生成策略。
Assigned 手动的指定它的值。使用UUID.randomUUID().toString();手动配置可保证唯一性。

Identity 使用数据库的自己的主键生成策略,但是oracle不支持。
Sequence oracle中使用这个,也可以db2等等数据库
Hilo 高低位算法来生成主键,只需要一张额外的表,所以的数据库都支持。
Increment 查询最大的id值然后加1增长,Hibernate帮助增长的,不推荐使用,多线程的情况下会有问题的。
Uuid 设定其主键生成策略为uuid即可实现与assigned中使用UUID.randomUUID().toString();的效果。




4 集合类型的数据的存储
Set 无序 不重复
List 有序 可重复
Map 无序 不重复
有序的集合无法配置使其排序,但是无序的集合可以通过配置的方式使其排序但是排序一般不会用到。


比如购物网站用户地址信息
Set集合 非常重要会经常用到
设置有序无序unsorted|natural|comparatorClass默认的方式是unsorted
需要设置的属性是sort属性

order-by属性order-by = “address DESC/ASC(默认是ASC)”



List集合
List集合是有顺序的所以在映射的时候需要配置这样几个属性:userid, address,idx(索引表示它的顺序)

这样设计它的映射文件中应该写为:
<list name = “addressList” table = “user_address”>
<key column = “userid”></key>
<list-index column = “idx”></list-index>
<element type = “string” column = “address”></element>
</list>


数组
<array name = “addressList” table = “user_address”>
<key column = “userid”></key>
<list-index column = “idx”></list-index>
<element type = “string” column = “address”></element>
</array>
Arrays.toString(“”);可查看数组的元素


Map集合

<map name = “addressMap” table = “user_addressMap”>
<key column = “userid”></key>
<map-key type = “string” column  = “key_”></map-key>
<element type = “string” column = “address”></element>
</map>


Hibernate特有的集合
Bag 无序,可重复
<bag name = “addressbag” table = “user_addressbag”>
<key column = “userid”></key>
<element type = “string” column = “address”></element>
</map>


5:set集合顺序问题
HashSet 无序的
TreeSet 有序,放入数据之后里面的数据是排好了顺序的
LinkedHashSet 有序的,按照放入的数据的顺序存放的



6:一对多的关系
外键在多的那一方中
例如员工部门的关系

package cn.itcast.f_hbm_oneToMany;

import java.util.HashSet;
import java.util.Set;

/**
 * 部门
 * 
 * @author tyg
 * 
 */
public class Department {
	private Integer id;
	private String name;

	private Set<Employee> employees = new HashSet<Employee>(); // 关联的很多员工

	

	@Override
	public String toString() {
		return "[Department: id=" + id + ", name=" + name + "]";
	}

}

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

<hibernate-mapping package="cn.itcast.f_hbm_oneToMany">
	
	<class name="Department" table="department">
		<id name="id">
        	<generator class="native"></generator>
		</id>
		<property name="name"/>
		
		<!-- employees属性,Set集合,表达的是本类与Employee的一对多 
			class属性:关联的实体类型
			key子元素:对方表中的外键列(多方的那个表)
			
			inverse属性:
				默认为false,表示本方维护关联关系。
				如果为true,表示本方不维护关联关系。
				只是影响是否能设置外键列的值(设成有效值或是null值),对获取信息没有影响。
				
			cascade属性:
				默认为none,代表不级联。
				级联是指操作主对象时,对关联的对象也做相同的操作。
				可设为:delete, save-update, all, none ...
		<set name="employees" cascade="all">
			<key column="departmentId"></key>
			<one-to-many class="Employee"/>
		</set>
		-->
		
	</class>
	
</hibernate-mapping>


================================================================

package cn.itcast.f_hbm_oneToMany;

/**
 * 员工
 * 
 * @author tyg
 * 
 */
public class Employee {
	private Integer id;
	private String name;

	private Department department; // 关联的部门对象
	@Override
	public String toString() {
		return "[Employee: id=" + id + ", name=" + name + "]";
	}
}

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

<hibernate-mapping package="cn.itcast.f_hbm_oneToMany">
	
	<class name="Employee" table="employee">
		<id name="id">
        	<generator class="native"></generator>
		</id>
		<property name="name" type="string" column="name"/>
		
		<!-- department属性,表达的是本类与Department的多对一 
			class属性:关联的实体类型
			column属性:外键列(引用关联对象的表的主键)
		-->
		<many-to-one name="department" class="Department" column="departmentId"></many-to-one>
		
	</class>
	
</hibernate-mapping>


测试

package cn.itcast.f_hbm_oneToMany;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.junit.Test;

public class App {

	private static SessionFactory sessionFactory = new Configuration()//
			.configure()//
			.addClass(Department.class)// 添加Hibernate实体类(加载对应的映射文件)
			.addClass(Employee.class)// 添加Hibernate实体类(加载对应的映射文件)
			.buildSessionFactory();

	// 保存,有关联关系
	@Test
	public void testSave() throws Exception {
		Session session = sessionFactory.openSession();
		session.beginTransaction();
		// --------------------------------------------

		// 新建对象
		Department department = new Department();
		department.setName("开发部");

		Employee employee1 = new Employee();
		employee1.setName("张三");

		Employee employee2 = new Employee();
		employee2.setName("李四");

		// 关联起来
		employee1.setDepartment(department);
		employee2.setDepartment(department);
		department.getEmployees().add(employee1);
		department.getEmployees().add(employee2);

		// 保存
//		session.save(employee1);
//		session.save(employee2);
		session.save(department); // 保存部门

		// --------------------------------------------
		session.getTransaction().commit();
		session.close();
	}

	// 获取,可以获取到关联的对方
	@Test
	public void testGet() throws Exception {
		Session session = sessionFactory.openSession();
		session.beginTransaction();
		// --------------------------------------------

		// 获取一方,并显示另一方信息
		Department department = (Department) session.get(Department.class, 1);
		System.out.println(department);
		System.out.println(department.getEmployees());

		// Employee employee = (Employee) session.get(Employee.class, 1);
		// System.out.println(employee);
		// System.out.println(employee.getDepartment());

		// --------------------------------------------
		session.getTransaction().commit();
		session.close();
	}

	// 解除关联关系
	@Test
	public void testRemoveRelation() throws Exception {
		Session session = sessionFactory.openSession();
		session.beginTransaction();
		// --------------------------------------------

		// // 从员工方解除
		// Employee employee = (Employee) session.get(Employee.class, 1);
		// employee.setDepartment(null);

		// 从部门方解除(与inverse有关系,为false时可以解除)
		Department department = (Department) session.get(Department.class, 1);
		department.getEmployees().clear();

		// --------------------------------------------
		session.getTransaction().commit();
		session.close();
	}

	// 删除对象,对关联对象的影响
	@Test
	public void testDelete() throws Exception {
		Session session = sessionFactory.openSession();
		session.beginTransaction();
		// --------------------------------------------

		// // 删除员工方(多方),对对方没有影响
		// Employee employee = (Employee) session.get(Employee.class,2);
		// session.delete(employee);

		// 删除部门方(一方)
		// a, 如果没有关联的员工:能删除。
		// b, 如果有关联的员工且inverse=true,由于不能维护关联关系,所以会直接执行删除,就会有异常
		// c, 如果有关联的员工且inverse=false,由于可以维护关联关系,他就会先把关联的员工的外键列设为null值,再删除自己。
		Department department = (Department) session.get(Department.class, 4);
		session.delete(department);

		// --------------------------------------------
		session.getTransaction().commit();
		session.close();
	}

}







多对多


对于老师的hbm的配置文件应该是:
<!--
Teacher属性,Set集合
表达的是本类与Teacher的多对多的关系
Table属性:中间表(集合表)-->一定要一致
Key子元素:集合外键(引用当前表主键的那个外键)
-->
<set name = “teachers”  table = “t_teacher_student”>
<key column = “studentId”></key>
<many-to-many class = “Teacher” column = “teacherId”></many-to-many>
</set>

对于学生类的hbm的配置文件应该是:
<set name = “students”  table = “t_teacher_student”>
<key column = “teacherId”></key>
<many-to-many class = “Student” column = “studentId”></many-to-many>
</set>


默认的是双方都维护中间表中这个数据库的数据,与inverse有关,inverse = true那么本方不维护。
多对多的时候inverse = false的时候,能维护关联关系,那么先接触关联关系然后再删除。但是inverse = true 的时候,如果本身不维护的话就直接删除但是这样会报错(因为存在着关联关系)。

Cascade属性
级联
默认的是none
操作本对象的时候对于与之关联的对象也做相同的操作
可以设置的值是delete,save-update,all,none


7. Session对象

Session.save(“”);Session.save(“”);
Session.save(“”);Session.save(“”);
只会执行一次insert语句。

session.save(“sdfsdfsdf”);session.flush();立即执行
Session.evict(user);清除某一个指定的对象
一.操作实体对象的
Save(),update(),saveOrUpdate(),delete()
Save()的时候直接就执行而不是等到提交的时候才执行。

二.操作缓存的
Clear(),evict();flush();

三.查询实体对象的
Get();load();createQuery();createCriteria();
Load()不是马上执行,只有在你用的时候才会执行






Hibernate事务隔离级别
<property name = “connnection.isolation”>1(读未提交)/2(读已提交)/4(可重复读)/8(串行化(不可并行))</property>






一对一映射

基于外键的方式:
1. 在person的配置文件中,其配置文件当中没有外键,property-ref属性写的是对方映射中外键列对应的属性名。
采用<one-to-one name = “” column = “”></one-to-one>标签

2.在idcard的配置文件中设置有外键的
<many-to-one name = “”  class = “” column = “” > </many-to-many>
注意:从有外键的哪一方解除关系可以的,但是从没有外键的哪一方解除关系是不可以的,只能由有外键的哪一方去解除关联关系。

基于主键的方式:
1. 在Person的配置文件当中
采用<one-to-one name = “idcard” column = “Idcard”></one-to-one>标签
2.在Idcard的配置文件当中
采用:
<one-to-one name = “person” column = “Person” constrained = “true”></one-to-one>标签

注意当使用一对一基于主键方式的时候,有外键方的主键生成策略一定要是foreign
<generator class = “foreign”>
<param name = “property”> person </param>
</generator>

删除时如果是没有外键的那一方(和对方的外键值有关联关系),直接执行删除动作的时候会发生异常,因为和对方的外键值有关联关系,但是如果是对方进行删除的话不会出现异常。
继承结构的:
1.设计表的时候可以将所有的内容都放在一张表中。不过一行中往往会有多个null的值

配置文件:
<!-- 
		discriminator-value属性:
			用于鉴别是哪个类的一个值,表示这个值就是这个类。
			如果不写,默认为类的全限定名。
	 -->
	<class name="Article" table="article" discriminator-value="Aticle">
		<id name="id">
        	<generator class="native"/>
		</id>
		
		<!-- 用于鉴别是什么类型的一个列 -->
		<discriminator type="string" column="class_"></discriminator>
		
		<property name="title"/>
		<property name="content" type="text" length="10000"/>
		<property name="postTime" type="timestamp"/>
		
		
		<!-- 子类:Topic -->
		<subclass name="Topic" discriminator-value="Topic">
			<property name="type"></property>
		</subclass>
		
		
		<!-- 子类:Reply -->
		<subclass name="Reply" discriminator-value="Reply">
			<property name="floor"></property>
		</subclass>






2. 
<!-- 采用每个类一张表的方式,抽象类也对应表。 -->
	<class name="Article" table="article2">
		<id name="id">
        	<generator class="native"/>
		</id>
		<property name="title"/>
		<property name="content" type="text" length="10000"/>
		<property name="postTime" type="timestamp"/>
		
		
		<!-- 子类:Topic -->
		<joined-subclass name="Topic" table="topic2">
			<key column="id"></key>
			<property name="type"></property>
		</joined-subclass>
		
		
		<!-- 子类:Reply -->
		<joined-subclass name="Reply" table="reply2">
			<key column="id"></key>
			<property name="floor"></property>
		</joined-subclass>
		
	</class>

3.


<!-- 采用每个具体类一张表的方式,抽象类不对应表。
		abstract默认为false,设为true表示本类不对应表(类可以不是abstract的),这时就会忽略table属性。
	 -->
	<class name="Article" abstract="false" table="article3">
		<id name="id">
			<!-- 
				当使用每个具体类一张表的方式时,主键生成策略不能是identity。
				因为在整个继承结构中,主键值是不能重复的。
			 -->
        	<generator class="hilo">
        		<param name="table">hi_value</param>
                <param name="column">next_value</param>
                <param name="max_lo">100</param>
        	</generator>
		</id>
		<property name="title"/>
		<property name="content" type="text" length="10000"/>
		<property name="postTime" type="timestamp"/>
		
		
		<!-- 子类:Topic -->
		<union-subclass name="Topic" table="topic3">
			<property name="type"></property>
		</union-subclass>
		
		
		<!-- 子类:Reply -->
		<union-subclass name="Reply" table="reply3">
			<property name="floor"></property>
		</union-subclass>
		
	</class>












8 HQL语句


Auto-import 表示在HQL语句中写类的简单名称时,是否自动的导包




QBC方式查询 :Query by Criteria




一对一的只有有外键的那一方才能维护关系。

继承结构的映射
1.所有的数据都放在一张表当中去,当然很多的列会存在=null的情况。
2.每个类对应着一张表,包括抽象类也有自己的一张表。
3.每个具体的类都对应着一张表但是抽象类不对应着表。

HQL语句查询的是对象和属性。
关键字不区分大小写,但是类名和属性名的话区分大小写。
语法 FROM 实体 AS E
Where / Order by / group by  、having /  

Lazy属性
True:第一次的时候加载
False:及时的加载
Extra:增强的懒加载策略。




Hibernate连接池
使用C3P0连接池需要导入C3P0的包,只需要在Hibernate的配置文件当中进行设置即可

<!-- C3P0连接池设定-->
		<!-- 使用c3p0连接池  配置连接池提供的供应商-->
		<property name="connection.provider_class">org.hibernate.connection.C3P0ConnectionProvider                                                                                                                                                     </property>
		<!--在连接池中可用的数据库连接的最少数目 -->
		<property name="c3p0.min_size">5</property>
		<!--在连接池中所有数据库连接的最大数目  -->
		<property name="c3p0.max_size">20</property>
		<!--设定数据库连接的过期时间,以秒为单位,
		如果连接池中的某个数据库连接处于空闲状态的时间超过了timeout时间,就会从连接池中清除 -->
		<property name="c3p0.timeout">120</property>
		 <!--每3000秒检查所有连接池中的空闲连接 以秒为单位-->
		<property name="c3p0.idle_test_period">3000</property>

二级缓存:EhCacheProvider(比较强大些)(使用之前要导入三个jar包+ehcache.xml(直接拷贝用稍微修改即可))
<!-- 使用二级缓存,默认是未打开的。 -->
		<!-- 指定要使用的缓存的提供商,这也就打开了二级缓存 
		<property name="cache.provider_class">org.hibernate.cache.HashtableCacheProvider</property>
		-->
		<property name="cache.provider_class">org.hibernate.cache.EhCacheProvider</property>
		<!-- 开启使用查询缓存 -->
		<property name="cache.use_query_cache">true</property>
		<!-- 指定要使用二级缓存的实体类 -->
		<class-cache usage="read-write" class="cn.itcast.l_second_cache.Employee"/>
		<class-cache usage="read-write" class="cn.itcast.l_second_cache.Department"/>
		<collection-cache usage="read-write" collection="cn.itcast.l_second_cache.Department.employees"/>
	
		<!-- 导入映射文件 
		<mapping resource="cn/itcast/a_helloworld/User.hbm.xml"/>
		-->
	
HashTable -->线程安全的,但是速度回慢一些
HashMap-->线程不安全的,速度快一些。


getCurrentSession只要是存在Session的时候就不会创建新的Session,当发生提交或者回滚后,Hibernate会自动的关闭Session

但是openSession则不一样,每次都是重新创建一个新的Session。

版权声明:本文为博主原创文章,未经博主允许不得转载。

Hibernate自学详细笔记

标签:hibernate   数据库   hql   

原文地址:http://blog.csdn.net/wangyang1354/article/details/48140191

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!