Hibernate

hibernate简介
Hibernatehibernate简介
hibernate快速入门
session查询api
实体类的三种状态
关联关系多对一
一对多
多对多

hibernate常用查询api
hibernate缓存一级缓存
二级缓存
查询缓存

OpenSessionInView1、创建一个工具类HIbernateUtils
2、创建一个过滤器OpenSessionInViewFilter
3、在hibernate.cfg.xml中配置属性

jpa基本用法
多对一
一对多
多对多

hibernate-validator

Hibernate
概念:
作用:
特点:

hibernate快速入门
导包

Some_Text

配置文件

<!DOCTYPE hibernate-configuration PUBLIC
    "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
    "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
    <!-- 四大参数 -->
    <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
    <property name="hibernate.connection.url">jdbc:mysql://localhost:3306/hibernate</property>
    <property name="hibernate.connection.username">root</property>
    <property name="hibernate.connection.password"></property>
    <!-- SQL 方言 ,注意使用MySQLInnoDBDialect,才可以使用Innodb引擎-->
    <property name="dialect">org.hibernate.dialect.MySQL5InnoDBDialect</property>
    <!-- 打印出sql -->
    <property name="show_sql">true</property>       
    <!-- 格式化sql -->
    <property name="format_sql">true</property>
    <!-- 有表更新表,没有表自动创建表 -->
    <property name="hbm2ddl.auto">update</property>     
    <!-- 加载映射文件 -->
    <mapping resource="User.hbm.xml"/>
</session-factory>
</hibernate-configuration>

注意:主配置文件名,一般默认是hibernate.cfg.xml,并且在src根目录中 上面的配置文件,可以参考etc文件夹下的配置文件



创建类

public class User {
private int uid;
private String username;
private String password;
//get/set方法 必须要有
}

映射文件

<!DOCTYPE hibernate-mapping PUBLIC
    "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
    "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">  
<hibernate-mapping>
<class name="com.hibernate.entity.User" table="user">
    <id name="uid" column="uid">
        <!-- 使用数据库默认的生成主键的方案 -->
        <generator class="native"/>
    </id>
    <property name="username" column="username"/>
    <property name="password" column="password"/>
</class>
</hibernate-mapping>


 Configuration configure = new Configuration().configure("hibernate.cfg.xml");
SessionFactory factory = configure.buildSessionFactory();
Session session = factory.openSession();// 获取连接
// 开启事务
Transaction tx = session.beginTransaction();
User user = new User("黄蓉", "123");
session.save(user);
tx.commit();// 提交事务
session.close();// 关闭连接

session查询api
save、delete、update
get 不支持延迟查询
load 延迟查询:如果使用了对象中非id的属性时才会发送sql语句
saveOrUpdate
瞬时态执行save(),游离态执行update()
merge
两个相同id的对象合并

实体类的三种状态
瞬时态:无id,与session无关联,与数据库无关联
持久态:有id,与session有关联,与数据库关联 持久态对象修改数据,会自动修改数据库的数据
游离态(离线):有id,与session无关联,与数据库有关


具体请看hibernate的三种状态

关联关系

多对一
多个Customer对应一个User


一对多
一个User对应多个Customer



注意:一对多,多对一其实是从不同角度看问题,本质是一样的,任意写一个就是单向的一对多(多对一),两个都写,就是双向的一对多(多对一)。单向意味着,只能从一方找到另一方,双方可以相互找到对方。

多对多


hibernate常用查询api
详情请点击这里

hibernate缓存

一级缓存
第一次查找,去缓存中找,没有数据,从数据库获取,然后存入一级缓存,并且存入快照区;session没有关闭,并且执行第二次查找,先从一级缓存中获取。如果对象修改了数据,一级缓存中的数据也修改了,那么会将一级缓存和快照区的数据进行比对,如果不相同,就将数据存入数据库。
第一级别的缓存是 Session 级别的缓存,它是属于事务范围的缓存(session的一级缓存)
更多详情请查看

二级缓存
二级缓存属于SessionFactory级别的缓存,缓存的对象根据提供的实现类不同,放置的位置也不同,主要就是内存和硬盘中。二级缓存是缓存对象的Id,所以只有通过id查询的,二级缓存才能生效。
第二级别的缓存是 SessionFactory 级别的缓存,它是属于进程范围的缓存
二级缓存的实现有很多,我们使用ehcache来实现二级缓存
1、导包

    <dependency>
        <groupId>org.hibernate</groupId>
        <artifactId>hibernate-ehcache</artifactId>
        <version>5.0.12.Final</version>
    </dependency>

    <dependency>
        <groupId>net.sf.ehcache</groupId>
        <artifactId>ehcache-core</artifactId>
        <version>2.6.11</version>
    </dependency>

2、在spring-hibernate.xml中配置

    <!-- 开启二级缓存:根据id来查询 -->
  <prop key="hibernate.cache.use_second_level_cache">true</prop>
  <!-- 开启查询缓存:根据非id来查询,需要在query中设置setCacheable(true) -->
  <prop key="hibernate.cache.use_query_cache">true</prop>
  <!-- 高速缓存提供程序 -->
  <prop       key="hibernate.cache.region.factory_class">org.hibernate.cache.ehcache.SingletonEhCacheRegionFactory</prop>

3、在resources根目录中添加ehcache.xml文件

  <ehcache>  
  <!--
  指定二级缓存存放在磁盘上的位置,可以使用磁盘目录
    也可以使用Java System Property目录
    user.home是用户目录
    user.dir是用户当前工作目录
    java.io.tmpdir是默认临时文件路径
  -->
<diskStore path="java.io.tmpdir/cache"/>

<!-- ehcache将缓存分为多个不同的区域,不同的区域可以设置不同的缓存策略 -->

<!--缓存策略:
    name:Cache的唯一标识。
    maxElementsInMemory:内存中最大缓存对象数。
    eternal:Element是否永久有效,一旦设置true,timeout将不起作用。
    timeToIdleSeconds:设置Element在失效前的允许闲置时间。仅当element不是永久有效时使用,可选属性,默认值是0,也就是可闲置时间无穷大。
    timeToLiveSeconds:设置Element在失效前允许存活时间。最大时间介于创建时间和失效时间之间。仅当element不是永久有效时使用,默认是0.,也就是element存活时间无穷大。
    overflowToDisk:配置此属性,当内存中Element数量达到maxElementsInMemory时,Ehcache将会Element写到磁盘中。
    maxElementsOnDisk:磁盘中最大缓存对象数,若是0表示无穷大。
    memoryStoreEvictionPolicy:当达到maxElementsInMemory限制时,Ehcache将会根据指定的策略
    去清理缓存中的内容。默认策略是LRU(最近最少使用),你也可以设置为FIFO(先进先出)或是LFU(较少使用) -->
  
<defaultCache
        maxElementsInMemory="10000"
        eternal="false"
        timeToIdleSeconds="120"
        timeToLiveSeconds="120"
        overflowToDisk="true"
/>

<cache name="simple"
       maxElementsInMemory="1000"
       eternal="true"
       timeToIdleSeconds="0"
       timeToLiveSeconds="0"
       overflowToDisk="false"
/>

<!--可以给每个实体类指定一个配置文件,通过name属性指定,要使用类的全名-->
<!--<cache name="com.study.entity.User"-->
<!--maxElementsInMemory="10000"-->
<!--eternal="false"-->
<!--timeToIdleSeconds="300"-->
<!--timeToLiveSeconds="600"-->
<!--overflowToDisk="true"-->
<!--/>-->

</ehcache>
4、在需要使用二级缓存的类上添加注解

//region:标示要使用的区域,不同的区域使用的缓存策略不一样,见上面第3点说明
//usage:指定使用的并非策略
@org.hibernate.annotations.Cache(region ="simple",usage =     CacheConcurrencyStrategy.READ_ONLY)

ehcache的四种缓存并发策略如下:
read-write(读写型)
提供Read Committed事务隔离级别
在非集群的环境中适用
适用经常被读,很少修改的数据
可以防止脏读
更新缓存的时候会锁定缓存中的数据

nonstrict-read-write(非严格读写型)
适用极少被修改,偶尔允许脏读的数据(两个事务同时修改数据的情况很少见)
不保证缓存和数据库中数据的一致性
为缓存数据设置很短的过期时间,从而尽量避免脏读
不锁定缓存中的数据

read-only(只读型)
适用从来不会被修改的数据(如参考数据)
在此模式下,如果对数据进行更新操作,会有异常
事务隔离级别低,并发性能高
在集群环境中也能完美运作

5、测试

   AppInfo appInfo = appInfoService.findOneById(1);
    System.out.println(appInfo);

    AppInfo appInfo1 = appInfoService.findOneById(1);
    System.out.println(appInfo1);

注意:
1、list()只查询一级缓存,而iterator()会从二级缓存中查
2、list()方法返回的对象都是实体对象,而iterator()返回的是代理对象

查询缓存
Query Cache只是在特定的条件下才会发挥作用,而且要求相当严格:
完全相同的HQL重复执行。(注意,只有hql)
重复执行期间,Query Cache对应的数据表不能有数据变动(比如添、删、改操作)

绝大多数的查询并不能从查询缓存中受益,所以Hibernate默认是不进行查询缓存的。查询缓存适用于以下场合:
在应用程序运行时经常使用的查询语句(参数相同)
很少对与查询语句检索到的数据进行插入、删除或更新操作

  Query query = session.createQuery(hql);     
  query.setCacheable(true); //启用查询缓存  
  query.setCacheRegion(“queryCacheRegion”); //设置查询缓存区域(数据过期策略)  
  query.list();  
  OpenSessionInView

1、创建一个工具类HIbernateUtils

   private static SessionFactory factory;
static {
     factory = new Configuration().configure().buildSessionFactory();
}

public static Session getSession() {
    return factory.getCurrentSession();//将session与线程绑定
}

2、创建一个过滤器OpenSessionInViewFilter

   Session session = HibernateUtils.getSession();
    Transaction tx = null;
    try {
        tx = session.beginTransaction();
        chain.doFilter(request, response);
        tx.commit();
    } catch (Exception e) {
        e.printStackTrace();
        if (tx != null) {
            tx.rollback();
        }
    } finally {
        if (session != null) {
            session.close();
        }
    }

3、在hibernate.cfg.xml中配置属性

  <property name="hibernate.current_session_context_class">thread</property> 

request(请求)->open session并开始transaction->controller->View(Jsp)->结束transaction并 close session.
有可能在chain.doFilter()被阻塞,因为有可能输出jsp的页面内容大,response.write的时间长,另一方面可能是网速慢,服务器与用户间传输时间久。当大量这样的情况出现时,就有连接池连接不足,造成页面假死现象。

jpa
什么是jpa
java persistence api,java在持久层的一套接口,与jdbc接口类似,提供一套规范,有其他数据库厂商去实现
hibernate实现了jpa接口


基本用法



@Entity //表示该类为持久化类
@Table(name="user") //对应数据库的表名
public class User {
@Id //主键
@GeneratedValue(strategy=GenerationType.IDENTITY)//主键生成策略 IDENTITY与native类似
private Integer uid;
@Column(name="user_name") //设置属性名与字段名的映射关系
private String username;
private String password; //如果属性名与字段名一致,可以不写注解

}
注意:如果下面的注解不理解,请看上面xml配置映射关系的图

多对一

@ManyToOne(cascade=CascadeType.ALL) //casacde为级联
@JoinColumn(name="uid") //外键
private User user;

一对多

在一方设置@OneToMany和@JoinColumn

@OneToMany(cascade=CascadeType.ALL) //casacde为级联
@JoinColumn(name="uid") //外键
private Set<Customer> custSet = new HashSet<>();

多对多
在任意一方设置@ManyToMany和@JoinTable

@ManyToMany(cascade=CascadeType.ALL,fetch=FetchType.LAZY)
@JoinTable(//生成第三张表
        name="role_user",
        joinColumns={@JoinColumn(name="uid")},//本表中的主键
        inverseJoinColumns={@JoinColumn(name="rid")}//另一张表的主键
)
private Set<Role> roleSet = new HashSet<>();

双向的只要在另一个类中写同样的注解即可

@ManyToMany(cascade=CascadeType.ALL,fetch=FetchType.LAZY)
@JoinTable(
        name="role_user",
        joinColumns={@JoinColumn(name="rid")},//本表中的主键
        inverseJoinColumns={@JoinColumn(name="uid")}//另一张表的主键
)
private Set<User> userSet = new HashSet<>();

hibernate-validator
springmvc整合validator
1、导包,注意要4.xx的版本

 <dependency>
        <groupId>org.hibernate</groupId>
        <artifactId>hibernate-validator</artifactId>
        <version>4.3.1.Final</version>
    </dependency>

2、在springmvc中配置

  <bean id="validator" class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean">
    <property name="providerClass" value="org.hibernate.validator.HibernateValidator" />
</bean>
<mvc:annotation-driven validator="validator">

4、在类上添加注解

   //Bean Validation 中内置的 constraint
  @Null   //被注释的元素必须为 null    
@NotNull    //被注释的元素必须不为 null    
@AssertTrue     //被注释的元素必须为 true    
@AssertFalse    //被注释的元素必须为 false    
@Min(value)     //被注释的元素必须是一个数字,其值必须大于等于指定的最小值    
@Max(value)     //被注释的元素必须是一个数字,其值必须小于等于指定的最大值    
@DecimalMin(value)  //被注释的元素必须是一个数字,其值必须大于等于指定的最小值    
@DecimalMax(value)  //被注释的元素必须是一个数字,其值必须小于等于指定的最大值    
@Size(max=, min=)   //被注释的元素的大小必须在指定的范围内    
@Digits (integer, fraction)     //被注释的元素必须是一个数字,其值必须在可接受的范围内    
@Past   //被注释的元素必须是一个过去的日期    
@Future     //被注释的元素必须是一个将来的日期    
@Pattern(regex=,flag=)  //被注释的元素必须符合指定的正则表达式    

//Hibernate Validator 附加的 constraint    
@NotBlank(message =)   //验证字符串非null,且长度必须大于0    
@Email  //被注释的元素必须是电子邮箱地址    
@Length(min=,max=) @Range用法一致 //被注释的字符串的大小必须在指定的范围内    
@NotEmpty   //被注释的字符串的必须非空    
@Range(min=,max=,message=)  //被注释的元素必须在合适的范围内

5、springmvc

    @RequestMapping("doAdd")
    public String doAdd(Model model,
           @RequestParam(name = "img", required = false) MultipartFile multipartFile,
           @Valid AppInfo appInfo, BindingResult bindingResult 
          //@Valid必须与BindingResult在一起,bindingResult放在末尾
){}

导包

 <dependencies>
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.12</version>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>antlr</groupId>
        <artifactId>antlr</artifactId>
        <version>2.7.7</version>
    </dependency>
    <dependency>
        <groupId>com.fasterxml</groupId>
        <artifactId>classmate</artifactId>
        <version>1.3.4</version>
    </dependency>
    <dependency>
        <groupId>dom4j</groupId>
        <artifactId>dom4j</artifactId>
        <version>1.6.1</version>
    </dependency>
    <dependency>
        <groupId>org.apache.geronimo.specs</groupId>
        <artifactId>geronimo-annotation_1.0_spec</artifactId>
        <version>1.0</version>
    </dependency>
    <dependency>
        <groupId>org.hibernate.common</groupId>
        <artifactId>hibernate-commons-annotations</artifactId>
        <version>5.0.1.Final</version>
    </dependency>
    <dependency>
        <groupId>org.hibernate</groupId>
        <artifactId>hibernate-core</artifactId>
        <version>5.0.12.Final</version>
    </dependency>
    <dependency>
        <groupId>org.hibernate.javax.persistence</groupId>
        <artifactId>hibernate-jpa-2.1-api</artifactId>
        <version>1.0.0.Final</version>
    </dependency>
    <dependency>
        <groupId>org.jboss</groupId>
        <artifactId>jandex</artifactId>
        <version>2.0.0.Final</version>
    </dependency>
    <dependency>
        <groupId>jboss</groupId>
        <artifactId>javassist</artifactId>
        <version>3.7.ga</version>
    </dependency>
    <dependency>
        <groupId>org.jboss.logging</groupId>
        <artifactId>jboss-logging</artifactId>
        <version>3.3.1.Final</version>
    </dependency>
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>5.1.30</version>
    </dependency>
</dependencies>
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,240评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,328评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,182评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,121评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,135评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,093评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,013评论 3 417
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,854评论 0 273
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,295评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,513评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,678评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,398评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,989评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,636评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,801评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,657评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,558评论 2 352

推荐阅读更多精彩内容