hibernate学习笔记3

13   hibernate核心

表和表的关系:

常见有7中关系:

单项关系一下四种       

1-1  外键1-1,主键1-1的关系

1-n

n-1

n-n

多项关系:互相使用;

1-1

1-nn-1

n-n

   以下有两个表,user_info、和login连个表。表和字段如下;

User_info

Uid  truename  phone   sex

 

Longin

Lid   longinname  password  uid

这里建立了user类和longin类,同事newuser

User表中不含login字段,但是longin表中有user_info字段,但是在login的类中加入了user应用;

注:a单项外键1-1中第一个表的主键是另外一个表的外键,所以在另外一个表里,这个外键不受约束可以随便写。为了达到主外键一一对应就用到unique写法如下

<many-to-one name="user" column="uid" not-null="true" class="User" unique="true" cascade="all">

</many-to-one>当把配置文件和类写好就可以自动生成数据库连接表了;

保存的时候:这里先将user先存入进去,因为只有主键先获得持久化才能跟其他表有关系;注意外键配置时候必须不能为空;也就是说user_info是父表,另外的表longin为子表,但查询的时候必须先查询子表,也就是login表,因为user_info表中没有login表中的属性,但login表中有user_info的应用:

//这里只保存了一个关联表被关联的不保存一般会报错,但是有这样的配置就会保存一个表:级联(如:两表通过 id字段建立一对一关系,同时选项上了实施参照完整性”“级联更新相关字段”“级联删除相关记录,目的是实现,当在employee建立新用户时,同时自动在user_right表中给其建立相应的权力记录,但我发现如在employee中新增一个用户时,user_right并没有同步增加一条记录,但是在employee中删除一个用户时,user_right中却会同步更新!):cascade(级联)="all"它将配置的关联和被关联的对象共存亡;

多项外键1-1:其它不变就是对象的模型变了,在user表中加入(表名)longin对象字段,也就是双向包含,所以在user配置中加入了<one-to-one name="login"class="Login"property-ref(表示关联对方的属性)="user"></one-to-one>这样保存数据顺序和上一致,但是查询可以是反向和正向,有利于查询

b共享主键关联:可以是主键名不一样,但主键值必须一样,也就是关系模型有变化,对象模型则不会变化;

1-1的单项共享主键关联:主键在longin中,所以先创建longin在创建user

           1-1的双项共享主键关联:保存的时候以login的主键为主,所以先保存login:查询则无所谓;

     单项n-1:先保存有主键的对象在保存无主见的对象;<many - to-one></many-to-one>,连个表字段:

                                   T_room                        user

                                   Id  idname            1    ----   n    id  username   rooomid

       双项n-1:数据库不变,只是变对象用到private Set<User> users;,一个循环语句for(User user:users)

     单项1-n:主控权放在1的上面,而n-1主控权在n的一方,所以在1的一方加上引用

                              room  1-------- n    user

        双项1-n:就是在在n的一方加上引用,在user方加上<many -to-one>

                                   注:在1掌控的时候,会发送多余的sql语句(update),所以效率就下降了,所以可以在配置文件中加入inverse=true反转(就是将主控权交给多的一方,false的话就是自己掌控),这时候注意的是操作数据只能从n的一方去操作;而有n掌控时候就不会发多余的;

   n-n的关系:实现的时候需要一个中间表,中间表中有连个字段,它们就是联合主键(联合主键就是这个表里字段值不能一样的,两个字段加起来做一个主键),保存的时候先保存无set的那个对象;映射是<many -to- many>.

                      在双项多对多中要从两个对象中分别查询的话配置xml文件是一样的;(也就是<set>配置)

集合映射:中的例子映射,一般用set设置的值不会有顺序的。而用list设置的值就会有顺序的(这里的list是个接口,不能是arrylist,但是new的时候就得是arrylist),同样的也要修改配置文件

                     

继承映射:将对象的映射关系在表里面体现出来     

1)每个类分层结构一张表:一个父类不管他有多少子类都将他们与父类数据放入一张表中;

       也就是整个树一张表,subclass代表子类它的名字与类名绑定的,discriminator是个鉴别器这里的type就是鉴别器,是用来识别数据类型的一个字段,

  例子如下:父类是persion,两个子类是studentwork

                Id   name   age     school          factory            type

           1        aaa             55              qinghua                           s

        2   bbb      22                     shuoshuodian        w

   有这张表体可以看出只有学校和工厂才能分清楚他们是什么人,在配置文件中不能加不能为空的判断,这样也有问题,应为的字段可以空,就没有意义

2)每个子类一张表,对象模型不变,也就是类代码不变,只需修改配置文件(数据模型)

       和以上的类一样所以就做三张表,

T_person

Id     name        age      sex

T_student

Id      school      pid        

T_work

Id       factory     pid

 

 

说明:这里的pid是外键就是personid字段不同但值相同(也可以去掉pid用共享主键来达到要求)这里所用就是共享主键,从建表看,生成了第三个表达到结果:可以加不能为空的配置

3)每个具体的类一张表;对象模型还是不变,变的还是数据库

例子如下:建立三张表

           T_pserson

 

                          T_studnet

                          Id     name       age     school

                         

                          T_factory

                          Id      name      age     factory  

         说明:这俩个子表的id不能相同 ,用到联合子类,这里产生了person表,但是是空的为了    不让这个表产生可以用abstract =true;这里假如加了不能为空的话,就不能手动的向表中插入数据了; 

-----------------------------------------------------------------------------------------------------------------

HQL讲解

语法:1.实体查询

String hql = " from TUser";

执行这条语句会返回TUser以及TUser子类的纪录。

注: 如果 TUser 类具有外键, 查询会报错!

解决方法: select 别名。属性 from  as 别名。 没有别名。属性仍然报错!

hql = "from java.lang.Object"

会返回数据库中所有库表的纪录。

where 语句

hql = "from TUser as user where user.name='yyy'"

其中,as可以省略也一样

hql = "from TUser user where user.name='yyy'"

where子句中,我们可以通过比较运算符设定条件,如:= <> > < >= <= between not between in not in islike等。

2.属性查询

List list = session.createQuery("select user.name, user.age from TUser as user").list();

还可以在HQL中动态构造对象实例的方法,将数据封装。

List list = session.createQuery("select new TUser(user.name, user.age) from TUser as user").list();
Iterator it = list.iterator();
while(it.hasNext() ) {
TUser user = (TUser)it.next();
System.out.println(user.getName());
}

但是要注意这里的TUser对象只是对nameage属性的封装,其他状态均未赋值,所以不能用它来进行更新操作。

也可以在HQLSelect子句中使用统计函数

"select count(*) ,min(user.age) from TUser as user"

也可以使用distinct关键字来删除重复纪录。

select distinct user.name from TUser as user

3.实体的更新与删除

hibernate 2中需要先查询出实体,设置属性后再保存。

hibernate 3中,提供了更灵活的方式(bulk delete/update

更新:

Query query = session.createQuery("update TUser set age=18 where id=1");
query.executeUpdate();

删除:

session.createQuery("delete TUser where age>=18");
query.executeUpdate();

4.分组与排序

Order by子句:

from TUser user order by user.name, user.age desc

Group by子句和Having子句

"select count(user), user.age from TUser user group by user.age having count(user)>10"

5.参数绑定

通过顺序占位符?来填充参数:

1hibernate 2 中通过session.find方法来填充

session.find("from TUser user where user.name=?", "Erica", Hibernate.STRING);

多个参数的情况:

Object[] args = new Object[] {"Erica", new Integer(20)};
Type[] types = new Type{Hibernate.STRING, Hibernate.INTEGER};
session.find("from TUser user where user.name=? and user.age=?", args, types);

2)通过Query接口进行参数填充:

Query query = session.createQuery("from TUser user where user.name=? and user.age>?");
query.setString(0,"Erica");
query.setInteger(1, 20);

通过引用占位符来填充参数:

String hql = "from TUser where name=:name";
Query query = session.createQuery(hql);
query.setParameter("name","Erica");

甚至可以将查询条件封装为一个

class UserQuery {
private String name;
private Integer age;
//getter and setter
}
String hql = "from TUser where name=:name and age=:age";
Query query = session.createQuery(hql);
UserQuery uq = new UserQuery();
uq.setName("Erica");
uq.setAge(new Integer(20));
query.setProperties(uq); //
会调用里面的getter?
query.iterate();

6.联合查询

也可以使用 inner joinleft outer join right out join full join

排列组合:form TUser TAddress

事实上sqlhql除了语法上相似外,差别很大,完全不是一个概念.这里所操作的都是对象的属性sql是关系数据库查询语言,面对的数据库;hqlHibernate这样的数据库持久化框架提供的内置查询语言,虽然他们的目的都是为了从数据库查询需要的数据,sql操作的是数据库表和字段,而作为面向对象的hql操作的则是持久化类及其属性。hql语句执行后的结果都是对象;

oracle的案例数据库来讲解;分别有三个脚本语句文件,将三个脚本文件打开粘贴到oracle中,在dos下按命令User\sqlplus scott to tiger 接着把sql脚本拷贝运行,也就是案 例数据库,分别是创建数据、添加数据、删除冗余数据。

 1 Hibernian中的column属性:们声明从JavaBeanid属性到表的id列的映射. propertyHibernate column属性都有相同的值,我们本来可以忽略Hibernate column属性,但是为了清晰起见,我们还是把column列出来是个特殊的标 .它被用来声明表的主键

2myclipse中可以自动的生成Hibernian配置文件但是手动导包的时候他不会把log4j property文件导入,需要我们自己去导入,还要在myeclipse中手动导入junit组件

3这种写法:也可以是一种循环for(Object obj:list): 这是一种新的循环遍历集合的方式,冒号前边定义变量,代表集合中当前操作的元素,它的类型是集合中元素的类型,在循环体中直接用。
冒号后边就是一个集合。这种写法比较简单,易于理解。
4当现有表后又文件的时候hql读取表的时候出现的CGLIB错误说明数据表中的字段为空了,必须赋值

5Hql语句的时候可以使用myclipse中的HQL编辑器他可以将hql语句自动翻译为sql语句,但是有时候这个编辑器会报错打不开,就要看看工作路径下…data文件的配置,看的是configfile的配置路径和是否能够找到session工厂,还有就是映射文件不能错;

6 hql支持查询对象的别名打点,就可以实现多表查询,还支持左右链接和内联。

7数据表达链接方式:左外链接,右外连接,内连接,全连接

  左外链接:把左边的那个表中不符合条件的字段查出来,右外连接一样

  内连接:发送等值链接条件

  全连接:左右都不符合条件的值都显示出来

   这里的简写id就是对象中的持久化标识,就是配置文件中<id>标签中name的值

With可以在join后面设置条件,createQuery发出的是hql语句,

  支持:子查询+聚集函数,分组查询(分组查询用having加条件:)

8 ROWNUM sql中的函数:限制返回数据的条数(类似游标工作)系统任务这样的函数起始值是1

 所以rownum>某个数字或rownum = 非数字都是 不合法的:但是 可以用rownum<=某个数字

HQL中有这个函数但是没有此功能。用这个也就是查询最大的几个数据,所以也叫TOP n 方法

 

Hibernate中的缓存 一级缓存:session(进程)级别(listireator查询缓存都在)不关闭session的话一直都存在

二级缓存:sessionfactory应用中,是服务器级别的 ,只要网站不关闭就一直存在,一般会在里面放一些不重要的东西

cout*)的时候在hibernate中返回的一定是integerlong版本不同也会不同的

原生SQLnetive SQL):

         就是像mysql oracle等自己的一些特性就称作原生sql

 

 

二级缓存只需要查一次数据库,在次操作数据不用去查询了,它会首先找缓存,看看有没有,如果有就直接用,没有的时候在去查!

hibernate中用的都是EHCache,不支持集群,Hibernate的二级缓存是应用服务器级别的,他的最大的好处就是跨session的,把一些不时常用不到的数据放到session

                还有一些如SwarmCacheJBoss TreeCache都是企业级的分布式的

配置二级缓存:1首先在hibernate.cfg.xml中的配置

                <property name="cache.use_second_level_cache">true</property>   //开启缓存

                   <propertyname="cache.provider_class">org.hibernate.cache.EhCacheProvider</property>//缓存提供商

              2上述就配置提供了缓存,还要在相应的表中配置缓存

                            <cache usage="read-only"/>

                   3.当这里启用了EHcache的时候就要导入ehcache.xml文件(在hibernate-3.2\etc的包中)这样就不会报错,里面有相应的配置

                4 解释:当查询的时候先从一级缓存中查,然后从二级缓存中查询,如果都查不到的话就会发sql继续查询

你可能感兴趣的:(hibernate学习笔记3)