⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 hibernate_note.txt

📁 加拿大达内科技的hibernate学习笔记
💻 TXT
📖 第 1 页 / 共 3 页
字号:
				共享主键:

					主键做外键,方法简明.节省一个字段,利用one-to-one标签.



					

		映射文件:

			唯一外键:

			po1{ 

				Long oid;

				Po2 po2;

			}

			<class >

				<id>产生的机制是随便的</id>	

				/*<one-to-one>//这里不能用一对一,对这个属性进行一对一映射

						这个属性在数据库里面对应的是个外键,而外键对应的关系是多对一.

						所以要写<many-to-one>,单向关系只用在一方表达.

				*/

				<many-to-one 

					nome="po2" 

					class="Po2" 这个可以不用写

					column=oid2 表示应用的外键

					unique=true 表示该字段是唯一的.

					cascaded="all"//因为是关联属性所以级联也要说明,就是在数据库里面对PO1的操作要把po2也进行操作.

				/>

			</class>

			共享主键:	

				po不用改.

				主键的产生方式就需要改变

			<id name="oid" column="oid">我的oid的值是从我关联的对象来的

				<generator class="foreign">id生成策略变成外键

						我的主键从外边来,从addr属性来

					<param name="property">addr</param>它是从属性address里获得的.

				</generator>

			</id>

			关联字段变成

				<one-to-one 

					name="addr"

					constraint="true"//addr属性约束了自己所在类的主键的生成.

						表明该类对象的数据库表和被关联对象对应的数据库表之间,通过一个外键引用对主键进行约束

						影响save和delete方法,在级联操作时候的先后顺序

					cascade="all"

				/>

			主键的值在这个属性里面.

			oid的值是从addr属性,的aid里面来,aid是用hilo计算出来的.计算之后就引用到oid

			所以addr的aid即使主键也是外键.

			是以属性来描述的,oid的值是来自于aid,constraint表示addr约束了oid的值.

			双向的地方对方再加一个one-to-one



			一般都会使用共享主键来表示一对一.



集合映射:

mapping collection of value types

值类型:

	指的就是非引用类型.基本类型在集合里面变成包装类和字符串都是值类型.

	现在存的不是自定义的对象,而是整个基本类型和字符串.

	退化的1对多:

		一个po和字符串之间的对应关系.

	set

		元素不重复,无顺序.

	集合里面每个元素都是字符串.

	映射:

		private Set images=new HashSet();

		images要映射到其他的表里面,这两个表直接用外键来关联.

		集合实际上是存入到另外一张表里面.

		<set 

			name="aliases" 集合

			table="t_aliases"对应的表

		>

			<key column="aid">这个table的外键

			<element type="string" column="aliase"> type不可以省略,集合元素的字段,从集合的角度来说,集合里面的元素

		</set>

		set表示的这张表不是po就没有必要有主键,里面key和表里的id并不是主键,是外键,

		需要主键的话可以建立联合主键

			drop table t_aliases;

			drop table t_person;

			create table t_person(

				oid integer(11) primary key,

				name varchar(11) not null

			);

			create table t_aliases(

				aid integer(11) references t_person(oid),

				aliase varchar(50),

				constraint person_aliases primary key(aid,aliase)

			);



一对多 association

	the most important kind of association

	双向,一对多:

	PO1里面有多个PO2的引用,如果每个PO2里面都有一个PO1的引用,那么就是双向一对多

	再java的内存里面,一方有Set引用另一个类型,另一个类型里面有该类型的一个引用.双向一对多.

	Company{Set<Employee> employees}       1:n     Employee{Company compay;}

	尽量设计成双向,业务一但变化,从那边都可以查到对方.

	注意多的一方要加上equals和hashcode方法



	在映射里面有个关联属性:

		关联属性是company,再company里面是employees

		po是有表的,set里面全是employee对象,employee对应的有表,employees不对应表

	<set 

		name="employees" 

		cascade="save-update" 除了删除操作其他操作都进行.

	>

		<key column="fid"></key>

		employee表的外键.e这边多,多的这一方的表起到关联作用的是外键,

		一的这一方起关联作用的表是主键

		e和c 是一对多的关系,

		e里面有c的一个引用,这个引用就是用fid这个外键代表,fid指向c这边的主键.

		有集合的这一方是 一,没有集合的这一方是 多

		<one-to-many class="Employee"></one-to-many>

	</set>

	关联属性之所以配置复杂,

	employees表达的是一对多,在数据库里面就是主键对外键,

	索引这个key是引用我这边主键的外键.

	

	从e关联到c

		这个关联属性应用特殊的多对一标签



	你要存c就有c来维护这个关系,

		你要存c的时候就会先去存e,e呢又有个外间字段,这个字段是空的,我存完e之后,再存c然后才有主键,

		那么e才把外键值set进去.



		可以用一个属性来解决.invers="true"



	改动po给po一个添加成员的方法

		public void hire(Employee e){

			if(employees!=null){

				employees.add(e);

			}

			e.setCompany(this);

		}



		public void setCompany(Company company) {

		this.company = company;

		company.hire(this);

		}

		这两种写法都是可以的,只是只有一方就够了,

		从逻辑上决定权再公司.



		再oracle上,eid的值并没有生成,相应的e的hashcode和equale方法都报错.

	

		在<set inverse="true" 存c的话那么碰到inverse就会把主控交给e,e就会现存c在存自己这个时候就有外键了.

		>

		如果你是关系的主控方你就要先存对方,然后在存自己,这样能最大程度的保证自己的数据完整性,就不会有外键为空的情况.



inverse=true

log4j:WARN No appenders could be found for logger (org.hibernate.cfg.Environment).

log4j:WARN Please initialize the log4j system properly.

Hibernate: insert into T_Company (name, cid) values (?, ?)

Hibernate: insert into T_Employee (name, fid, eid) values (?, ?, ?)

Hibernate: insert into T_Employee (name, fid, eid) values (?, ?, ?)

Hibernate: insert into T_Employee (name, fid, eid) values (?, ?, ?)



inverse=false

log4j:WARN No appenders could be found for logger (org.hibernate.cfg.Environment).

log4j:WARN Please initialize the log4j system properly.

Hibernate: insert into T_Company (name, cid) values (?, ?)

Hibernate: insert into T_Employee (name, fid, eid) values (?, ?, ?)

Hibernate: insert into T_Employee (name, fid, eid) values (?, ?, ?)

Hibernate: insert into T_Employee (name, fid, eid) values (?, ?, ?)

Hibernate: update T_Employee set fid=? where eid=?

Hibernate: update T_Employee set fid=? where eid=?

Hibernate: update T_Employee set fid=? where eid=?



控制权就要交给多的这一方,所以inverse=true就是 (控制权翻转) 

在set的关联属性上写inverse那么就是我不管了,把主控交给多个一方.多的一方就会先加载一的一方.

由多的一方维护.



写一个工具类:

	直接的返回Session给我们使用。



<set 

	name="employees",

		集合属性表达的就是一对多.

	cascade="save-updata"

		级联操作.除了删除的所有操作.

	inverse="true"

		现存关系的另外一方,然后在存自己.

>

	<key

		column="fid"

			one-to-many标签里面,class所描述类型对应的表中的外键.

	>

	<one-to-many 

		class="Employee"

			Employee表示当前类和它的一对多关系,通过类型描述了它所对应的表

	>

</set>



<many-to-one 

	name="company"

		表达多对一的关系,数据库里面用fid表示,表示company对应的表的外键.

	column="fid"

		这个外键字段的fid

>



多对多 many-to-many

	将两个表要表达的多对多,要利用一张中间表,来表达多对多的关系.

	Student	1	n

	Course		m	1

	一个学生选多门课程,一门课程可以被多个学生选则.

	多对多从逻辑上是个很复杂的情况.

	可是你从学生对象里面看不出自己这一方是多还是一,只能知道course是多.

	<set name="courses" table="t_enrollment">

			<key column="fsid"></key>

			<many-to-many //po里面就成了,多对多.

			></many-to-many>

		</set>

	必须要加inverse属性,如果不加会抛出唯一性约束错误.



第四章,

	Working with Persistent Objects

	持久对象的状态管理.



po的状态,

	并不是结构的问题,是po和它托管环境之间的问题.非托管的环境.

	po当我们吧一个持久对象new出来之后:

		这个对象和数据库没有关系.为什么说它有关系呢,通过.hbm.xml来描述关系,这是逻辑上的关系,实际并没有关系,

		因为数据库里面并没有数据,这是一种状态.

		当对象被存入数据库之后,数据库确实有了这个数据这又是一种状态.

		session又一级缓存,会保存对象的一份副本,对象和副本的变化,这就优势一种状态.

		session的save student就和session有了关系和数据库也有了关系,

		当我们将session关闭,那么session的缓存就不存在,对象和session就没有关系了,但是数据库里面有记录了,就又是一种状态.

		

		持久对象的三种状态

		1,db没有data,和session无关:瞬态(自由态)(暂态),不被session管,在内存中不在数据库中.

		2,db中又data,和session有关:持久态,数据库里面有持久数据,而且受session的管理随时和数据库保持同步.

		3,db中有data,和session无关:脱管态(游离态),脱离了session的管理.

	po有几种状态,有几种特征.

		Transient

		Persistent

		Detached

		状态的转化的中间就牵扯道很多语法.

		所有的方法都是session的.



	new -> Transient

		在class标签里面,unsaved-value 默认是等于null,如果希望没有存就等于1

	Transient -> Persistent

		save()	非常去定对象是个transient的对象,这种对象的初始值有 class标签的unsaved-value指定.

			用Long那么默认值就是null,如果用long默认值就是0,那么不能直接和unsaved-value的默认值一致了.当然可以自己指定.

		saveOrUpdate() 不确定是什么状态的对象

	Persistent -> Transient

		delet(o),到数据库里面去吧记录删除,但是对象的oid依然还存在,

			这个对象就还可以进行save但是不能进行saveOrUpdate,因为他又oid它就会去做更新,可是数据库里并没有对应的记录了.

			hibernate可能认为oid的值和业务有关

			已经是持久对象了还要删除它,所以并不经常用了,

	Persitent -> Detached

		close()		session关闭,那么session里面的所有对象都是脱管对象.

		clear()		session里面有个缓存,保存持久对象的引用,那么一旦调用clear清空了缓存那么session就不认识这些持久对象了,对象变成游离态.

				session还在.所有持久对象都全变成游离态

				s.save(stu);stu.setName("Tony");如果现在是持久态那么就不用再做更新操作,直接对session做flush或者吧事务commit就可以了.

		evict(po)	把po从session的缓存里面删除掉.

				这三个函数就可以把持久对象变成

	Detached -> Persistent

		update(po)	和session再建立联系就可以了.把po和数据库做一个同步.po如果是自由态的那么就报错,对持久态po没有用.

				脱管的po回到session的管理下.

		saveOrUpdate(po) 和update()用处一样.交给hibernate自己判断是什么状态的对象.

		lock(po)	只是和session进行联系,并不跟数据库做同步操作

	开始 -> Persistent

		这个开始到持久,表示的是session从数据库里面把对象恢复出来到程序里面.

		恢复对象的方法:

			get(stu.class,oid); 取得指定对象.		

			load(stu.class,oid); 取得指定对象.

			find(); 现在已经不用了.

			iterate(); 现在已经不用了.

			etc

		select 对应的有多种方法.真正的数据的程序,一般都要求你用一个select解决问题.

		但是hibernate里面不能用sql,要用oo的方式,要用HQL.这些函数加上HQL读出来的结果都是持久态对象,

	garbage jvm	

		只能回收Transient和detached,

		persistent状态的有引用再session里面



	整个图把session的使用完全的列出来了.



Session的读取方法:

	get(Class,oid),如果找不到所要的数据,不会抛异常,返回一个null.

	load(Class,oid),如果找不到所要的数据,就会抛出异常.这个异常可以不用捕捉.

	get方法使用立即加载的方式发送sql,

	load方法只有对象被访问的时候会发送sql

	他们其他的地方都一样,返回要查的对象Object

	练习:



cascade="none"忽略级联

		save-update关联关系只用来进行插入和更新.

		delete 删除

		all 所有操作都级联操作.

		all-delete-orphan 删除关联的时候把持久对象也一起删除

		delete-orphan 从关系种脱离的持久对象也删除.



	one-to-one 里面一般是用all

	one-to-many save-update





批量更新:Batch update

	语法:

		for(int i=0;i<100000;i++){

			Customer customer=new Customer(....);

			session.save(customer);

		}tx.commit();session.close();

	如果hibernate的批量处理那么,hibernate的缓存里面有个对象大小相似的副本,

	一旦进行10万次就会出现,OutOfMemoryException.

	那么就只能在中间过程种进行flush();

	for(int i=0;i<100000;i++){

			Customer customer=new Customer(....);

			session.save(customer);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -