笔记之_java整理hibernate
页面调试数据:<%@taglib uri="/struts-tags" prefix="s" %>
<s:debug></s:debug>
Js清除缓存
使用hibernate延迟加载时,并且数据库有关联关系,转换成json对象时不能直接转换,要用new JSONObject(),然后put()方法存值
国外框架项目地址: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)这个表示一个实体类,Table表示对应数据库中的表名。
@Entity
@Table(name="t_emp")
(2)这个表示主键自动增长
mysql数据库
@Id
@GeneratedValue
oracle数据库
@Id
@SequenceGenerator(name = "FLINKSEQ", sequenceName = "flink_seq", initialValue = 1, allocationSize = 1)
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "FLINKSEQ")
(3)这个表示关联对象以及关联的字段名字
@ManyToOne
@JoinColumn(name="dept_id")
@OneToMany(mappedBy="flinkType") //主表实体类映射关系
(4)和数据库中字段不一样的,要通过这个属性写清楚。
@Column(name="emai")
(5)表示时间字段
@Temporal(TemporalType.TIMESTAMP)
和@Temporal(TemporalType.DATE)
Dao.impl包中:
@Repository实体类数据访问层实现,放在类上
Service.impl包中:
@Service实体类业务逻辑层实现,放在类上
@Resource(name="flinkTypeDaoImpl")属性注入值放在setter方法上
Controller包中:
@Controller 是servlet标志,放在类上
@Scope(value="prototype") 每次实例化,放在类上
@Resource(name="flinkTypeServiceImpl")赋值,属性的setter方法上
测试类:放测试类上
@ContextConfiguration(locations="classpath:applicationContext.xml")
@RunWith(value=SpringJUnit4ClassRunner.class)
struts传参:
getter方法
ActionContext.getContext().getContextMap().put("arrLinks", arrLinks);
struts页面取值:
#r.id
id
@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连接指定一下隔 离级别,然后让数据库去搞定一切就够了
以上是 笔记之_java整理hibernate 的全部内容, 来源链接: utcz.com/z/390018.html