Hibernate 映射文件的配置 核心文件的配置 一对一 一对多 多对多 hibernate检索策略 Hibernate中session的关闭问题总结

以留言系统为实例

1 .配置映射文件:首先得引入约束dtd

<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">

然后<hibernate-mapping></hibernate-mapping>映射标签

<class></class>标签  表示你要创建表的javaBean功能类  

<id></id>配置表的主键id<generator class="native"><generator> native :hibernate自动是哪种数据库 然后根据数据库类型进行主键的增长   来保证数据的唯一性

<proterty></proterty>来配置表的字段

<set></set> 一对多是有的标签  来表示那个多的集合

<one-to-one>  一对一

<one-to-many>一对多

<many-to-many>多对多

2.核心配置文件

同样的也要引入约束dtd

<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">

然后<hibernate-configuration></hibernate-configuration>加载核心文件标签

<session-factory></session-factory>session工厂标签

然后3个模块

1  连接数据库  进行配置

peroperty标签

  具体的

<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="hibernate.connection.url">jdbc:mysql://localhost:3306/liuyanban</property>
<property name="hibernate.connection.username">root</property>
<property name="hibernate.connection.password"></property>

2.hibernate信息模块

  输出日志

输出sql语句:<property name="hibernate.show_sql">true</property>

格式化sql语句 <property name="hibernate.format_sql">true</property>

配置建表信息<property name="hibernate.hbm2ddl.auto">update</property>配置了这个有表就更新没有就创建

配置session线程绑定<property name="hibernate.current_session_context_class">thread</property>

配置数据库方言 <property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>

3。隐射文件配置

<mapping resource属性/>

2.一对一配置

一对一关联分为主键关联和外键关联

    主键关联:不需要添加额外的字段,两个表的主键值一样

    外键关联:附表有一个额外的字段和主表相关联  或两个表都有额外字段和其对应的表相关联

<one-to-one
        name="propertyName"                                (1)
        class="ClassName"                                        (2)
        cascade="cascade_style"                                 (3)
        constrained="true|false"                               (4)
        fetch="join|select"                               (5)
        property-ref="propertyNameFromAssociatedClass"          (6)
        access="field|property|ClassName"                        (7)
        formula="any SQL expression"                            (8)
        lazy="proxy|no-proxy|false"                         (9)
        entity-name="EntityName"                         (10)
        node="element-name|@attribute-name|element/@attribute|."
 
        embed-xml="true|false"
        foreign-key="foreign_key_name"
/>

cascade:用于级联操作 crud操作   官方解释:表明操作是否从父对象级联到被关联的对象

constrained(约束):表明该类对应的表对应的数据库表,和被关联的对象所对应的数据库表之间,通过一个外键引用对主键进行约束。 这个选项影响save()和delete()在级联执行时的先后顺序以及 决定该关联能否被委托(也在schema export tool中被使用).

fetch (可选 - 默认设置为select): 在外连接抓取或者序列选择抓取选择其一.

property-ref:指定关联类的属性名  这个将会和本类的主键相对应,如果没有指定会使用对方关联类的主键

lazy:对延迟查询的高效进行指定  如果为extra为及其懒惰 你要什么就给什么不给多也不给少 ,指定这个查询很高效

 access (可选 - 默认是 property): Hibernate用来访问属性的策略。

 formula (可选):绝大多数一对一的关联都指向其实体的主键。在一些少见的情况中, 你可能会指向其他的一个或多个字段,或者是一个表达式,这些情况下,你可以用一个SQL公式来表示。 (可以在org.hibernate.test.onetooneformula找到例子)

  lazy (可选 - 默认为 proxy): 默认情况下,单点关联是经过代理的。lazy="no-proxy"指定此属性应该在实例变量第一次被访问时应该延迟抓取(fetche lazily)(需要运行时字节码的增强)。 lazy="false"指定此关联总是被预先抓取。注意,如果constrained="false", 不可能使用代理,Hibernate会采取预先抓取!

entity-name (可选): 被关联的类的实体名

 1.主键关联的:

    例: User和Account,一个用户对应一个账户。

  在附表的one-to-one中要写constrained="true" 表示受到约束通过一个外键引用对主键进行约束

 User类与配置文件

    private Integer id;

   private String username;

   private String password;

   private Account account;

    one-to-one中的class属性可以不写,默认Hibernate会使用反正自己去寻找。

<one-to-one name="account" class="piaohan.domain.Account"cascade="all" />

 Account类与配置

   private Integer id;

   private String accountNum;

   private Integer money;

   private User user;

<id name="id" column="id"><generator class="foreign"><!--本类中想要关联的属性--><param name="property">user</param></generator></id>

<one-to-one name="user" class="" constrained="true"></one-to-one>

表示不添加额外的字段 使两个表的主键值一样    这时两个表的主键的值一样

2.单方外键关联 :

例:一个留言对应一个回复

在留言当中显示其对应的回复

Message

 

public class Message {

private Integer mid;
private String title;
private String mtext;
private String mtime;
private User user;
private Revert revert;

<many-to-one name="revert" class="" unique="true"></many-to-one>

这里就要问了  为什么是many-to-one呢    这种关联Message 实际上这里是用many-to-one然后用unique来进行限制  限制成一对一的关系

所以一对一的单方外键关联是一个特殊的many-to-one的例子

public class Revert {

private Integer rid;
private String rtext;
private String rtime;
private Message message;

<one-to-one name="message" class="" property-ref="rever"></one-to-one>

配置property-ref值为关联类的属性  其对应本类中的主键值  如果没有配置呢?会使用对方关联类的主键

2.双方外键关联

都是用<many-to-one></many-to-one>所以一对一的双方外键关联是一个特殊的many-to-one的例子

关联类的属性是一样的     都要进行unique的配置 

  <many-to-one name="account" cascade="all" unique="true"

         column="accountid" />

    Account配置(类不变)

<many-to-one name="user" unique="true" column="userid"

         cascade="all" />

 

一对多的配置

 

public User() {
super();
// TODO Auto-generated constructor stub
}
private Integer uid;
private String username;
private String password;
private String email;
private Set<Message> messageset=new HashSet<Message>();

一个用户对应多个留言

<set  name="messageset(对应本类中的set集合名)">

     //使用户有多个留言的关系  外键

    <key column="uid"></key>

   <one-to-many name="message" class=""></one-to-many>

</set>

 

public class Message {

private Integer mid;
private String title;
private String mtext;
private String mtime;
private User user;
private Revert revert;

<many-to-one name="user" class="" column="uid(要与主表当中配置的外键保持一致)"></many-to-one>

5.多对多的配置

通过第三张表来表示两个表之间的关系

private Integer rid;
private String name;
//通过建立set集合来表示一个角色可有对应多个用户
private Set<User> userset=new HashSet<User>();

<set name="userset(类中set集合)" table="userrole(第三张表的名称)" cascade="all">

   //user和role创建联系

   //外键的名称

   <key column="rid"></key>

   <many-to-many name="user" class="" column="uid"></many-to-many>

</set>

public class User {

private Integer uid;
private String username;
private String password;
//通过建立set集合来实现 一个用户有多个角色对应
private Set<Role> roleset=new HashSet<Role>();

<set name="roleset" table="(要保持一致)">

//反映本类中的主键在第三张表中的外键

  <key column="uid"></key>

<many-to-many name="role" class="" column="rid(与另一张中的配置保持一致)"> </many-to-many>

</set>

Hibernate检索策略

分为立即查询和延迟查询

特点:立即查询执行到这一句时立即发送查询数据库语句进行查询数据库  通过session.get()方法

      延迟查询:不会立即查询当到对像中取值才会发送语句  ,查询数据库 通过session.load()方法

   延迟又分为类级别延迟和关联级别延迟

   类级别:通过sesion.load()来实现

    关联级别实现:通过配置映射文件lazy(默认为true)  fetch(默认为select)

     lazy:true (延迟),false(不延迟),extra(极其懒惰(延迟上升一个等级效率高))

  批量抓取问题

   查询的数据量比较大产生的问题是  会重复查询相同的语句

   通过batch-size值越大性能越高

一级缓存和二级缓存的问题

他们的特点:一级缓存:1.默认是打开的

                                2.存储的数据必须是持久态

                               3.适用范围是session的开启到关闭

                 二级缓存:1.需要手动打开

                                2.范围是sessionfactory范围

  User user=session.get(User.class,1(id值))执行过程

  user.setName("ji");

   首先会看一级缓存中是否有use内容,如果找不到会查询数据库,得到user对象存入一级缓存和快照区中

 执行到第二句时  只改变一级缓存中的值而不该快照区中

  执行commit时会做一件事情  比较

  如果快照区中的值与一级缓存值不相同那么就更新

  如果相同那么就不更新。   

Hibernate中的session关闭问题

session相当于jdbc中的connection 所以需要进行关闭

但是由于session要与本地线程进行捆绑来实现其单线程对象的特性

创建工具类

package com.jdztc.util;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;

/**
 * 
 * @author 付鹏鹏
 *产生SessionFactory核心工具类
 */
public class HibernateUtil {

    //采用静态代码块的方式   因为静态代码块是类加载的时候运行,且只运行一次
    private static Configuration configuration=null;
    private static SessionFactory sessionFactory=null;
    private static Session session=null;
    static{
        //加载核心配置文件, 创建对象将文件放入对象当中
       configuration=new Configuration();
       configuration.configure();
       
       //通过有文件的对象的引用来创建SessionFactory ,根据核心配置文件中的数据库信息  和映射文件来进行表格的创建
      sessionFactory= configuration.buildSessionFactory();
      //通过getCurrentSession()的方法来得到保证是单线程对象的Session
      session=sessionFactory.getCurrentSession();
    }
    public static Session gerThreadSession(){
        return session;
    }
    public static SessionFactory getSessionFactory(){
        return sessionFactory;
    }
    public static void main(String[] args){
        
    }
}

在查询数据库中 HibernateUtil.getSession()时不能关闭因为执行到commit()会自动关闭  如果你还关闭将会报session已经关闭

还有一点:commit也不能随便要到最后关闭   举个例子:

 public static void addRevert(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String mid=req.getParameter("uid");
        System.out.println("uid +"+mid);
        String content=req.getParameter("content");
        System.out.println("content:"+content);
        if(content.indexOf("
")!=-1){
            content.replace("
", "<br>");
        }
        Message message=MessageDao.getMessage(mid);
        if(message!=null){
            //将message与revert相关联     设置revert中的message与message中的revert
            Revert revert=message.getRevert();
            System.out.println("revert:"+revert);
            if(revert==null){
                revert=new Revert();
            }
            Date date=new Date();
            DateFormat time1=new SimpleDateFormat("yyyy.MM.dd HH:mm:ss ");
            String time=time1.format(date);
            //  设置message中的revert
            System.out.println("revert2:"+revert);
            message.setRevert(revert);
            RevertDao.add(revert, content, time, message);
            //更新留言
            MessageDao.updateMessage(message);
            //req.getRequestDispatcher("index.jsp").forward(req, resp);
        }else{
            System.out.println("message == null");
        }
        
    }
 Message message=MessageDao.getMessage(mid);通过内容来查询message 
getMessage(mid)方法中commit和rollback()都不能有全部删除 因为session已经和本地线程绑定 如果关闭
Message message=MessageDao.getMessage(mid);下面的代码将不能得到session  所以必须到
在 MessageDao.updateMessage(message);方法中commit()和rollback()
在addRevert方法的最后进行关闭  注意之前不能有commit()和rollback()
原文地址:https://www.cnblogs.com/fupengpeng/p/6791673.html