admin 管理员组文章数量: 887038
2023年12月19日发(作者:tooltip控件内容换行)
Hibernate1.1简介一.orm和Hibernate为什么orm框架编程语言和底层数据库发展不协调,催生了orm框架ormORM(对象关系数据库映射)Object/releationMappingorm理解成一种规范面向对象的简单易用性和数据库技术的优势面对象设计————面向对象编程-————数据库持久化必须返回数据库的访问模式orm模型编程语言的优势:1.面向对象的建模,操作;2.多态,继承。3.简单易用易理解;数据库的发展并未同步编程语言的发展:1.大数据的查找和排序2.集合数据连接的操作。映射3.数据库的并发和事务4.数据的约束和隔离orm模型流行的orm模型:JpAHibernate(开源orm框架)IbatisTopLink解决办法1。jdbc人工转换2.使用orm模型优势:1,开发速度快,节约成本。updatetablewhereid=xxx;HIbernate:优势:ate对jdbc访问数据库代码分装大大简化了数据库访问的重读代码;ate主流的持久化框架,很大程度上简化了dao编码工作;ate使用的反射机制,而不是使用字节码程序的透明性4.多种数据库的支持实现复杂的映射关系5。完全的面向对象。6.开源和免费的linces7.轻量级的封装、8.可扩展性。劣势:1.学习成本高、量十分庞大的时候不推荐使用HIbernate原生态的jdbc操作数据库;表的关系十分复杂数据seta=xxx,b=xxx,c。。。。。
一.引入模型不匹配(阻抗不匹配)Java面向对象语言,对象模型,其主要概念有:继承,关联,多态等;数据库是关系模型,其主要概念有:表,主键,外键等解决办法1.使用jdbc手工准换2.使用orm(ObjectRelationMapping对象关系映射)框架来解决,主流的有Hibernate,Toplink,OJB,ibatis(半自动的)优势开发速度快节约成本Hibernate的优点:1、Hibernate对JDBC访问数据库的代码做了封装,大大简化了数据访问层繁琐的重复性代码。2、Hibernate是一个基于jdbc的主流持久化框架,是一个优秀的orm实现,它很大程度的简化了dao层编码工作。3、Hibernate使用java的反射机制,而不是字节码增强程序类实现透明性4、Hibernate的性能非常好,因为它是一个轻量级框架。映射的灵活性很出色。它支持很多关系型数据库,从一对一到多对多的各种复杂关系。5、Hibernate使数据库的操作完全面向对象。而不是从前的面向关系进行操作。劣势学习成本高表的关系十分复杂并且数据量十分庞大不推荐使用Hibernate推荐使用JDBC或者IbatisJDBC的优点和缺点JDBC的优点直接底层操作,提供了很简单、便捷的访问数据库的方法,跨平台性比较强。灵活性比较强,可以写很复杂的SQL语句。JDBC的缺点因为JAVA是面向对象的,JDBC没有做到使数据能够面向对象的编程,使程序员的思考仍停留在SQL语句上。操作比较繁琐,很多代码需要重复写很多次。如果遇到批量操作,频繁与数据库进行交互,容易造成效率的下降。
JDBC的程序操作可以封装一些什么内容?又不可以封装哪些内容?Hibernate为什么要用HibernateHibernate实现了面向对象的数据库编程Hibernate比起JDBC来,在代码的书写上比较简单化了。Hibernate提出了缓存机制,这样可以使访问数据的效率提高很大。Hibernate的配置使用mysql数据库进行演示安装好如果没有服务的话在安装目录下的bin目录中找到mysqld在cmd中进入到这个目录中,然后--install安装这个服务。首先建立一个工程,然后添加Hibernate能力然后填写相应的配置即可。DriverName:mysqlURL:jdbc:mysql://localhost:3306/hzgghibernateUsername:rootPassword:root1.2创建映射类实例由表到类创建的两个实体对象和.1.2.1使用单体对象进行增删改查以book为例idbnameauthor如出现中文乱码加入如下代码jdbc:mysql://localhost:3306/hzgghibernate?useUnicode=true&characterEncoding=;
ateException;;n;nFactory;ction;uration;;ateSessionFactory;publicclasstest{/***1.获得Session*2.操作领域对象*3.使用Session方法进行增删改查*4.如果是dml操作。需要提交事务*5.关闭Session*@paramargs*/publicstaticvoidmain(String[]args){//save();//queryById(2);//queryAll();//delete();//update();}//保存数据publicstaticvoidsave(){Sessionsession=null;Transactiontx=null;try{session=sion();tx=ransaction();Bookbook=newBook("2c","brudddce");//Productp=newProduct();//e("chide");//e(newDate(0));//ce(3.33);//(p);(book);
}catch(HibernateExceptione){//ck();tackTrace();}finally{();ession();}}////单个查询publicstaticBookqueryById(intid){Sessionsession=sion();Bookbook=(Book)(,id);n(me());ession();returnbook;}//查询全部publicstaticvoidqueryAll(){/***遇到写语句的时候用Query类*SQl*HQLfromcalss*/Sessionsession=sion();Stringhql="fromBook";Queryquery=Query(hql);List
try{session=sion();tx=ransaction();Bookbook=queryById(1);(book);}catch(HibernateExceptione){//ck();tackTrace();}finally{();ession();}}//更新数据publicstaticvoidupdate(){Sessionsession=null;Transactiontx=null;try{session=sion();tx=ransaction();Bookbook=queryById(2);hor("kkkk");(book);}catch(HibernateExceptione){//ck();tackTrace();}finally{();ession();}}publicstaticSessionbuildSession(){/***1.加载配置文件Configuration
}}*2.生产SessionFactory*3.创建Session*/Configurationconf=newConfiguration();ure("");SessionFactoryfactory=essionFactory();Sessionsession=ssion();returnsession;代码分析配置文件:
表示要链接的数据库地址表示要链接的数据库的驱动类要连接的数据库的用户名要连接的数据库的密码_t表示要使用的数据库的类型mysql数据库oracle数据库SQLServer数据库lidate:加载hibernate时验证创建表结构update:加载hibernate时自动更新数据库结构,如果表存在不用创建,如果不存在就创建。create:每一次加载hibernate时都创建表结构create-drop:加载hibernate时创建,退出时删除
Cnfiguration类负责管理Hibernate的配置信息。包括如下内容:•Hibernate运行的底层信息:数据库的URL、用户名、密码、JDBC驱动类,数据库Dialect,数据库连接池等(对应文件)。•持久化类与数据表的映射关系(*.文件)创建Configuration的两种方式•属性文件(ties):Configurationcfg=newConfiguration();•Xml文件()Configurationcfg=newConfiguration().configure();第二种创建方式较为常见。文件默认的目录为系统的根目录。(展示源代码以得到证实)Configuration对象根据当前的配置信息生成SessionFactory对象。SessionFactory对象一旦构造完毕,即被赋予特定的配置信息(SessionFactory对象中保存了当前的数据库配置信息和所有映射关系以及预定义的SQL语句。同时,SessionFactory还负责维护Hibernate的二级缓存)。Configurationcfg=newConfiguration().configure();SessionFactorysf=essionFactory();是线程安全的。SessionFactory是生成Session的工厂:Sessionsession=ssion();构造SessionFactory很消耗资源,一般情况下一个应用中只初始化一个SessionFactory对象。在Hibernate中,Transactiontx=ransaction()相当于给数据库操作起事务。()则为提交事务。Hibernate的整个运行过程如下:1、应用程序先调用Configuration类,该类读取Hibernate配置文件及映射文件中的信息,2、并用这些信息生成一个SessionFactory对象,3、然后从SessionFactory对象生成一个Session对象,4、并用Session对象生成Transaction对象;A、可通过Session对象的get(),load(),save(),update(),delete()和saveOrUpdate()等方法对PO进行加载、保存、更新、删除、等操作;
B、在查询的情况下,可通过Session对象生成一个Query对象,然后利用Query对象执行查询操作;如果没有异常,Transaction对象将提交这些操作到数据库中。1.2.2主配置文件和类对应的的映射1.2.3主键生成策略根据主键生成策略的不同Hibernate在发送sql的时间不同如果主键是increment时候当调用save方法的时候会马上发送sql如果是assigned的时候当调用save方法不会马上发送sql而是当commite的时候发送sql;表示符生成器Increment由hibernate自动以递增的方式生成表识符,每次增量为1描述Identity由底层数据库生成表识符。条件是数据库支持自动增长数据类型。ernate根据底层数据库序列生成标识符。条件是数据库支持序列。根据底层数据库对自动生成表示符的能力来选择identity、sequence、hiloHibernate采用128位的UUID算法来生成标识符。该算法能够在网络环境中生成唯一的字符串标识符,这种策略并不流行,因为字符串类型的主键比整数类型的主键占用更多的数据库空间。如果主键用字符类型,并且不代表任何含义。assigned适用于自然主键。由java程序负责生成标识符。不能把setID()方法声明为Private的。尽量避免使用自然主键。
increment标识符生成器increment标识符生成器由Hibernate以递增的方式为代理主键赋值Hibernate会先读取NEWS表中的主键的最大值,而接下来向NEWS表中插入记录时,就在max(id)的基础上递增,增量为1.(带走+1)适用范围:•由于increment生存标识符机制不依赖于底层数据库系统,因此它适合所有的数据库系统••适用于只有单个Hibernate应用进程访问同一个数据库的场合OID必须为long,int或short类型,如果把OID定义为byte类型,在运行时会抛出异常identity标识符生成器identity标识符生成器由底层数据库来负责生成标识符,它要求底层数据库把主键定义为自动增长字段类型(加1带走)适用范围:•由于identity生成标识符的机制依赖于底层数据库系统,因此,要求底层数据库系统必须支持自动增长字段类型.支持自动增长字段类型的数据库包括:DB2,Mysql,MSSQLServer,Sybase等•OID必须为long,int或short类型,如果把OID定义为byte类型,在运行时会抛出异常sequence标识符生成器sequence标识符生成器利用底层数据库提供的序列来生成标识符.Hibernate在持久化一个News对象时,先从底层数据库的news_seq序列中获得一个唯一的标识号,再把它作为主键值适用范围:
•由于sequence生成标识符的机制依赖于底层数据库系统的序列,因此,要求底层数据库系统必须支持序列.支持序列的数据库包括:DB2Oracle等•OID必须为long,int或short类型,如果把OID定义为byte类型,在运行时会抛出异常native标识符生成器native标识符生成器依据底层数据库对自动生成标识符的支持能力,来选择使用identity,sequence或hilo标识符生成器.适用范围:•由于native能根据底层数据库系统的类型,自动选择合适的标识符生成器,因此很适合于跨数据库平台开发•OID必须为long,int或short类型,如果把OID定义为byte类型,在运行时会抛出异常assigned标识符生成器hibernate和底层数据库都不帮助你生成主键,也就是说得自己在程序中手动的设置主键的值。适用范围:主键有一定的含义,需要根据业务产生的情况。Uuid标识符生成器Hibernate采用128位的UUID算法来生成标识符。该算法能够在网络环境中生成唯一的字符串标识符,这种策略并不流行,因为字符串类型的主键比整数类型的主键占用更多的数据库空间使用范围:主键是字符串,而且必须是唯一
一个Student和Teacher的实例izable;n;ction;r;ateSessionFactory;publicclassTeacherDao{publicSerializablesave(Teachert){Sessionsession=sion();Transactiontx=ransaction();Serializableid=(t);();ession();returnid;}publicTeacherfindById(Serializableid){Sessionsession=sion();Teachert=(Teacher)(,id);ession();returnt;}publicstaticvoidmain(String[]args){TeacherDaodao=newTeacherDao();Teachert=newTeacher("张三",34,null);}}(t);izable;n;ction;t;
r;ateSessionFactory;publicpublicclassStudentDao{=nSerializablesessionsave(Studentt){Transactiontx=ransaction();getSession();();Serializableid=(t);ession();}returnid;publicsession=nStudentfindById(Serializableid){StudentHibernateSessionFactory.t=(Student)(sion();returnt;closeSession();class,}publicvoidupdate(Studentstu){=nsessionTransactiongetSession();(stu);tx=ransaction();();}ession();publicStudentDaostaticvoidmain(String[]args){Studentdao=newStudentDao();TeacherDaos=Id(1);Teacherdao2=newTeacherDao();cher(t);t=Id(1);(s);}}id);
1.2.4持久化对象的状态持久化对象有3种状态:持久化状态临时状态游离状态Session的特定方法能使对象从一个状态转换到另一个状态临时对象(transient)•••在使用代理主键的情况下,OID通常为null不处于Session的缓存中在数据库中没有对应的记录持久化对象(也叫”托管”)(Persist)••••OID不为null位于Session缓存中持久化对象和数据库中的相关记录对应Session在清理缓存时,会根据持久化对象的属性变化,来同步更新数据库•在同一个Session实例的缓存中,数据库表中的每条记录只对应唯一的持久化对象游离对象(也叫”脱管”)(Detached)•OID不为null
••不再处于Session的缓存中一般情况需下,游离对象是由持久化对象转变过来的,因此在数据库中可能还存在与它对应的记录Session使用以下方法可以使持久化对象转变成游离对象:测试hibernate中对象变化的状态:程序代码tx=ransaction();Customerc=newCustomer);(c)生命周期开始生命周期处于生命周期中Longid=();c=null;Customerc2=(Customer)(,id);();();处于生命周期中转变为持久化状态处于持久化状态状态临时状态处于生命周期中转变为游离态e();处于生命周期中处于游离态c2=null;结束生命周期结束生命周期
对象状态转化图对象状态的总结操纵持久化对象-save()Session的save()方法使一个临时对象转变为持久化对象Session的save()方法完成以下操作:
把News对象加入到Session缓存中,使它进入持久化状态选用映射文件指定的标识符生成器,为持久化对象分配唯一的OID.在使用代理主键的情况下,setId()方法为News对象设置OID使无效的.计划执行一条insert语句,把Customer对象当前的属性值组装到insert语句中Hibernate通过持久化对象的OID来维持它和数据库相关记录的对应关系.当News对象处于持久化状态时,不允许程序随意修改它的ID操纵持久化对象-update()Session的update()方法使一个游离对象转变为持久化对象,并且计划执行一条update语句.;ateException;n;ction;;ateSessionFactory;publicclasstestchijiuhua{publicstaticvoidmain(String[]args){update();}//更新数据publicstaticvoidupdate(){Sessionsession=null;Transactiontx=null;try{session=sion();tx=ransaction();//处于持久化状态Bookbook=(Book)(,1);//n(hor()+"---");//装换成游离状态此时session中没有了该状态(book);n(hor());hor("ssss");//此时session中没有了该状态转换为持久对象,执行更新(book);////
}catch(HibernateExceptione){//ck();tackTrace();}finally{();ession();}}}操纵持久化对象-saveOrupdate()saveOrUpdate:该方法同时包含save和update方法,如果参数是临时对象就用save方法,如果是游离对象就用update方法,如果是持久化对象就直接返回。如果参数是临时对象就用save方法如果是游离对象就用update方法
如果是持久化对象就直接返回,不执行操作二.Hibernate映射2.1生成表的工具类uration;Export;publicclassDBCreator{publicstaticvoidmain(String[]args){Configurationcfg=newConfiguration().configure();SchemaExportexport=newSchemaExport(cfg);(true,true);
}}2.2Hibernate的基本映射2.3Hibernate的关系映射2.3.1One2one一个product类在entity中;对象izable;;privateclassprivateIntegerProductid;implementsSerializableprivateStringDatename;publicprivateIntegerDoubledategetId()price;;{}returnid;public}=setId(Integerid;id){publicString}returnnamegetName();{public}tName(String=name;name){publicDategetDate(){}returndate;public}tDate(Date=date;date){public}returnDoublepricegetPrice();{{
publicvoidsetPrice(Doubleprice){=price;}}配置文件
package主键配置选项name属性标识符持久化类标识符的属性名column属性标识符映射数据库中对应的列的名字默认情况不下和name一样为idgenerator设置数据的列生成是否由数据库生成class配置主键生成策略普通的配置属性type指定数据库中映射的类型HIbernate属性中类型基本数据类型(int,float,char)ngth数据库列的长度not-null指定不为空scale指定数据中小数点的映射一个创建数据库表的工具类;uration;Export;publicclassDBCreator{publicstaticvoidmain(String[]args){Configurationcfg=newConfiguration().configure();SchemaExportexport=newSchemaExport(cfg);(true,true);}}测试Productpublicclasstest{publicstaticvoidmain(String[]args){save();}publicstaticvoidsave(){Sessionsession=null;Transactiontx=null;try{
}session=sion();tx=ransaction();Productp=newProduct();e("chide");e(newDate(0));ce(3.33);(p);}catch(HibernateExceptione){//ck();tackTrace();}finally{();ession();}}根据主键生成策略的不同发送sql的时间不同
;;publicprivateclassOrderimplementsprivateStringprivateStringidSerializable{name;publicprivateDateStringSet
}publicStringgetpName(){returnpName;}publicvoidsetpName(StringpName){=pName;}publicOrdergetOrder(){returnorder;}publicvoidsetOrder(Orderorder){=order;}}=id;两个配置文件,xml
(id);e("订单1");Calendarc=tance();(2014,8,7);=e();longmillions=e();n((millions));e((millions));OrderDetailod1=newOrderDetail();(UUID().toString());n();me("牙刷1");er(order);}}Sessionsession=sion();Transactiontx=ransaction();(order);(od1);();ession();2.3.4Many2many两个javabean对象Teacher和Student在entity包中Teacher类;publicclassTeacher{privateStringid;;privateStringname;privateSet
}publicvoidsetId(Stringid){=id;}publicStringgetName(){returnname;}publicvoidsetName(Stringname){=name;}publicSet
}=name;publicSet
e("刘欢");Teachert2=newTeacher();e("张龙");Teachert3=newTeacher();e("宗伟");Teachert4=newTeacher();e("孙宁振");Students1=newStudent();e("AAA");Students2=newStudent();e("BBB");Students3=newStudent();e("CCC");Students4=newStudent();e("DDD");Students5=newStudent();e("EEE");Students6=newStudent();e("FFF");Set
dents(t3set);dents(t4set);Sessionsession=sion();Transactiontx=ransaction();(t1);(t2);(t3);(t4);();ession();}publicstaticvoidqueryData(){Sessionsession=sion();List
2;publicclassProduct{privateintid;privateStringname;privatedoubleprice;publicintgetId(){returnid;}publicvoidsetId(intid){=id;}publicStringgetName(){returnname;}publicvoidsetName(Stringname){=name;}publicdoublegetPrice(){returnprice;}publicvoidsetPrice(doubleprice){=price;}}2;;publicclassFoodProductextendsProduct{privateDatedate;publicDategetDate(){returndate;}publicvoidsetDate(Datedate){=date;}}
2;publicclassBookProductextendsProduct{privateintpage;publicintgetPage(){returnpage;}publicvoidsetPage(intpage){=page;}}映射文件
在中配置
(book);e(food=newFoodProduct();ce(30);"牛肉");Calendarc=tance();(2014,8,7);e(millionsd=e();(food);new=e();(millions));}();tackTrace();(Exceptione){}ck();}}HibernateSessionFactory.{closeSession();publicSessionvoidtestLoad(){Transactionsessiontrytx==nullnull;;session{=sion();ProductSystem.p=(Product)(,(n(e());food=(FoodProduct),3);(n(e());bookclass=(BookProduct),2);}catchSystem.(n(e());e)}tackTrace();{HibernateSessionFactory.{closeSession}}();}1);
第二种方法每个子类属性一张表只需要变更配置文件joined-subclass元素的继承映射映射文件
}publicStringgetId(){returnid;}publicvoidsetId(Stringid){=id;}publicStringgetName(){returnname;}publicvoidsetName(Stringname){=name;}publicSetgetSetValue(){returnsetValue;}publicvoidsetSetValue(SetsetValue){ue=setValue;}publicListgetListValue(){returnlistValue;}publicvoidsetListValue(ListlistValue){lue=listValue;}publicString[]getArrayValue(){returnarrayValue;}publicvoidsetArrayValue(String[]arrayValue){alue=arrayValue;}publicMapgetMapValue(){returnmapValue;}publicvoidsetMapValue(MapmapValue){ue=mapValue;}映射文件
">
ist;p;t;or;;;;n;ction;ateSessionFactory;publicclassInitData{publicstaticvoidinitData(){Sessionsession=sion();Transactiontx=ransaction();CollectionEntityce=newCollectionEntity();e("testCollection");Setset=newHashSet();("a");("b");("c");Value(set);String[]ss={"1","2","3","4","5","6"};ayValue(ss);Listlist=newArrayList();("a");("o");("e");tValue(list);Mapmap=newHashMap();("0531","jn");("0532","qd");Value(map);(ce);();ession();
}publicstaticvoidqueryData(){Sessionsession=sion();CollectionEntityce=(CollectionEntity)(,"4028818d47c4013d0147c4013e780001");n(e());Setset=Value();Iteratoriter=or();while(t()){Objecto=();n(o);}Listlist=tValue();n((1));Mapmap=Value();n(("0531"));}ession();}publicstaticvoidmain(String[]args){//initData();queryData();}mponent;publicclassUser{privateintid;privateStringname;
}privateContactcontact;publicintgetId(){returnid;}publicvoidsetId(intid){=id;}publicStringgetName(){returnname;}publicvoidsetName(Stringname){=name;}publicContactgetContact(){returncontact;}publicvoidsetContact(Contactcontact){t=contact;}mponent;publicclassContact{privateStringemail;privateStringaddress;privateStringzipCode;privateStringcontactTel;publicStringgetEmail(){returnemail;}publicvoidsetEmail(Stringemail){=email;}publicStringgetAddress(){returnaddress;}publicvoidsetAddress(Stringaddress){s=address;}publicStringgetZipCode(){returnzipCode;}
}publicvoidsetZipCode(StringzipCode){e=zipCode;}publicStringgetContactTel(){returncontactTel;}publicvoidsetContactTel(StringcontactTel){tTel=contactTel;}配置文件
ateSessionFactory;publicclassInitData{publicstaticvoidmain(String[]args){initData();}publicstaticvoidinitData(){Sessionsession=sion();Transactiontx=ransaction();Useru=newUser();(1);e("张三");Contactco=newContact();ress("杭州");il("hzgg@");tactTel("111111");Code("qwer");tact(co);(u);();ession();}}2.5.3composite第一个mposite;publicclassEmp{privatePKIDid;privateStringname;publicPKIDgetId(){returnid;}
publicvoidsetId(PKIDid){=id;}publicStringgetName(){returnname;}publicvoidsetName(Stringname){=name;}}第二个mposite;izable;publicclassPKIDimplementsSerializable{privateIntegerfirstId;privateIntegerlastId;publicIntegergetFirstId(){returnfirstId;}publicvoidsetFirstId(IntegerfirstId){d=firstId;}publicIntegergetLastId(){returnlastId;}publicvoidsetLastId(IntegerlastId){=lastId;}}配置文件
">
}publicstaticvoidqueryData(){Sessionsession=sion();PKIDid=newPKID();stId(123);tId(456);Empe=(Emp)(,id);n(e());ession();}publicstaticvoidmain(String[]args){//initData();//queryData();}}Hibernate配置选项Hibernate级联cascade属性的可能值有all:所有情况下均进行关联操作,即save-update和delete。none:所有情况下均不进行关联操作。这是默认值。save-update:在执行save/update/saveOrUpdate时进行关联操作。delete:在执行delete时进行关联操作。all-delete-orphan:当一个节点在对象图中成为孤儿节点时,删除该节点。比如在一个一对多的关系中,Student包含多个book,当在对象关系中删除一个book时,此book即成为孤儿节点。所谓父子关系,即指由父方控制子方的持久化圣明周期,子方对象必须和一个父方对象关联。如果删除父方对象,应该级联删除所有关联的子方对象;如果一个子方对象不再和一个父方对象关联,应该把这个子方对象删除。all-deleteorphan的能力:1.当保存或更新父方对象时,级联保存或更新所有关联的子方对象,相当于cascade为save-update2.当删除父方对象时,级联删除所有关联的子方对象,相当于cascade为delete3.删除不再和父方对象关联的所有子方对象
版权声明:本文标题:Hibernate文档 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.freenas.com.cn/free/1702935898h436588.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论