第一篇:hibernate总结(共)
1、JPA是接口(是一套标准),hibernate是其实现
2、@Entity 表示这个类是实体类(javaBean)
3、@Id 表示主键(javaBean)
4、这样写在配置文件中要书写映射
配置时不一样,不用resouse了,也不用写映射文件了;
但在测试时要用Configuration config = new AnnotationConfiguration(); 其他的都一样了注:加入annotationjia包 :hibernate annotation jar包---ejb3 persistence jar包---
hibernate-common-annotations.jar包 ★在文档中没提到hibernate-common-annotations.jar包
5、若打@符号不提示可修改:windows--properties--搜索content--java--Editor--Content Assist然后改动右下的Auto-Activation中的选项;第一个表示提示的时间,越短表示提示的越快,;第二个表示在java类中是以 “.”号触发的;第三项表示以@来触发javadoc的;你需要把点三项的@改动到第二项中就可以了,想快点提示,把第一项的时间该小点;
6、常见的O/R Mapping Freamworks :hibernate / jdo/toplink/ibatis7、JPA他是O/R Mapping Freamworks框架的接口,像hibenate等框架实现这个接口;类比JDBC和实现它的众多数据库的驱动
★
8、hiberante可以把你建好的表自动生成类(通过逆向工程)
当然也可以通过你建好的类帮你自动生成对应的表;
到底是先类还是先表????
解答: 纯理论是先建类后见表, 你的类建好后可以夸数据库建表,因为我们是面向对象编程,所有的起点都应该是面向对象,从面向对象开始,所以说纯理论是先类后表;
实际中先表后类要比先类后表的多,因为第一、没有hibernate时人们都习惯先表后类,这个习惯不好改了; 第二、建好数据库表后往往要对数据库表进行优化,比如说建索引、建中间表、建视图、建各种各样的优化,若用hibernate自动生成,针对数据库优化的这些内容hibernate是没法帮你生成的9、通过转换,引入log4j的配置文件输出日志信息,想把日志信息输出到配置文件中,改动一下配置文件就行了(log4j.properties);
★ :注解写在get方法上
★ 注解放在get方法上还是放在成员变量上?
解答:应该放在get方法上,若放在成员变量上实际上破坏了java面向对象的封装性,因为成员变量定义成private权限就是不让直接访问的,如果把注解放在其上,hibernate就可以直接去访问你私有的成员变量(java反射访问私有变量),甚至去修改你的私有成员变量
10、ID的自动生成策略解答?(重点AUTO)
解答:若在id的get方法上只标注@GeneratedValue相当于用了AUTO,会根据你连得数据库帮你用哪种生成id的方式;如果你连的是oracle会用sequence,但他建的序列名字是固定的名字~~HIBERNATE_SEQUENCE;
11、TableGenerator(表生成器),他适用于任何一种数据库,如你想让你的数据库跨平台、连数据也跨平台,表生成器是一个好的选择; 若用AUTO跨平台,以个缺点是若用的是
sequence,其序列名字是固定的~~~hibernate-sequence;
12、联合主键:如果有几列联合做主键,其设计模式是,构建一个主键类并实现Serializable
接口,重写equals()方法和hashCode()方法,并有其get/set方法;然后在bena类中构
建一个主键类属性即可;
Serializable接口作用:把当前类的对象序列化的序列化的作用:可以把一个对像直接写到硬盘上,也可以直接从硬盘上读取对像,还可以通过网
络把对象传到对方那去,或者对方把序列化得东西直接传给我;
为什么要实现Serializable接口?
解答:Annotation项目中,对于Woman类,若在内存中有多个Woman类对象,而每个Woman
类对象里都有个WomanPK(主键类)类对像,如果内存满了,要用虚拟内存,就是把硬盘上的一
部分空间作为内存来使用,这就需要把一部分Woman对象暂时先传到硬盘上去,此时就需要用到
序列化了;
为什么要重写equals()方法?
解答:用来保证唯一性的; 我们不仅要在数据库中保证唯一性,还要在内存中保证唯一性,在数据库中通过主键来保证的,类比在内存中的对象也要通过主键类对像来保证其唯一性,达到与
数据库同步,所以在这种情况下应该重写equals和hashCode;所以说既然用了联合主键,就
应该重写equals和hashCode方法,而且他的逻辑还不能乱用,不能用父类里面的equals,两个同样的对象就视为同一个对象;
为什么要重写hashCode()方法
解答:要查哈希表中的内容是否相等时首先从hashCode查起;最简单的哈希表可看作是一
个表格或数组,里面有好多位置,每个位置放的是哈希值相同的对象,所以里面往往装的是一个
链表;例如有两个类A、B,他们的哈希值都是1,他们就会被放在哈希表中的同一个位置,若要
查询哈希标中某个类和哈希表中的那个类相同,首先要计算出这个类的哈希值,通过计算出的哈
希值直接定位到与这个哈希值相等的位置,然后循环遍历出这个哈希值里面的对象,找出与哈希
标中对象相同的对象;注:存放Woman对象时,计算对象里面的主键类对象的哈希码值(不是
计算对象的哈希码值),然后存入哈希表中;
13、从数据库中取一个对象的方法:get();和 load();二者区别?
解答:当用session.get()去拿一个对象的时候,他马上发出sql语句,从数据库中取
出对象的值来把它装到对象中去(此时对象中已有值了),不会产生延迟;
若用load()方法去拿对象时,load生成的是一个代理对象(他并没有对象的属性值),他
并没有真正的发出sql语句从数据库中取出数据,sql语句其实是在你需要拿那个对象的属性
是才发出的,当然从数据库中拿属性时肯定需要session对象,若session关闭会报错;
若用get或load取数据时,数据库中没有那条数据,get会报错,load不会,因为没有
用对象的属性,load就不会马上发送sql语句,也就不会去连数据库;
☆ 判断一个对象是代理对象还是普通对象?
解答:打印对象所在的类名; 如t对象System.out.println(t.class);
接受代理对象的类是实际类的子类;(拿属性时要调用类中方法,代理类又没有)
14、update()方法总结及注意事项?(注:★update方法会在commit时才发update语句)
解答:第一:用来更新detached状态的对象,更新完成后对象转为persistent状态;
第二:更新transisent状态的对象会报错;
第三:更新自己手动设定id的transisent对象可以(前提是数据库中有对应的记录)
第四:处于persistent状态的对象若被改变,若跟原来(和缓存中的比较)的值不相同就会发
sql语句,发sql语句时会把所有字段都更新,若跟原来的值相同就不会发送sql语句;
第五:若在xml中设置成动态更新,没变的值是不会更新的,(他是把改过的值和在内存中对应的对象进行比较,若值相同就不把这个字段夹在sql语句中,反之夹在sql语句中; 若对象
在内存中不存在,会把所有字段都更新,即发送所有字段)(跨session)
若想跨session也想知更新改过的字段,用merge(s对象)方法(他会先从数据库把对
应的对象取出,然后比较在发update语句)
只更新部分字段建议用HQL(EJBQL)语句,面向对象的语句;
15、saveOrUpdate()方法,没id时肯定执行save,有id且做了属性改变执行update方
法;
16、clear()方法:不管是get方法还是用load方法取对象都是先从缓存中查找(一级缓
存),如果缓存中没有才会从数据库中查找,调用clear方法会强制清空session缓存;
17、flush()方法:强制进行从内存到数据库同步;在什么时候flush是受FlushMode控
制,这可以设置,在session对象刚建立时设置什么时候flush;
18、SchemaExport类:用于在程序中生成建表语句;
关系映射(重点)
<有双向关联必设mappedBy=”对方属性名”>
1、关系映射指的是对象之间的关系,并不是指数据库之间的关系;(数据库中表之间只有主
外建关系)《分单向和双向,其数据库是一样的》
2、一对一关系(单向关联:丈夫表对应的bean类中有妻子表bean对象属性,妻子表中没
有丈夫表bean对象):
a)、一对一单向外键关联(丈夫表中多出一个id,它是引用妻子表中的id值,也就是
说妻子表中id存在,丈夫表中的那个id值才能存在: emp和dept):
Annation::@OneToOne @JoinColumn
b)、一对一单向主键关联(不重要丈夫表和 妻子表中都多出一id,并且都是引用对方
表的id值):xml c)、一对一单向 双主键 关联(丈夫表中有两个字段做主键《双主键》去引用妻子表 中 id值):此时的bean需要实现serialzable接口,还得重写hasCode()和 equals()方法; 3、一对一关系(双向关联:丈夫表和妻子表都有对方法的bena对象): a)一对一双向外键关联:@OneToOne(mappedBy 对方那里是主导) xml b)一对一双向主键关联: 4、组件映射:还拿妻子和丈夫来说—在数据库中妻子和丈夫做成一张表,妻子是丈夫表的一部 分,但在写bean时还是丈夫bean和妻子bean,但此时妻子bean中就没有id了,丈夫表中还有妻子bean对象引用,用Annotation配置是在丈夫bean中的妻子引用上 加上@Embedded就可以了;在访问时通过丈夫对象和妻子对象来访问; 5、多对一的数据库设计一般是:在多方加外键; 多对一 单向关联:在类中的映射,在多的那个bean类中加上单个bean的类的属性就行 用Annotation配置 :在加的那个bean属性上配置:@ManyToOne就行了; 多对一双向关联:和平时练习的一样,一个bean属性一个Set集合属性; 此时Annotation配置是:在多里@ManyToOne单个里 @OneToMany(mappedBy=”group”) 6、一对多单向关联:数据库的设计和多对一的是一样的; 一对多的单向关联:在类中的映射,在单个bean类中加上多个bean的类的set集合属性就 行了; 用Annotation配置:在加的那个bean属性上配置: @OneToMany 和 @JoinColumn(name=”多bean类中的外键名”) 一对多 和多对一的双向关联:单的加对方set集合属性,多的一方加对方bean属性; 7、多对多的单向关联: 首先数据库的一般设计是: 建一个中间表,中间表有两个id分别引 用两个对象的id值,并且两id做主键(双主键),多对多的单向关联:只在一方间立对方的set集合,xml配置也只配有集合的一方; 多对多双向关联(少用):个在自己bena中加上对方set<对方bena>集合属性; 配置是: 8、cascade=“all”----可以取的值:all(所有 时级联)、remove(删除时级联),其他两个不常用:----刷新和合并; 《除了all,其他的只有在调用其对应的方法时才级联;》 Eg:存A关联到B,而B又关联到C,此时就可以在A的xml中用于映射对象的的标签加上 cascade属性,在B也中加上就行了;它不是必须的,也可以先存储C--在存储B—在存储A; 《有关联就可以用它,不管是那种关联,一对一还是多对 一、或一对多 都行;》 铁律:双向关系在程序中要设定双向关联; 9、fetch(抓取):用于从数据库中读取数据时能够级联读取; 它有两个值:eager《渴望的》表示立即加载== 和 lazy《懒惰的》表示延迟加载,不用不加载,用时才加载数据<级联的>; 取一不要多《lazy》取多要一《eager》 cascade用于级联增、删、改fetch用于 查 级联; 注意: 1、上面说的cascade管增、删、改,fetch管 查的解释:其实cascade对增、删、改、查都是级联的,只不过是在查询时分为立即加载和延迟加载,你若用立即加载,不 管你用不用都会同时把所关联的数据提取出来放入内存中,若用延迟加载,只有等到你 用到所关联的对象时,才会从数据库中把数据提取出来; 2、若用的是延迟加载:只有你用到被关联的数据时才会从数据库中提取出来,此时必须在session关闭之前操作,因为它是用session从数据库中提取数据的; 而立即加载会在你从数据库提取数据(当前数据)时把所关联的数据一块取出放入内存 中,若你在读取这部分关联的操作,在session关闭前后都可以,它是从内存中 取的;10、11、更新数据: 第一种:先把要更新的数据get()或load()出来,然后对其赋予你想的值,commitxml中:inverse=”true” 《set的属性》;表示关联关系在对方那里设定,取我不用拿对方,取对方必须拿我; 后会帮你更改;这种方式会发送两条update语句,第一条更改user 第二改group 第二种:用update方法更新数据: update方法用于更新托管状态的对象,即:脱离 session管理的对象,先get()出来,然后关闭session,对get出来的对象从新赋值,然后在得到另一个session,在用update更新数据,==关闭session; 12、删除对象:先把要删除的对象get出来,然后把关联关系设为null<打破关联关系>,在调用delete()方法,如不设为null,会把二者有关联的数据全删除掉; 注解:删除u1会关联到group1,然而删group2又会关联到u2,所有若不打破关联关系 会把所有相互关联的数据全部删除掉;u.setGroup(null);打破关联关系; 另一种方式是:用hql语句删除对象,实际中此方法用的多; 13、查询语句: ===、缓存问题: 分为- 一级缓存、二级缓存、查询缓存(三级缓存) 一级缓存:称为session级别的缓存, 每个session都有各自的缓存; 二级缓存:可称为sessionFactory级别的缓存;session会先从二级缓存中查找所需 数据,找不到才发送sel语句从数据库中提取所需数据; 若想用eh二级缓存,首先在habernate.cfg.xml中打开二级缓存,然后到habernate的文档去找到eh的xml文件,拷贝到项目中,和habernate.cfg.xml同级别;project—etc适合放二级缓存的数据: 1、经常被访问 2、不会被经常改动 3、数据量不大; 实际中,不到万不得已一般是不会考虑二级缓存; 精华-Hibernate面试题及答案大集合 1.一般情况下,关系数据模型与对象模型之间有哪些匹配关系(多选) A)表对应类B)记录对应对象C)表的字段对应类的属性D)表之间的参考关系对应类之间的依赖关系(1)A,B,C 2.以下关于SessionFactory的说法哪些正确?(多选) A)对于每个数据库事务,应该创建一个SessionFactory对象B)一个SessionFactory对象对应一个数据库存储源。C)SessionFactory是重量级的对象,不应该随意创建。如果系统中只有一个数据库存储源,只需要创建一个。D)SessionFactory的load()方法用于加载持久化对象(2)B,C 3.Customer类中有一个Set类型的orders属性,用来存放Order订单对象,在Customer.hbm.xml文件中,用哪个元素映射orders属性? A)B)C)D)<:property>(3)A 4.元素有一个cascade属性,如果希望Hibernate级联保存集合中的对象,casecade属性应该取什么值?(单选) A)noneB)saveC)deleteD)save-update(4)D 5.以下哪些属于Session的方法? A)load()B)save()C)delete()D)update()E)open()F)close()(5)A,B,C,D,F 6.以下程序的打印结果是什么?(单选) 1.2.3.4.tx = session.beginTransaction();Customer c1=(Customer)session.load(Customer.class,new Long(1));Customer c2=(Customer)session.load(Customer.class,new Long(1));System.out.println(c1==c2);5.6.tx.commit();session.close();A)运行出错,抛出异常B)打印falseC)打印true(6)C 7.以下程序代码对Customer的name属性修改了两次: 7.8.9.tx = session.beginTransaction();Customer customer=(Customer)session.load(Customer.class, new Long(1));10.customer.setName(“Jack”);11.customer.setName(“Mike”);12.tx.commit();执行以上程序,Hibernate需要向数据库提交几条update语句?(单选)A)0 B)1 C)2 D)3(7)B 8.在持久化层,对象分为哪些状态?(多选)A)临时状态B)独立状态C)游离状态D)持久化状态(8)A,C,D 9.对于以下程序,Customer对象在第几行变为持久化状态?(单选) 13.Customer customer=new Customer();//line1 14.customer.setName(“Tom”);//line2 15.Session session1=sessionFactory.openSession();//line3 16.Transaction tx1 = session1.beginTransaction();//line4 17.session1.save(customer);//line4 18.tx1.commit();//line5 19.session1.close();//line6 A)line1 B)line2 C)line3 D)line4 E)line5 F)line6(9)D 10.对于以下程序,Customer对象在第几行变为游离状态?(单选) 20.Customer customer=new Customer();//line1 21.customer.setName(“Tom”);//line2 22.Session session1=sessionFactory.openSession();//line3 23.Transaction tx1 = session1.beginTransaction();//line4 24.session1.save(customer);//line4 25.tx1.commit();//line5 26.session1.close();//line6 A)line1 B)line2 C)line3 D)line4 E)line5 F)line6(10)F 11.以下哪一种检索策略利用了外连结查询?(单选)A)立即检索 B)延迟检索 C)迫切左外连结检索(11)C 12.假设对Customer类的orders集合采用延迟检索策略,编译或运行以下程序,会出现什么情况(单选) 27.Session session=sessionFactory.openSession();28.tx = session.beginTransaction();29.Customer customer=(Customer)session.get(Customer.class,new Long(1)); 30.tx.commit();31.session.close();32.Iterator orderIterator=customer.getOrders().iterator();A)编译出错 B)编译通过,并正常运行 C)编译通过,但运行时抛出异常(12)C 13.关于HQL与SQL,以下哪些说法正确?(多选) A)HQL与SQL没什么差别B)HQL面向对象,而SQL操纵关系数据库C)在HQL与SQL中,都包含select,insert,update,delete语句D)HQL仅用于查询数据,不支持insert,update和delete语句 (13)B,D 14.事务隔离级别是由谁实现的?(单选) A)Java应用程序 B)Hibernate C)数据库系统 D)JDBC驱动程序(14)C 15.悲观锁与乐观锁,哪个具有较好的并发性能?(单选)A)悲观锁 B)乐观锁(15)B Hibernate工作原理及为什么要用? 原理: 1.读取并解析配置文件 2.读取并解析映射信息,创建SessionFactory 3.打开Sesssion 4.创建事务Transation 5.持久化操作 6.提交事务 7.关闭Session 8.关闭SesstionFactory 为什么要用: 1.对JDBC访问数据库的代码做了封装,大大简化了数据访问层繁琐的重复性代码。 2.Hibernate是一个基于JDBC的主流持久化框架,是一个优秀的ORM实现。他很大程度的简化DAO层的编码工作 3.hibernate使用Java反射机制,而不是字节码增强程序来实现透明性。 4.hibernate的性能非常好,因为它是个轻量级框架。映射的灵活性很出色。它支持各种关系数据库,从一对一到多对多的各种复杂关系。 2. Hibernate是如何延迟加载? 1.Hibernate2延迟加载实现:a)实体对象 b)集合(Collection) 2.Hibernate3 提供了属性的延迟加载功能 当Hibernate在查询数据的时候,数据并没有存在与内存中,当程序真正对数据的操作时,对象才存在与内存中,就实现了延迟加载,他节省了服务器的内存开销,从而提高了服务器的性能。 3.Hibernate中怎样实现类之间的关系?(如:一对多、多对多的关系) 类与类之间的关系主要体现在表与表之间的关系进行操作,它们都市对对象进行操作,我们程序中把所有的表与类都映射在一起,它们通过配置文件中的many-to-one、one-to-many、many-to-many、4. 说下Hibernate的缓存机制 1.内部缓存存在Hibernate中又叫一级缓存,属于应用事物级缓存 2.二级缓存: a)应用及缓存 b)分布式缓存 条件:数据不会被第三方修改、数据大小在可接受范围、数据更新频率低、同一数据被系统频繁使用、非 关键数据 c)第三方缓存的实现 5. Hibernate的查询方式 Sql、Criteria,object comptosition Hql: 1、属性查询 2、参数查询、命名参数查询 3、关联查询 4、分页查询 5、统计函数 6. 如何优化Hibernate? 1.使用双向一对多关联,不使用单向一对多 2.灵活使用单向一对多关联 3.不用一对一,用多对一取代 4.配置对象缓存,不使用集合缓存 5.一对多集合使用Bag,多对多集合使用Set 6.继承类使用显式多态 7.表字段要少,表关联不要怕多,有二级缓存撑腰 7. Struts工作机制?为什么要使用Struts? 工作机制: Struts的工作流程: 在web应用启动时就会加载初始化ActionServlet,ActionServlet从 struts-config.xml文件中读取配置信息,把它们存放到各种配置对象 当ActionServlet接收到一个客户请求时,将执行如下流程.-(1)检索和用户请求匹配的ActionMapping实例,如果不存在,就返回请求路径无效信息;-(2)如果ActionForm实例不存在,就创建一个ActionForm对象,把客户提交的表单数据保存到ActionForm对象中;-(3)根据配置信息决定是否需要表单验证.如果需要验证,就调用ActionForm的validate()方法;-(4)如果ActionForm的validate()方法返回null或返回一个不包含ActionMessage的ActuibErrors对象, 就表示表单验证成功;-(5)ActionServlet根据ActionMapping所包含的映射信息决定将请求转发给哪个Action,如果相应的 Action实例不存在,就先创建这个实例,然后调用Action的execute()方法;-(6)Action的execute()方法返回一个ActionForward对象,ActionServlet在把客户请求转发给 ActionForward对象指向的JSP组件;-(7)ActionForward对象指向JSP组件生成动态网页,返回给客户; 为什么要用: JSP、Servlet、JavaBean技术的出现给我们构建强大的企业应用系统提供了可能。但用这些技术构建的系统非常的繁乱,所以在此之上,我们需要一个规则、一个把这些技术组织起来的规则,这就是框架,Struts便应运而生。 基于Struts开发的应用由3类组件构成:控制器组件、模型组件、视图组件 8. Struts的validate框架是如何验证的? 在struts配置文件中配置具体的错误提示,再在FormBean中的validate()方法具体调用。 9. 说下Struts的设计模式 MVC 模式: web应用程序启动时就会加载并初始化ActionServler。用户提交表单时,一个配置好的ActionForm对象被创建,并被填入表单相应的数据,ActionServler根据Struts-config.xml文件配置好的设置决定是否需要表单验证,如果需要就调用ActionForm的 Validate()验证后选择将请求发送到哪个Action,如果Action不存在,ActionServlet会先创建这个对象,然后调用 Action的execute()方法。Execute()从ActionForm对象中获取数据,完成业务逻辑,返回一个ActionForward对象,ActionServlet再把客户请求转发给ActionForward对象指定的jsp组件,ActionForward对象指定的jsp生成动态的网页,返回给客户。 10. spring工作机制及为什么要用? 1.spring mvc请所有的请求都提交给DispatcherServlet,它会委托应用系统的其他模块负责负责对请求进行真正的处理工作。 2.DispatcherServlet查询一个或多个HandlerMapping,找到处理请求的Controller.3.DispatcherServlet请请求提交到目标Controller 4.Controller进行业务逻辑处理后,会返回一个ModelAndView 5.Dispathcher查询一个或多个ViewResolver视图解析器,找到ModelAndView对象指定的视图对象 6.视图对象负责渲染返回给客户端。为什么用: {AOP 让开发人员可以创建非行为性的关注点,称为横切关注点,并将它们插入到应用程序代码中。使用 AOP 后,公共服务(比如日志、持久性、事务等)就可以分解成方面并应用到域对象上,同时不会增加域对象的对象模型的复杂性。 IOC 允许创建一个可以构造对象的应用环境,然后向这些对象传递它们的协作对象。正如单词 倒置 所表明的,IOC 就像反 过来的 JNDI。没有使用一堆抽象工厂、服务定位器、单元素(singleton)和直接构造(straight construction),每一个对象都是用其协作对象构造的。因此是由容器管理协作对象(collaborator)。 Spring即使一个AOP框架,也是一IOC容器。Spring 最好的地方是它有助于您替换对象。有了 Spring,只要用 JavaBean 属性和配置文件加入依赖性(协作对象)。然后可以很容易地在需要时替换具有类似接口的协作对象。} Spring 框架是一个分层架构,由 7 个定义良好的模块组成。Spring 模块构建在核心容器之上,核心容器定义了创建、配置和管理 bean 的方式,如图 1 所示。 组成 Spring 框架的每个模块(或组件)都可以单独存在,或者与其他一个或多个模块联合实现。每个模块的功能如下: ☆ 核心容器:核心容器提供 Spring 框架的基本功能。核心容器的主要组件是 BeanFactory,它是工厂模式的实现。BeanFactory 使用控制反转(IOC)模式将应用程序的配置和依赖性规范与实际的应用程序代码分开。 ☆ Spring 上下文:Spring 上下文是一个配置文件,向 Spring 框架提供上下文信息。Spring 上下文包括企业服务,例如 JNDI、EJB、电子邮件、国际化、校验和调度功能。 ☆ Spring AOP:通过配置管理特性,Spring AOP 模块直接将面向方面的编程功能集成到了 Spring 框架中。所以,可以很容易地使 Spring 框架管理的任何对象支持 AOP。Spring AOP 模块为基于 Spring 的应用程序中的对象提供了事务管理服务。通过使用 Spring AOP,不用依赖 EJB 组件,就可以将声明性事务管理集成到应用程序中。 ☆ Spring DAO:JDBC DAO 抽象层提供了有意义的异常层次结构,可用该结构来管理异常处理和不同数据库供应商抛出的错误消息。异常层次结构简化了错误处理,并且极大地降低了需要编写的异常代码数量(例如打开和关闭连接)。Spring DAO 的面向 JDBC 的异常遵从通用的 DAO 异常层次结构。 ☆ Spring ORM:Spring 框架插入了若干个 ORM 框架,从而提供了 ORM 的对象关系工具,其中包括 JDO、Hibernate 和 iBatis SQL Map。所有这些都遵从 Spring 的通用事务和 DAO 异常层次结构。 ☆ Spring Web 模块:Web 上下文模块建立在应用程序上下文模块之上,为基于 Web 的应用程序提供了上下文。所以,Spring 框架支持与 Jakarta Struts 的集成。Web 模块还简化了处理多部分请求以及将请求参数绑定到域对象的工作。 ☆ Spring MVC 框架:MVC 框架是一个全功能的构建 Web 应用程序的 MVC 实现。通过策略接口,MVC 框架变成为高度可配置的,MVC 容纳了大量视图技术,其中包括 JSP、Velocity、Tiles、iText 和 POI。 Spring 框架的功能可以用在任何 J2EE 服务器中,大多数功能也适用于不受管理的环境。Spring 的核心要点是:支持不绑定到特定 J2EE 服务的可重用业务和数据访问对象。毫无疑问,这样的对象可以在不同 J2EE 环境(Web 或 EJB)、独立应用程序、测试环境之间重用。 IOC 和 AOP 控制反转模式(也称作依赖性介入)的基本概念是:不创建对象,但是描述创建它们的方式。在代码中不直接与对象和服务连接,但在配置文件中描述哪一个组件需要哪一项服务。容器(在 Spring 框架中是 IOC 容器)负责将这些联系在一起。 在典型的 IOC 场景中,容器创建了所有对象,并设置必要的属性将它们连接在一起,决定什么时间调用方法。下表列出了 IOC 的一个实现模式。 Spring 框架的 IOC 容器采用类型 2 和类型3 实现。 面向方面的编程 面向方面的编程,即 AOP,是一种编程技术,它允许程序员对横切关注点或横切典型的职责分界线的行为(例如日志和事务管理)进行模块化。AOP 的核心构造是方面,它将那些影响多个类的行为封装到可重用的模块中。 AOP 和 IOC 是补充性的技术,它们都运用模块化方式解决企业应用程序开发中的复杂问题。在典型的面向对象开发方式中,可能要将日志记录语句放在所有方法和 Java 类中才能实现日志功能。在 AOP 方式中,可以反过来将日志服务模块化,并以声明的方式将它们应用到需要日志的组件上。当然,优势就是 Java 类不需要知道日志服务的存在,也不需要考虑相关的代码。所以,用 Spring AOP 编写的应用程序代码是松散耦合的。 AOP 的功能完全集成到了 Spring 事务管理、日志和其他各种特性的上下文中。 IOC 容器 Spring 设计的核心是 org.springframework.beans 包,它的设计目标是与 JavaBean 组件一起使用。这个包通常不是由用户直接使用,而是由服务器将其用作其他多数功能的底层中介。下一个最高级抽象是 BeanFactory 接口,它是工厂设计模式的实现,允许通过名称创建和检索对象。BeanFactory 也可以管理对象之间的关系。 BeanFactory 支持两个对象模型。 □ 单态 模型提供了具有特定名称的对象的共享实例,可以在查询时对其进行检索。Singleton 是默认的也是最常用的对象模型。对于无状态服务对象很理想。 □ 原型 模型确保每次检索都会创建单独的对象。在每个用户都需要自己的对象时,原型模型最适合。 bean 工厂的概念是 Spring 作为 IOC 容器的基础。IOC 将处理事情的责任从应用程序代码转移到框架。正如我将在下一个示例中演示的那样,Spring 框架使用 JavaBean 属性和配置数据来指出必须设置的依赖关系。 BeanFactory 接口 因为 org.springframework.beans.factory.BeanFactory 是一个简单接口,所以可以针对各种底层存储方法实现。最常用的 BeanFactory 定义是 XmlBeanFactory,它根据 XML 文件中的定义装入 bean,如清单 1 所示。 清单 1.XmlBeanFactory BeanFactory factory = new XMLBeanFactory(new FileInputSteam(“mybean.xml”)); 在 XML 文件中定义的 Bean 是被消极加载的,这意味在需要 bean 之前,bean 本身不会被初始化。要从 BeanFactory 检索 bean,只需调用 getBean()方法,传入将要检索的 bean 的名称即可,如清单 2 所示。 清单 2.getBean() MyBean mybean =(MyBean)factory.getBean(“mybean”); 每个 bean 的定义都可以是 POJO(用类名和 JavaBean 初始化属性定义)或 FactoryBean。FactoryBean 接口为使用 Spring 框架构建的应用程序添加了一个间接的级别。 IOC 示例 理解控制反转最简单的方式就是看它的实际应用。在对由三部分组成的 Spring 系列 的第 1 部分进行总结时,我使用了一个示例,演示了如何通过 Spring IOC 容器注入应用程序的依赖关系(而不是将它们构建进来)。 我用开启在线信用帐户的用例作为起点。对于该实现,开启信用帐户要求用户与以下服务进行交互: ☆ 信用级别评定服务,查询用户的信用历史信息。 ☆ 远程信息链接服务,插入客户信息,将客户信息与信用卡和银行信息连接起来,以进行自动借记(如果需要的话)。 ☆ 电子邮件服务,向用户发送有关信用卡状态的电子邮件。 三个接口 对于这个示例,我假设服务已经存在,理想的情况是用松散耦合的方式把它们集成在一起。以下清单显示了三个服务的应用程序接口。清单 3.CreditRatingInterface public interface CreditRatingInterface { public boolean getUserCreditHistoryInformation(ICustomer iCustomer);} 清单 3 所示的信用级别评定接口提供了信用历史信息。它需要一个包含客户信息的 Customer 对象。该接口的实现是由 CreditRating 类提供的。 清单 4.CreditLinkingInterface public interface CreditLinkingInterface { public String getUrl();public void setUrl(String url);public void linkCreditBankAccount()throws Exception;} 信用链接接口将信用历史信息与银行信息(如果需要的话)连接在一起,并插入用户的信用卡信息。信用链接接口是一个远程服务,它的查询是通过 getUrl()方法进行的。URL 由 Spring 框架的 bean 配置机制设置,我稍后会讨论它。该接口的实现是由 CreditLinking 类提供的。 清单 5.EmailInterface public interface EmailInterface { public void sendEmail(ICustomer iCustomer);public String getFromEmail();public void setFromEmail(String fromEmail);public String getPassword();public void setPassword(String password);public String getSmtpHost();public void setSmtpHost(String smtpHost);public String getUserId();public void setUserId(String userId); 学习Hibernate,如何快速入门? 1. 学习Hibernate,入门的重点是什么? a)怎么样在我的Tomcat中配置Hibernate? 2种类型的配置文件 2类Jar包(jdbc jar包、hibernate jar包集合)b)我怎么样在我的Java程序中使用Hibernate? 标准代码 2. Hibernate技术中最重要的30%常用技术是什么? a)在Tomcat中熟练配置Hibernate; b)在使用Session和Query对象熟练的执行增删改查操作; c)基本的HQL开发; 下面看个示例: public List String hql = “select m.id as {menu.id},m.name as {menu.name},m.url as {menu.url},m.icon_url as {menu.iconUrl},m.parent_id as {menu.parentId},” +“m.serial_number as {menu.serialNo},m.admin as {menu.adminUse},m.system_admin as {menu.systemAdmin} ,m.program_name as {menu.programName}” +“ from menu m, entity_type et, entity_admin_menu eam” +“ where et.id = ”+id+“" +” and m.program_name = '“+GlobalNames.PROGRAM_NAME_CHSS+”'“ +” and et.id = eam.entity_id“ +” and m.id = eam.menu_id“; List第二篇:精华-Hibernate面试题及答案大集合
第三篇:学习Hibernate,如何快速入门
第四篇:hibernate执行sql语句的总结
nu”,Menu.class).list();
return menus;
}
1.通过addEntity(“menu”,Menu.class),通过addEntity把要返回的数据强转为Menu,注意Menu必须要是配置hibernate映射了的。m.id as {menu.id},这是为了如果数据库字段名和Menu模型中不一样所以都as取了个别名,那么这样就能返回menu对象了。
2、如果要执行的sql语句是多表查询,并且是返回一个对象。但是这个对象是没有配置hibernate映射的。这种就麻烦了。hibernate执行SQL默认返回的是一个object类型的数组,List menus
=super.getSessionFactory().getCurrentSession().createSQLQuery(hql).list();
for(int i=0;i {Object[] objects =(Object[])menus.get(i);for(int j=0;j 运行后报错:java.lang.ClassCastExceptionjava.lang.Object;cannot be cast to net.greatsoft.chss.domain.privilege.model.Menu,原来是查询出来的字段并不能自动转换为bean对象,所以要添加addEntity(Clazz class)。有人肯定会说添加addEntity了,但是如果Menu没有添加hibernate映射的话,此时会报Menu unmapping。。。就是没添加映射,所以只能添加setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP);//返回一个map,KEY:为DB中名称一致(大小写一致)遍历list时就可以。所以只能将返回的值变成Map,这样就好操作了,然后就可用反射取值了,详细看:hibernate 执行sql语句返回自定义对象 3、hibernate 中createQuery与createSQLQuery两者区别是: 前者用的hql语句进行查询,后者可以用sql语句查询 前者以hibernate生成的Bean为对象装入list返回,后者则是以对象数组进行存储 所以使用createSQLQuery有时候也想以hibernate生成的Bean为对象装入list返回,就不是很menus = super.getSessionFactory().getCurrentSession().createSQLQuery(hql).addEntity("me 方便 突然发现createSQLQuery有这样一个方法可以直接转换对象 Query query = session.createSQLQuery(sql).addEntity(XXXXXXX.class); XXXXXXX 代表以hibernate生成的Bean的对象,也就是数据表映射出的Bean。但是这个bean必须有映射 呵呵以后多注意,还是时不时的要看看hibernate各个对象方法的使用. Hibernate(6)—— 一对多和多对多关联关系映射(xml和注解)总结 涉及的知识点总结如下: One to Many 映射关系 o 多对一单向外键关联(XML/Annotation)o 一对多单向外键关联(XML/Annotation)o 懒加载和积极加载 o 一对多双向外键关联(XML/Annotation) Many to Many 映射关系 o 多对多单向外键关联(XML/Annotation)o 多对多双向外键关联(XML/Annotation)o set的inverse元素详解 问题小结 关联关系的优缺点 多对一单向外键关联关系 注意多对一关联是多方持有一方的引用。看一个例子,去淘宝购物,那么一个淘宝用户可以对应多个购物订单,如图所示: 多的一方是Orders,持有一方的引用,也就是Users,而在Users中无需作任何定义,从订单到用户的关系是单向多对一关联。对应数据库就是: 还有比如说学生和班级的关系,多个学生可以属于同一个班级,这就是从学生到班级也是典型的单向多对一关系,看代码实现: 基于注解的多对一单向外键关联: 单向多对一关联中,多方需要持有一方的引用,那么多方(学生类)需要额外配置,需要对持有的一方引用使用注解@ManyToOne(cascade={CascadeType.ALL}, fetch=FetchType.EAGER),设置为级联操作和饥渴的抓取策略,@JoinColumn(name=“cid”),而一方(教室类)无需做任何多方的定义。 注意;多方必须保留一个不带参数的构造器! importjavax.persistence.Entity;importjavax.persistence.GeneratedValue;importjavax.persistence.Id; //班级类,在多对一关系中属于一的方,不持有其他多余的配置,反而是被多方持有 @Entity public class ClassRoom { private intcid;//班级编号 private String cname;//班级名称 // 自动增长的主键 @Id @GeneratedValue publicintgetCid(){ returncid;} public void setCid(intcid){ this.cid = cid;} public String getCname(){ returncname;} public void setCname(String cname){ this.cname = cname;} } View Code 一方——班级类无需做多余的定义,下面是多方——学生实体和配置: importjavax.persistence.CascadeType;importjavax.persistence.Entity;importjavax.persistence.FetchType;importjavax.persistence.GeneratedValue;importjavax.persistence.Id;importjavax.persistence.JoinColumn;importjavax.persistence.ManyToOne; //学生实体类,属于多对一的多方,持有班级(一方)的引用 @Entity public class Students { private intsid;//编号 private String sname;//姓名 private ClassRoom classroom;//学生班级 //注意:多方一定要显式的定义不带参数的构造方法 public Students(){ } public Students(String sname){ this.sname = sname;} // 多方使用注解:@ManyToOne // fetch=FetchType.EAGER,急加载,加载一个实体时,定义急加载的属性会立即从数据库中加载。 // 全部级联操作,referencedColumnName显式设置数据库字段名cid,不写默认就是和name一样的。 @ManyToOne(cascade={CascadeType.ALL}, fetch=FetchType.EAGER)@JoinColumn(name=“cid”,referencedColumnName=“cid”)publicClassRoomgetClassroom(){ return classroom;} public void setClassroom(ClassRoom classroom){ this.classroom = classroom;} // 自动增长主键 @Id @GeneratedValue publicintgetSid(){ returnsid;} public void setSid(intsid){ this.sid = sid;} public String getSname(){ returnsname;} public void setSname(String sname){ this.sname = sname;} } View Code 下面测试:先生成数据库脚本,再进行学生对象的插入 public class TestStudentsByAnno { private static SessionFactorysessionFactory; @Before public void setUp()throws Exception { System.out.println(“setUp()...”);sessionFactory = new AnnotationConfiguration().configure().buildSessionFactory();} @After public void tearDown()throws Exception { System.out.println(“tearDown()...”);sessionFactory.close();} @Test public void testSave(){ Session session = sessionFactory.getCurrentSession();Transaction tx = session.beginTransaction(); try { ClassRoom c = new ClassRoom();c.setCname(“computer001”); Students s = new Students(“zhangsan”);s.setClassroom(c); session.save(s);tx.commit();} catch(Exception ex){ ex.printStackTrace();tx.rollback();} } @Test @Ignore public void testSchemaExport(){ SchemaExport se = new SchemaExport(new AnnotationConfiguration().configure());se.create(true, true);} } View Code 反向创建表的数据库脚本如下: create table ClassRoom(cid integer not null auto_increment, cnamevarchar(255), primary key(cid))create table Students(sid integer not null auto_increment, snamevarchar(255), cid integer, primary key(sid)) 插入一个学生对象,会自动生成如下语句: ClassRoom c = new ClassRoom();c.setCname(“computer001”); Students s = new Students(“zhangsan”);s.setClassroom(c); session.save(s);tx.commit();View Code Hibernate: insert into ClassRoom(cname)values(?)Hibernate: insert into Students(cid, sname)values(?, ?)插入成功: 基于xml配置实现多对一单向外键关联 View Code 一方(教室类)无需做任何多方的定义。只需要维护好自己的属性配置即可。而多方只需要加上 hibernate.cfg.xml里加上 多对一时候,多方设置EAGER加载,一对多的时候,一方设置LAZY加载 多对多关联,多方需要保留一个无参构造器。第五篇:Hibernate(6)—— 一对多和多对多关联关系映射(xml和注解)总结