首页 > 代码库 > hibernate整理
hibernate整理
国外框架项目地址:http://websystique.com/springmvc/spring-mvc-4-angularjs-example/ Angularjs文本输入框用ng-moduel,其他的用{{ }} 放行用.*? Angularjs插件地址http://www.cnblogs.com/pilixiami/p/5634405.html UI班的教程:http://pan.baidu.com/share/link?shareid=4146906997&uk=866705889 非严格读写是并发的概念 Spring不支持多线程 Flush()强制要求缓存与数据库一致 Eache表连接,lazy子查询 ORM: 编写程序时,以面向对象的方式处理数据 保存数据时是以关系型数据库的方式存储的 Hibernate的数据持久化: New实例化对象时默认是瞬时的 Jdbc连接数据库时,持久化数据 将数据存入硬盘 单向关联关系: 一个类单方向包含另一个类为属性,模拟数据库外键 mysql数据库附加: String driver=com.mysql.jdbc.Driver String url=jdbc:mysql://localhost:3306/demo Hibernate实体类: (1) @Entity @Table(name="t_emp") 这个表示一个实体类,Table表示对应数据库中的表名。 (2) @Id @GeneratedValue 这个表示主键自动增长 (3) @ManyToOne @JoinColumn(name="dept_id") 这个表示关联对象以及关联的字段名字 (4) @Column(name="emai") 和数据库中字段不一样的,要通过这个属性写清楚。 (5) @Temporal(TemporalType.TIMESTAMP) 和@Temporal(TemporalType.DATE) 表示时间字段 @manyTomany必须有第三个表为中间表,命名为中间表的表名为:表名_表名2,命名不规范要@ManyToMany(mappedBy="表名") 在hibernate中分页参数与mysql一致,排除几笔取几笔 Hibernate不用stringMVC而是用ORM框架 Mybaties连接数据库用的数据库连接池是dbcp,而hibernate用c3p0 Hibernate连接数据库还要面包切的jar包 Hibernate实体类的生命周期: 瞬时状态:刚用new语句创建,还没有被持久化,且不处于session的缓存中 持久状态:已被持久化,且加入到session缓存中,执行了update()或save()方法时 游离状态:已经被持久化,但是不再处于session缓存中 jdbc与hibernate区别 ? JDBC与hibernate在性能上相比,JDBC灵活性有优势。 而Hibernate在易学性,易用性上有些优势。 当用到很多复杂的多表联查和复杂的数据库操作时,JDBC有优势。 相同点: 两者都是Java的数据库操作。 两者对于数据库进行直接操作的对象都不是线程安全的,都需要及时关闭。 两者都可以对数据库的更新操作进行显式的事务处理。 不同点: 使用的SQL语言不同: JDBC使用的是基于关系型数据库的标准SQL语言, Hibernate使用的是HQL(Hibernate query language)语言 操作的对象不同: JDBC操作的是数据,将数据通过SQL语句直接传送到数据库中执行, Hibernate操作的是持久化对象,由底层持久化对象的数据更新到数据库中。 数据状态不同: JDBC操作的数据是“瞬时”的,变量的值无法与数据库中的值保持一致, 而Hibernate操作的数据是可持久的,即持久化对象的数据属性的值是可以跟数据库中的值保持一致的。 has a 和 is a的区别? has a 包含关系 (对象之间有关联关系) is a 继承 (泛化关系) JDBC与框架的区别: Jdbc: 1)、要求sql比较精通 2)、对jdbc操作循环取值要细心,重复工作量很大 3)、对jdbc操作insert,update拼接字符串,要求细心 Hibernate: 不懂sql也没有太大的关系,只要按hibernate框架语法来操作就行了 2、要使用hiberante步骤 1)、配置核心的配置文件 Mybatis-->连接数据库,用户名,密码.....,调试sql Hibernate-->也是一样的(名称 hibernate.cfg.xml) 2)、java实体类与数据库表建立映射关系 可能还会有 一对多, 多对一 多对多 一对一 Mybaits以接口为核心 CityMapper.java -->CityMapper.xml(自己写insert,update,delete,select) Hiberante:以实体类为核心,insert,update,delete,select不会自己做 3)、编写工具类 Mybatis中取 SqlSessionFactory --> session --> 操作 -->(提交事务 可选) Hibernate中取 SessionFactory -->session -->开启事务 -->操作-->提交事务 3、实体类与数据库表映射在hibernate中有2种写法 公司实际开发中,肯定是使用注解 学习中使用xml 4、hibernate日期格式 @Temporal(TemporalType.TIMESTAMP) yyyy-MM-dd hh:mm:ss @Temporal(TemporalType.DATE) yyyy-MM-dd @Temporal(TemporalType.TIME) hh:mm:ss public Date getDtime() { return dtime; } 5、外键 Hibernate: 1:1 @OneToOne 1:n @OneToMany N:1 @ManyToOne N:M @ManyToMany 6、N:1 配置属性 @ManyToOne(fetch=FetchType.LAZY ) Fetch 检索加载的方式 EAGER 立即查询 LAZY 延迟加载(保证 session未关闭) @JoinColumn(name="typeId") 外键列 7、配置核心hibernate.cfg.xml <hibernate-configuration> <session-factory> 1)、声明 你用的是哪种数据库 (断言 方言 hibernate.dialect) 2)、驱动包 hibernate.connection.driver_class 3)、用户名 hibernate.connection.username 4)、密码 hibernate.connection.password 5)、url hibernate.connection.url 6)、显示sql hibernate.show_sql=true/false 7)、是否自动维护表结构 hibernate.hbm2ddl.auto update 1)、none 不需要维护 2)、create-only 如果实体类有对象,数据库没有,就会创建 3)、drop 每次关闭项目就会删除所有的表 4)、create 每次启动都要重新创建表 5)、create-drop每次启动重新创建表,关闭时候删除所有表 6)、update 如果实体类与表结构不一致,就自动更新 7)、取得session的方式 hibernate.current_session_context_class thread 8)、在没有spring框架的情况下,必须把你定义好的带有注解的实体类,交给核心配置文件 <mapping class=”完整类路径” /> 以后还有数据库连接池配置 </session-factory> </hibernate-configuration> 8.sessionFactory.openSession()和sessionFactory.getCurrentSession()区别(面试题) openSession() 打开以后,必须手动的关闭close(); getCurrentSession()打开以后,不需要关闭,交给当前应用自动管理,但是必须在hibernate.cfg.xml中配置 <property name="hibernate.current_session_context_class">thread</property> 9、使用hibernate增,删,改操作 语法 //1、创建Session Session session=HibernateUtil.getCurrentSession(); //2、开启事务 Transaction trans=session.beginTransaction(); try { 操作 //提交 trans.commit(); } catch (Exception e) { trans.rollback(); //回滚 e.printStackTrace(); } 不在事务执行范围内的操作没有效果 hibernate的get()和load()方法的区别: 1. 对于get方法,hibernate会确认一下该id对应的数据是否存在,首先在session缓存中查找,然后在二级缓存中查找,还没有就查询数据库,数据库中没有就返回null。 2. load方法加载实体对象的时候,根据映射文件上类级别的lazy属性的配置(默认为true),分情况讨论: (1)若为true,则首先在Session缓存中查找,看看该id对应的对象是否存在,不存在则使用延迟加载,返回实体的代理类对象(该代理类为实体类的子类,由CGLIB动态生成)。等到具体使用该对象(除获取OID以外)的时候,再查询二级缓存和数据库,若仍没发现符合条件的记录,则会抛出一个ObjectNotFoundException。 (2)若为false,就跟get方法查找顺序一样,只是最终若没发现符合条件的记录,则会抛出一个ObjectNotFoundException。 这里get和load有两个重要区别: 如果未能发现符合条件的记录,get方法返回null,而load方法会抛出一个ObjectNotFoundException。 load方法可返回没有加载实体数据的代理类实例,而get方法永远返回有实体数据的对象。 配置对外关系时: @ManyToOne(fetch=FetchType.LAZY)子查询 @ManyToOne(fetch=FetchType.EAGER)表连接 双向关联关系: private List<Flink> arrFlinks=new ArrayList<Flink>(0); @OneToMany(mappedBy="linkType") public List<Flink> getArrFlinks() { return arrFlinks; } private FlinkType linkType; // 分类(唯一的) @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "typeId") public FlinkType getLinkType() { return linkType; } 面试题权限操作 (下午看) 多用户多权限系统 用户名: Users (userId(PK) , userName) 角色表: Role( roleId(PK),roleName); 功能(菜单)表Func(funcId(PK), funcName, funcUrl, parentId(FK-->funcId), isShow); 角色用户表: role_user(id, userId(FK), foleId(FK)) 角色功能表: role_func(id, roleId(FK), funcId(FK)) 多用户单权限系统 用户名: Users (userId(PK) , userName, roleId(FK)) 角色表: Role( roleId(PK),roleName); 功能(菜单)表 Func(funcId(PK), funcName, funcUrl, parentId(FK-->funcId), isShow); 角色功能表: role_func(id, roleId(FK), funcId(FK)) hibernate的查询方式: hql查询: Session session=sessionFactory.getCurrentSession(); Query query=session.createQuery(hql); 自定义sql查询: Session session=sessionFactory.getCurrentSession(); SQLQuery sqlQuery=session.createSQLQuery(sql); 标准查询: Session session=sessionFactory.getCurrentSession(); Criteria criteria=detachedCriteria.getExecutableCriteria(session); 分页查询: .setFirstResult(firstResult); //起始数据 .setMaxResults(maxResults); //取得数据条数 hibernate在批量操作的时候,如何优化性能? 批量新增,批量修改,批量删除 一次性新增、删除、删除100个元素? 千万不要一次性新增到最后现去 提交,效率很低 每20个更新一次 session.flush() session.clear() for(int i=0;i<100000;i++){ Monkey monkey=new Monkey(....); session.save(monkey); if(i%20==0){ //单批次操作的最大数量 session.flush(); session.clear(); } } 为何这里写20不是其它的数字,可以去hibernate.batch_size=20 什么时候要用update,什么时候要用merge? update():如果你确定在当前session的会话里不存在一个与要进行update操作有相同标识符(主键)的持久化对象,那么调用update()。 修改页面->根据id查询(session缓存中:id=2)-->页面(隐藏域放主键的=2)--> editSave( new 实体类( id=2)) 这时候就会报异常了 (可以使用merge来解决,还可以使用,根据id查询时候,session.evict(obj) ) merge():如果你在任何时候修改了数据都想把数据保存到数据库中,那么就调用merge()。 查询条件:类型 下拉列表 String hql=“from Flink f where f.linkType.id=?” 对象导航查询 Sql: select * from Flnk f inner join FlinkType t on f.typeId=t.id Where t.id=? String hql=” from Flink f left out join fetch f.linkType t Where t.id=?”; 帮你生成 inner join update和saveOrUpdate的区别? update()修改根据主键数据库中的数据 saveOrUpdate()如果该对象未持久化(没有新增过)执行save方法,如果已经持久化了,那就执行update修改操作。 1、hibernate的三种状态之间如何转换 瞬时状态、持久状态、游离状态 当调用 save(),update() 对象变为持久化状态 当实例化对象,就是瞬时状态 当调用delete()游离状态,脱离了session都叫游离状态 3、session.clear(),session.evict(Object) clear() 移出所有在session(一级缓存,只能在内存存在)管理的缓存 evict() 从session缓存中移出某个指定的对象 4、Hibernate工作原理及为什么要用? 原理: 1.读取并解析配置文件 2.读取并解析映射信息,创建SessionFactory 3.打开Sesssion 4.创建事务Transation 5.持久化操作 6.提交事务 7.关闭Session 8.关闭SesstionFactory (二级缓存,需要使用第三方框架) 为什么要用: .对JDBC访问数据库的代码做了封装,大大简化了数据访问层繁琐的重复性代码。 .Hibernate是一个基于JDBC的主流持久化框架,是一个优秀的ORM实现。他很大程度的简化DAO层的编码工作 .hibernate使用Java反射机制。 .hibernate的性能非常好,因为它是个轻量级框架。映射的灵活性很出色。它支持各种关系数据库,从一对一到多对多的各种复杂关系。对缓存支持的 4.Hibernate是如何延迟加载? . Hibernate2延迟加载实现:a)实体对象 b)集合(Collection) . Hibernate3\4\5 提供了属性的延迟加载功能 当Hibernate在查询数据的时候,数据并没有存在与内存中,当程序真正对数据的操作时,对象才存在与内存中,就实现了延迟加载,他节省了服务器的内存开销,从而 提高了服务器的性能。 5.Hibernate中怎样实现类之间的关系?(如:一对多、多对多的关系) 类与类之间的关系主要体现在表与表之间的关系进行操作,它们都市对对象进行操作,我们程序中把所有的表与类都映射在一起,它们通过配置文件中的 many-to-one、one-to-many、many-to-many、 6.说下Hibernate的缓存机制 . 内部缓存存在Hibernate中又叫一级缓存(session),属于应用事物级缓存 . 二级缓存:(SessionFactory) a) 应用及缓存 b) 分布式缓存 条件:数据不会被第三方修改、数据大小在可接受范围、数据更新频率低、同一数据被系统频繁使用、非关键数据 c) 第三方缓存的实现 (EhCache) 5. Hibernate的查询方式 Session.get() 立即加载 Session.load() 延迟加载 Sql、 Hql, Criteria, object comptosition (对象导航) 6. 如何优化Hibernate? .使用双向一对多关联,不使用单向一对多 .灵活使用单向一对多关联 .不用一对一,用多对一取代 .配置对象缓存,不使用集合缓存 .表字段要少,表关联不要怕多,有二级缓存撑腰 7. get和load区别; 1)get如果没有找到会返回null, load如果没有找到会抛出异常。 2)get会先查一级缓存, 再查二级缓存,然后查数据库; load会先查一级缓存,如果没有找到,就创建代理对象, 等需要的时候去查询二级缓存和数据库。 8. N+1问题。 Hibernate中常会用到 解决方法一个是延迟加载, 即lazy=true; Select * from Flink -->FlinkType(延迟的) 当调用对象.getFlinkType() 才去查询 再发送一个select * from FlinkType where id=? 一个是预先抓取 FetchType.EAGER, 即; left join 11 persist()和save()的区别 (了解) persist不保证立即执行,可能要等到flush;persist不更新缓存; 12 cascade,用来指示在主对象和它包含的集合对象的级联操作行为,即对住对象的更新怎么影响到子对象; save-update: 级联保存(load以后如果子对象发生了更新,也会级联更新). 但它不会级联删除 delete: 级联删除, 但不具备级联保存和更新 all-delete-orphan: 在解除父子关系时,自动删除不属于父对象的子对象, 也支持级联删除和级联保存更新. all: 级联删除, 级联更新,但解除父子关系时不会自动删除子对象. delete-orphan:删除所有和当前对象解除关联关系的对象 13 session.commit 和flush区别, commit会先调用flush 然后再执行clear(),然后提交事物; flush() 强制地要求内存对象 与 数据库中的数据保持一致(同步) flush 执行session,但不一定提交事物(因为事物可能被委托给外围的aop代理来做); 14 session清理的顺序: insert -> update -> delete -> 对集合进行delete -〉对集合的insert; 15 检索策略: 立即检索,lazy=false;延迟加载:lazy=true;预先抓取: fetch=“join”; 17、数据库事务 1)、四个特性 原子性、一致性,隔离性, 持久性 2)、事务隔离级别 Serializable: 串行化。隔离级别最高 4 Repeatable Read:可重复读 3(mysql) Read Committed:已提交数据读 2 (oracle) Read Uncommitted:未提交数据读。隔离级别最差 1 隔离级别越高的,数据精准性高,速度慢。 隔离级别越低的,查询速度快,但是数据精准性低. 1. 脏读: 对于两个事物 T1, T2, T1 读取了已经被 T2 更新但还没有被提交的字段. 之后, 若 T2 回滚, T1读取的内容就是临时且无效的. 2. 不可重复读: 对于两个事物 T1, T2, T1 读取了一个字段, 然后 T2 更新了该字段. 之后, T1再次读取同一个字段, 值就不同了. 3. 幻读: 对于两个事物 T1, T2, T1 从一个表中读取了一个字段, 然后 T2 在该表中插入了一些新的行. 之后, 如果 T1 再次读取同一个表, 就会多出几行. Read uncommitted 读未提交 公司发工资了,领导把5000元打到singo的账号上,但是该事务并未提交,而singo正好去查看账户,发现工资已经到账,是5000元整,非常高兴。可是不幸的是,领导发现发给singo的工资金额不对,是2000元,于是迅速回滚了事务,修改金额后,将事务提交,最后singo实际的工资只有2000元,singo空欢喜一场。 出现上述情况,即我们所说的脏读,两个并发的事务,“事务A:领导给singo发工资”、“事务B:singo查询工资账户”,事务B读取了事务A尚未提交的数据。 当隔离级别设置为Read uncommitted时,就可能出现脏读,如何避免脏读,请看下一个隔离级别。 Read committed 读提交 singo拿着工资卡去消费,系统读取到卡里确实有2000元,而此时她的老婆也正好在网上转账,把singo工资卡的2000元转到另一账户,并在singo之前提交了事务,当singo扣款时,系统检查到singo的工资卡已经没有钱,扣款失败,singo十分纳闷,明明卡里有钱,为何...... 出现上述情况,即我们所说的不可重复读,两个并发的事务,“事务A:singo消费”、“事务B:singo的老婆网上转账”,事务A事先读取了数据,事务B紧接了更新了数据,并提交了事务,而事务A再次读取该数据时,数据已经发生了改变。 当隔离级别设置为Read committed时,避免了脏读,但是可能会造成不可重复读。 大多数数据库的默认级别就是Read committed,比如Sql Server , Oracle。如何解决不可重复读这一问题,请看下一个隔离级别。 Repeatable read 重复读 当隔离级别设置为Repeatable read时,可以避免不可重复读。当singo拿着工资卡去消费时,一旦系统开始读取工资卡信息(即事务开始),singo的老婆就不可能对该记录进行修改,也就是singo的老婆不能在此时转账。 虽然Repeatable read避免了不可重复读,但还有可能出现幻读。 singo的老婆工作在银行部门,她时常通过银行内部系统查看singo的信用卡消费记录。有一天,她正在查询到singo当月信用卡的总消费金额(select sum(amount) from transaction where month = 本月)为80元,而singo此时正好在外面胡吃海塞后在收银台买单,消费1000元,即新增了一条1000元的消费记录(insert transaction ... ),并提交了事务,随后singo的老婆将singo当月信用卡消费的明细打印到A4纸上,却发现消费总额为1080元,singo的老婆很诧异,以为出现了幻觉,幻读就这样产生了。 3)锁机制 Mysql,sqlserver悲观锁: 当某个用户在操作的时候,其它用户不允许进行更新数据 锁整个表,锁行 Select * from 表 for update;(oracle乐观锁) Select * from 表 where id=5 for update; 直接上一个用户 提交或者回滚记录才行 乐观锁: 大家都可进行操作,但是会以某一个列(timestamp 系统自动维护) 编号 值 version 1 test 2017-1-1 20:10:2.101 Update 表 set 值=‘a’ where 编号=1 and veresion=’ 2017-1-1 20:10:2.101’ Commit; 16、什么是Hibernate的并发机制?怎么去处理并发问题? Hibernate并发机制: a、Hibernate的Session对象是非线程安全的,对于单个请求,单个会话,单个的工作单元(即单个事务,单个线程),它通常只使用一次, 然后就丢弃。 如果一个Session 实例允许共享的话,那些支持并发运行的,例如Http request,session beans将会导致出现资源争用。 如果在Http Session中有hibernate的Session的话,就可能会出现同步访问Http Session。只要用户足够快的点击浏览器的“刷新”, 就会导致两个并发运行的线程使用同一个Session。 b、多个事务并发访问同一块资源,可能会引发第一类丢失更新,脏读,幻读,不可重复读,第二类丢失更新一系列的问题。 解决方案:设置事务隔离级别。 Serializable:串行化。隔离级别最高 Repeatable Read:可重复读 Read Committed:已提交数据读 Read Uncommitted:未提交数据读。隔离级别最差 设置锁:乐观锁和悲观锁。 乐观锁:使用版本号或时间戳来检测更新丢失,在的映射中设置 optimistic-lock=”all”可以在没有版本或者时间戳属性映射的情况下实现 版本检查,此时Hibernate将比较一行记录的每个字段的状态 行级悲观锁:Hibernate总是使用数据库的锁定机制,从不在内存中锁定对象!只要为JDBC连接指定一下隔 离级别,然后让数据库去搞定一切就够了
hibernate整理
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。