00:00
下面我们来说说这个对象关系映射文件。实际上就是这个HBM.x苗这个HBM表示什么意思啊hb hi。I'm making。这个harmon的mapping有这么。通过这个映射文件呢?Harm可以理解持久化类跟数据表之间的对应关系,哪一个类跟哪个表对。类的属性跟哪一个字段对,如何去映射主键,如何去映射关联关系等等等等。在运行时,哈弗将根据这个映射文件来生成各种的词口语句,扩展名是HBM.xml。对应文件,我们说的就是这个news.hbm.x这就是一个实例。
01:02
这个验证文件里边的话呢,我们要讲很多内容啊,比方说呃,Class ID property,以及到后边我们讲一对多多对一,一对一的money two one one two one。Money to money money said。映射。子类的时候,映射集成关系的时候s class join class,映射主件的时候component,嗯,存放查询语句的query,这些的话呢,在后边我们都会一一的讲到。我们在一个HBM文件里边,我们可以定义多个类,就是说出来这一个里边我可以写多个class节点,可以这样写。可以写多个class class,但是我们通常情况下我们还是建议一个HM只对应一个类。下面我们就来详解一下这个文件,我们首先我们说最顶上那个叫harmlet mapping叫harmlet映射这个。
02:06
奥斜杠这里边的话呢,有一些属性,那我实际上PPT里边的这个列表的。截图截过来的。我们会对我们要讲的这个属性啊,打成这样的标记,不打标记的用的要少一点,大家要是需要看的话呢,看那个文档就可以了,那打标记的我们分为两个阶段来讲,打红色标记的马上说。打这个蓝色标记的,我们会随着这个技术学习的深入的话,我们再说。第一个我们看在这个mapping里边有一个什么package,叫表示包。指定一个包前缀,如果应收文档中没有指定权限定期的列名的话,就是用这个作为包名,什么意思呢?比方说我们这个里边的这个glass指定了一个高明。还有类名,你说X拿过来可写一个,哎,写一个排这个放进来。
03:06
这样就可以。有什么好处吗?那我如果我们在这一个HBM里,HBM文件里边映射多个类,而且这多个类在同一个包里边,它会起作用吧,对吧,比方说我再写一个class。哎,这个class呢,用这个在一个包里边,你写了一个他的话那个不是省事吗。当然我们刚才也讲了是吧,我们在这一个HBM文件里边啊,可能。或者是建议只使用一个class,那什么时候用呢?哎,我们后边我们还要学习来映射一个关联关系,映射关联关系的时候,我们也需要指定那个。关联关系那个类的类名,那如果关联的那个类跟当前这个类在一个包里边的话,这个也会起到一个简化配置的作用。那我们在mapping里边暂时就说这个package就可以了。
04:02
这边看class。是哪个他?Glass我们现在已经比较熟知的是name table name什么意思?Name是指定一个全类名,如果前面这个配置package了,也就是类名这个包里边的这个类。table呢,表明。我在数据库里边对应哪个表。那这个表明跟类名不一,不一定一致吧,比方说我这会儿带个SS。嗯,加一个前缀,这是可以的。这个时候用这个数据表,这个SS下划线你。我们来看常用的这个属性叫。动态插入,动态更新,这两个从一定意义上讲。一个意思差不多,我们来说这个动态插入若设置为true的话,表示当保存一个对象时,会动态的生成insert insert语句中仅包含取值不为空的字段,默认为false。
05:08
动态更新若设置为true的话,当更新一个对象时,会动态的生成update语句,Update语句中仅包含所有取值,需要更新的字段默认为false。我们首先我们来看一下这个动态更新啊,说完这个的话呢,这个动态插入这个道理一样,我们来说一下这个动态更新。在这吧。Public world test dynamic dynamic update。Egg。De。保出一个news。点get use glass。Ad是几啊?
06:02
这个的话呢,我需要看一下数据表。啊,我们有一和二是吧,就是一。做一个修改。That also改为abcd。写完我们跑一下看看效果。出了一个空指针异常,为什么呢?意思,这个记录是有的。他说。这个news没有获去找。数据库里边有对应的记录,而我们这块没有获取着,为什么呀,刚才我改过一个表明还记得吧,这块去掉。
07:02
这种就可以了。我们看我这块的话呢,有一个更新操作,这个更新操作怎么样,是不是把这三个字段都更新了。我们回到我们这个里边来。但我是不是只是改了一个author,说明这个语句并不是动态生成的?哎,我们希望啊,仅在这个赛里边仅包含我更新的字段,于是我来配置一下,这里边我来配一个动态更新。设置为出。再看。有一个。大家看这个时候,这个更新里边包含了这个字段呢,就是我实际上改这个字段而不改那些就没包含,这叫动态更新。那么对应的这个动态插入和这个道理是一样的。
08:02
Name说过了,C说过了,Select before update是不是也说过了?我们在对这个游离对象进行更新的时候,我们可以设置这个职位处,它先会进行查询。如果发现数据库里边那个记录。跟我游理对象这个状态一模一样的话我就不发update,不一样的话我再发update,这个设置为true的话,总会发生一条select,所以说这个性能有一定的降低,我们建议大家不来说这个属性是吧。下边。Class完看下一个,看下一个这个节点,下一个节点呢叫。ID,我们今天讲课的时候也说过这个ID。对于hamlet映射文件具有特殊的意义。还是映射关系。关于型数据库里边那个组件。
09:01
和持久化对象的。对象标识符的,我们看ID name是。属性的名字持续化链一个属性名,这是一个类型,是什么类型的是吧,Column。指定主键的那个列名generator,指定如何去生成组件。好了,我们这块需要花大气力来讲一下生成组件的方式有哪些,而且它们各有什么优缺点。映射对象标识符hamlet使用对象标识符OID来建立内存中对象跟数据库中表记录的对应关系,对象的OID跟表的主键相对应。harmlet通过对象标注生成器来为主件赋值。Hamlet推荐使用代理组件,就是不具备任何业务意义的字段。
10:01
叫代理组件,以前的话呢,我们这个主主件的时候,我们可能用过email可能用过。身份证号码,但这个的话呢,其实都是有问题的,因为他们是有这个业务含义的。我们推荐使用啊,代理组件没有任何业务含义的。然后呢,我们推荐代理组件使用整形,因为整形比字符串要节省更多的数据库空间,整形在我们BS项目里边有一什么毛病,我从前台获取这个请求参数是不是一个字符串类型啊。数据库里边是一个整形,我需要强转一下。这是他的缺点,但是我们还是推荐。逐渐使用整数类型。在对象关于映射文件里边呢,我们使用这个真子元素来设定标识符生成器,就是如何去生成那个组件。harmlet提供了标识无生成器的接口,叫这个嗯,ID genator,并提供了。
11:03
各种内置实现,它提供这个接口的意思是什么呀?我们也可以自己来定义我们的逐渐生长期,但通常情况下没有这个必要。直接使用这个内置实现就。可以了。我们看到了column name UN saved value,我们在前面讲过了。NCYNC的value这个值设定好以后的话,如果有一个对象,对象的主键值刚好跟那个NC的value一样,Harmon会认为它是一个。临时对象在调用save or update方法的时候,它会执行save操作,还记得吧?OK。呃,Generator,我们使用class来设定这个标识生成期,这里边的话呢,通常我们写这个数写名哈,而不去,而不去写这个全面性的类名。就像我们这个里边,我们用那个hero,而并不是写那个hero所对应那个真瑞的那个。
12:03
全类名。好,我们看harmon提供的内置表示生器,一共是有这么多种。其中这个foreign。再见。带键主键生成器,我们在讲一对一关联关系的时候,讲其他的几个我们逐一来看。第一个叫increment。增长自征,你看到这个inrement第一反应是什么呀?啊,感觉好像跟harm那个autorement一样吧,但实际上不一样。Rement标志物生成器是由harm以递增的方式生成代理主线,注意也是on来征。如何来确定这个主键呢?它先读取news表中组件的最大值。接下来。在插入这个记录的时候,就使用以前那个组件的最大值加一。
13:02
所以说这个时候怎么样,就可能会有。并发的问题了,他先去读,然后在那个基础上加一,这个时候你要是两个线程同时来读的话,读完之后一样。那都加一主键值也一样,那不就出现了主键重复。所以说这个只适用于测试的范围。我们测试的时候用一下还是不错的,但开发的时候具体写项目的时候不能够使用这个rement,但我们还是来测试一下啊。改为environment。备课之后呢,我把这个数据表删除。刚才这个S6的实际上已经生成了。新建一个方法吧。ID。
14:05
At t。创建一个news。A。It。执行一个插入操作。Save。执行一下看看。看确定ID的话呢,它的确是会来查这个表,先查一个最大值,然后新记录这个ID就是。查询之后这个ID最大值加一,那看一下吧,刷新就是这个一,好了,我们讲这个会发生并发的问题。发生这个并发问题的原因呢,就是因为我这个主键是先来读当前主键最大值,然后加一产生的。
15:07
那比方说我们来模拟一下这个过程哈。我不是要读一下吗,我读完之后,后边我才执行这个插入,现在我让这个线程睡一会儿。五秒就可以。外炮。先找一个。再找一个。这个时候呢?呃,这两次。读的这个ID的这个值就是一样的,大家看。这个手怎么了,没有进行插入操作,为什么呀。因为这个主键重复了,这个二重复了,大家看插入的就只有一条,而第二条没进来。这就是使用rement这个组件生成器。
16:01
的问题是吧,所以说我们开发的时候不能用它,测试的时候可以用。因为测试的时候并不是生产环境嘛。Identity。由底层数据库来负责生成标识符。它要求底层数据库。能把组件的生成方式定义为自动增长这个类型,这就要求底层数据库必须支持这个。自征。那要求底层数据库可以是DB two my circle circle server c space,你不支持这个四征的话用不了,比方说你Oracle就用不了。因为Oracle不支持这个自证嘛。OID必须定义为long in thought,而不能定义为back back,这个范围太小了是吧?通常情况下,这个主键都定义为long或者是in。看一下这种方式改为。
17:03
Identity。来。把这个涂掉啊。数据表呢,删除。测试一下。这个时候这个主键就是自称的。打开刷新都是它怎么能够看出它是自征的了呀,看那思路就可以了,你看插入的时候是不没有插入那个ID啊啊,这个主键是自动增长的。那卖circle,我们可以来用这个identity。下一个。Sequence。利用底层数据库提供的序列来生成标识符,所以说这就要求底层数据库一定是支持序列的,支持序列的数据库可以是DB two,也可以是Oracle,你这个时候你要是用的是MYSQL数据库,你搞一个sequence,它就不支持。
18:06
那那oid必须设置为long in或thought,而不能设置为bad,这个的话呢,是显然的哈,后边我们这样的要求我们就不给大家单独单独的提出来了,那sequence我们来看一下这个语法,ID generator sequence,我们可以来指定一个序列的名,比方说就news下发现sequence其他的。都是买SQL,自动的买SQL,你会看见这个SQL,就它会先来获取当前的序列值。然后呢,把这个序列值作为主件插入到数据表里面,这个我们就不试了,因为应用是的话还就要切换数据库不是了啊。写法跟这个写法一模一样。再下一个he。系列标志生成期是由harmle按照一定的高低算法来生成表示符,它从数据库特定的表的字段中来获取氦这个值哦,高低算法。
19:05
我在这块,我在这块的话呢,有一个详细的文档,大家可以来参看这个文档。上课的时候我们就不讲这个高级算法。Harm姆在持久化一个news对象的时候,有harm姆类负责生成逐渐值系种标志不生成器,这生成标志符的时候呢,会先来读取对应这个表的next y流值。那这种生成方式啊,不依赖于任何底层数据库,你无论是买circle啊,还是这个dp two啊,还是包口还是。都可以支持。因为它不依赖于底层数据库,它不是自称,也不是序列。看一下这个息肉算法。He表示不能记过来。Kow。数据表删除。
20:02
这种。看这个时候这个ID呢,是需要被插入的,所以说肯定不是底层的这个自征了哈,然后大家看它先会从我们的这个呃,Hamlet用那个key这个表里边来获取一个next height值,获取完这个值以后,它会马上对这里边的这个数据表里边这个next hi这个值进行。修改,那这样的话呢,就不会出现我们刚才并发那个问题,因为我读一遍,读一遍之后马上改了,再读之后就不一样了,所以说这个是可靠的。看一下我们的数据表。啊,这个值一样。F5,你看这个时候是不是又多出来了一个数据表啊?这个表是帮我生成主线值那个表。再插入一条。
21:00
这个是长为二,而第二条记录的这个主键的话呢,是32768,嗯,这里边是有一个高级算法,大家看到了吧。我们现在取的都是默认值,大家也可以根据实际情况来修改对应的属性值,那我这个里边的话呢,有详细的这个写法和文档,好我们看下一个。标志物正常器叫native native什么意思啊,本地。这个呢,会依据底层数据库对自动生成标书生成器的支持能力来选择identity sequence或者hero。所以说这个是跨平台的,你支持自征的话,我用自征,你不支自征的话,看你是不是支持序列都不支持的话,我使用he,这种方式不错,所以说我们很多时候这个标志生成器啊,我们就写为A。那我现在当前这个写为native的话,用的是不是一层那个auto,所以这个的话呢,我们就不举例子了。
22:03
这种方式是跨平台的。OK。其他几种的话呢,我们就不再一一说了,我们通常情况下选用的时候,直接选用这个native啊就很不错。下边说完了这个。ID节点,我们开始说property节点,Property什么意思?属性如何来映射属性和对应的字段,字段就是那个列。首先看我们一些比较熟知的哈。Property name属性名。Type。属性的类型这块是Java的全类名哈,还有一个call隆里边还有一个name,这是字段的名字,我目前我们这个比较了解的就两样个三项。看其他属性。什么访问,访问属性的方式?
23:06
默认是property属性,即用get跟set,这个是一个通用的方式,我们也可以把这个值改为field,这个时候hale就会使用反射的方式直接去访问那个重新变量。通常情况下这个取值还是property。因为我们那个。持久化类通常都需要定义get set。Column列名,诶。这不是有个靠拢子节点吗?就是说这个靠拢嘛,也可以定义在这个里面。再看。这type的话呢,我们需要说一下说指定harmon映射类型,Harmon的映射类型是Java类型跟circle类型之间的桥梁,如果没有显示的为属性设定这个映射类型,Harmon会根据反射机制识别出。
24:03
持久化类属性对应的Java类型,然后使用与之对应的harm映射类型,啥意思嘞?就是说我们这块的话呢,我们需要去写一个类型,然后hamlet好根据这个类型去定义数据表里边那个字段对应的类型,如果你要不写的话,Harm,那就需要通过反射的方式去侦测这个类型。那我们这块的话呢,我们是写写了一个全类名,也可以这么写,你也可以写一个哈的一个类型,大家看。String,这也可以,这个string很明显不是JA里边那个string啊,那个string这个字母是大写啊,这叫harm映是类型,那我们来看一下,我们来看一个表吧。啊,Java类型,Harm类应类型以及circleq类型之间的一个对应关系,我们写的叫string Java里边对应的是string标准,Circle里边是我差。
25:01
诶,我们可以通过这个表来进行这个选择,对应的harm harm类型来进行映射,但是我们这块的话呢,我们写上一个这个,呃。全类名也没问题。到后边我们会讲如何去映射那个时间类型,因为这个时间啊。有的时候的话呢,我只需要一个date,年月日,有的时候只需要一个time,时间小时分秒,有的时候的话呢,我可能既需要日期又需要时间,那个时候我们就需要明确指定。这个映射类型是什么?嗯,总而言之,必须必须得指定这个type,一方面的话呢,我们可以指定这个全类名。但有的时候我必须得显示指定啊,具体使用哪一个harm的映射类型,因为我需要进行精确映射,我们这个我们后边讲这个时间日期的时候会提到的。
26:01
再往前来。Type unique什么意思啊?这个列是不是添加一个。为约束。Update update。Update指的是这一列的值是不是可以被修改。在这呢嘛,是吧。Update,这没写啊,这一列的值是不是可以被修改?来。Index指定一个索引,Wince指定这个字段。的长度。我们把这几个我们一起来试一下。我们就以这个开头为例了哈。写一个来。第一个叫unique。另一个处添加为约束了。接下来update,我指定一个false表示这个。
27:01
列的指未修改。下一个我们还要知道一个index。我解一个news index,我同时设这两列一个index。还有一个叫。长度零二十,OK。初级表大家看一下。好,走一个。插入成功。看一下数据表F5。Outer table。大家看这轴抬头是不是20啊?索引,哎,我们有一个索引叫什么。叫news index,它同时作用于title跟author。
28:05
Title是不是有一个UNI啊。那给它加上唯一约束的话,就会为它加一个索引吗?这个还有一个我们需要说就是这个叫。Update,这个通过测试的时候才能拿得到。我们来看一下public。Boy he。Property。The update。At。先把这个对象获取出来。然后呢,我对它进行一个修改,帮助改。有一个。
29:05
肯定是可以改的是吧,那需要注意的是,我来改一下开头。瞧这。这个开头是不是没改呀?数据表。开头真没改,为什么呀,我这块设置了这样的一个属性叫。Title的update等于false,表示这一列的值不能被修改。懂了吧?嗯,开。Title。里边这个update等于false,表示开头这个字段的值不能被修改。了解一下哈。下编。说一个重要一点的,叫formula。
30:00
设置一个四口表达式,Heme将根据它来计算一个派生属性的值。什么叫派生属性呢?这样的并不是持久化类的,所有属性都直接和表的字段相匹配。持久化类的有些属性的值必须通过计算才获得,这样的属性我们称之为派生属性。在我们的持久化类里边添加一个属性,测试一下这个formula。添加一个属性。帮助添加一个描述的属性,我们说呀,该属性值。为什么呢?为开口。嗯。标题。冒号作者就可以了。
31:02
同学说,老师你写这个是不是很容易写啊?怎么写啊?写个对应的跟C。我直接在返回的时候这样写不就可以了吗?是不是就可以了,这样是可以了,像这样写的话呢,我觉得差点意思,为什么呀,我们这个派生属性的值啊,很容易计算,大家想。有一些排成属性的值需要比较复杂的计算才能够搞到,比方说我需要用到,我需要用到用到统计函数。那这个时候,那这里边写的话很明显就不是那么的合适了,是吧,所以说我们这个的话呢,我们还改回来。简单的是可以这样写的,那复杂的这样写就不行,复杂的什么意思啊,我需要借助于数据库里的一些统计函数啦,里边的一些思函数啦,你这样写就不合适了,所以说我们来用这个派生属性,OK。
32:14
像这一列的话呢,是我们通过计算可以得到的,所以说我们不需要在数据表里边写一个对应的列,就是说就不用在这个里边再加上一个DC了,那我来映试一下这个属性吧。News。你说一下。映射。派生属性。Property。ESC。OK,没有,只有一个formula,写一个circle口来看哈。Author。
33:00
符号。冒号。From n。Y n.ID等于ID,写完。看一下这次的效果。Use can get。DC搞一搞。这个值没问题,Aaaaa就是质量哈。AAAAA。Circle怎么写的呀,这不是内置的一个子查询呢,这个子查询语句刚好就是我这块在映射的时候写的这个方表。
34:00
大家看到了吧,嗯。这个formula我们需要使用中国号给它扩取,因为是一个子查询嘛,然后select这里边我写的这个author跟title应该是什么呀,应该是。列明。而不是属性名from表明N,然后n.ID等于它是什么呀?这个是此查询吗?这个是外表的ID。他那这个ID名的话就叫ID,所以说你这块就应该写成ID,看懂了吧。过来看方谬法必须需要加这个括号,这个表达式中列名跟表明应该跟数据表对应,而不是跟持久化类的属性跟类名对应,需要在方面的属性中使用参数,可以直接使用这样的形式,其中这个ID就是参数,它表示。外表的那个主键值。和当前持久化类的ID属性对应的列的ID值作为参数传入,这就是放我们还有一个属性没讲,这个属性叫skill。
35:07
啊,如果我们要是有一个这个大型或者是一个float型的话,它将指定映射之后那个字段小数点后边的位数。啊,这个我们不测试了,以上就是我们说的这个property,凡是我们打红色标记部分的,大家都需要认真的来看一下。
我来说两句