Java学习大全 之 Hibernate3.3

 

1、hibernate是开源的轻量级的对象关系映射框架,用了ORM思想,对jdbc进行了封装。
2、ORM(Object-Relation Mapping)对象关联映射。
3、hibernate配置文件默认名字为hibernate.cfg.xml或者hibernate.properties,当调用Configuration config = new Configuration().configure()则加载默认名字的配置文件。如果写死加载某个配置则Configuration config = new Configuration().configure(new File(strPath))或者Configuration config = new Configuration().configure(strPath)
4、hibernate配置文件示例
 <?xml version="1.0" encoding="utf-8"?>
 <!DOCTYPE hibernate-configuration PUBLIC" //Hibernate/Hibernate Configuration DTD/EN" "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
 <hibernate-configuration>
  <session-factory>
   <!--数据库驱动类-->
   <property name="connection.driver_class">com.mysql.jdbc.Driver</property>
   <!--数据库连接url-->
   <property name="connection.url">jdbc:mysql://localhost:3306/mytest</property>
   <!--数据库连接用户名-->
   <property name="connection.username">root</property>
   <!--数据库连接密码-->
   <property name="connection.password">root</property>
   <!--sql方言-->
   <property name="dialect">org.hibernate.dialect.MySQLDialect</property>
   <!--显示sql语句-->
   <property name="show_sql">true</property>
   <!--根据映射文件在数据库创建表-->
   <property name="hbm2ddl.auto">create</property>
   
   <!--c3p0连接池-->
   <property name="c3p0.min_size">5</property>
   <property name="c3p0.max_size">20</property>
   <property name="c3p0.timeout">1800</property>
   <!-- 最大的PreparedStatement的数量 -->
   <property name="c3p0.max_statements">50</property>
   <!-- 每次都验证连接是否可用 -->
   <property name="c3p0.validate">true</property>
   <!-- 当连接池里面的连接用完的时候,c3p0获取的新的连接数 -->
   <property name="c3p0.acquire_increment">2</property>
   <!--每隔多少秒就检查连接池里面的空闲连接-->
   <property name="c3p0.idle_test_period">120</property>
   
   
   <!--表和类的映射文件-->
   <mapping resource="org/model/User.hbm.xml"></mapping>
  </session-factory>
 </hibernate-configuration>
5、SessionFactory和Session
 Configuration config = new Configuration().configure();
 SessionFactory sessionFactory = config.buildSessionFactory();
 Session session = sessionFactory.openSession();
6、主键关系的双向一对一
 创建表,虽然可以用hibernate配置表的关系,但是为了数据严谨还是在表结构上也加上外键约束
 create table man(
  id int primary key auto_increment,
  name varchar(20)
 );
 create table women(
  id int primary key,
  name varchar(20),
  foreign key(id) references man(id)
 );
 Man.java类属性:private Integer id;private String name;private Women women;
 Women.java类属性:private Integer id;private Man man;private String name;
 Man.hbm.xml映射文件:outer-join代表外联查询默认是true,cascade表示级联操作默认为none,其值有all、none、save-update、delete
 <hibernate-mapping>
     <class name="com.bean.Man" table="man" catalog="mytest">
         <id name="id" type="java.lang.Integer">
             <column name="id" />
             <generator class="assigned" />
         </id>
         <property name="name" type="java.lang.String">
             <column name="name" length="20" />
         </property> 
   <one-to-one name="women" class="com.bean.Women" outer-join="false"  cascade="all"/>
     </class>
 </hibernate-mapping>
 Women.hbm.xml映射文件:id里面的generator的class="foreign"表示本id由外键提供。param元素的值代表本类哪个字段用,该字段代表外键
 <hibernate-mapping>
     <class name="com.bean.Women" table="women" catalog="mytest">
         <id name="id" type="java.lang.Integer">
             <column name="id" />
             <generator class="foreign">
              <param name="property">man</param>
             </generator>
         </id>
         <property name="name" type="java.lang.String">
             <column name="name" length="20" />
         </property>
         <!--constrained="true"表示本表主键存在外键约束,通常跟generator元素的class="foreign"同时出现的-->
         <one-to-one name="man" class="com.bean.Man" constrained="true"/>
     </class>
 </hibernate-mapping>
7、唯一外键关系的双向的一对一
 创建表,虽然可以用hibernate配置表的关系,但是为了数据严谨还是在表结构上也加上外键约束
 create table man(
  id int primary key auto_increment,
  name varchar(20)
 );
 create table women(
  id int primary key auto_increment,
  name varchar(20),
  mid int unique,
  foreign key(mid) references man(id) 
 );
 Man.java类属性:private Integer id;private String name;private Women women;
 Women.java类属性:private Integer id;private String name;private Man man;
 Man.hbm.xml映射文件:outer-join指的是是否外联查询,默认是true。cascade表示级联操作默认为none,其值有all、none、save-update、delete
 <hibernate-mapping>
     <class name="com.bean.Man" table="man" catalog="mytest">
         <id name="id" type="java.lang.Integer">
             <column name="id" />
             <generator class="native" />
         </id>
         <property name="name" type="java.lang.String">
             <column name="name" length="20" />
         </property>
         <one-to-one name="women" class="com.bean.Women" cascade="all"/>
     </class>
 </hibernate-mapping>
 Women.hbm.xml映射文件:fetch是指查询方式其值为join(表示通过outer join来查询即是只有一条sql语句)、select(表示另外发一条sql语句来查询对象的关联实体或集合,相对于第一条sql为延迟加载)。另外fetch会使得outer-join属性无效
 <hibernate-mapping>
     <class name="com.bean.Women" table="women" catalog="mytest" >
         <id name="id" type="java.lang.Integer">
             <column name="id" />
             <generator class="native" />
         </id>
         <many-to-one name="man" class="com.bean.Man" fetch="select">
             <column name="mid" unique="true" />
         </many-to-one>
         <property name="name" type="java.lang.String">
             <column name="name" length="20" />
         </property>
     </class>
 </hibernate-mapping>
8、延迟加载配置
 <class lazy="true">其值为:true、false,默认ture,加载类对象。如果为false那么会使得session.load(,)方法无效
 <one-to-one lazy="">其值为:false、proxy、no-proxy,加载类对象的关联对象
 <many-to-one lazy="">其值为:false、proxy、no-proxy,加载类对象的关联对象
 <set lazy="">其值为:true、false、extra,加载类对象的关联集合对象
9、单向多对一
 创建表(person为多的一方)
 create table room(
  id int primary key auto_increment,
  address varchar(20)
 );
 create table person(
  id int primary key auto_increment,
  name varchar(10),
  rid int,
  foreign key(rid) references room(id)
 );
 Room.java类属性:private Integer id;private String address;
 Person.java类属性:private Integer id; private Room room;private String name;
 Room.hbm.xml映射文件
 <hibernate-mapping>
     <class name="com.bean.Room" table="room" catalog="mytest">
         <id name="id" type="java.lang.Integer">
             <column name="id" />
             <generator class="native" />
         </id>
         <property name="address" type="java.lang.String">
             <column name="address" length="20" />
         </property>
     </class>
 </hibernate-mapping>
 Person.hbm.xml映射文件
 <hibernate-mapping>
     <class name="com.bean.Person" table="person" catalog="mytest">
         <id name="id" type="java.lang.Integer">
             <column name="id" />
             <generator class="native" />
         </id>
         <many-to-one name="room" class="com.bean.Room" fetch="select" cascade="all">
             <column name="rid" /><!--指的是person表的rid-->
         </many-to-one>
         <property name="name" type="java.lang.String">
             <column name="name" length="10" />
         </property>
     </class>
 </hibernate-mapping>
10、双向一对多
 把上一例子中的Room.java增加一个属性
 Room.java类属性:private Integer id;private String address;private Set persons = new HashSet();
 把上一例子中的Room.hbm.xml修改编程双向关联
 inverse属性表示维护权反转,值为false表示由Room维护,值为true表示由Person维护,默认为false即是由自己维护。一般把其设为true。
 以下面例子解析:
  如果为false那么主外键关系由Room维护。
  先执行添加Room对象
  再执行添加2个Person对象(person表的rid是从p.getRoom().getId()而来的)
  最后会对那两个Person对象的rid进行更新,更新为Room对象的rid(直接从r.getId()而来的)
  总结:inverser=false最后会有更新Person的外键rid的语句(多少条语句?由这个Room对象添加了多少个Person决定),这种方法比较严谨的保证数据不乱,但是也影响了效率。
  
  如果为true那么主外键关系有PersonW维护。
  先执行添加Room对象
  再执行添加2个Person对象(person表的rid是从p.getRoom().getId()而来的)
  总结:inverse=true最后没有更新Person的外键rid的语句,这种方法会高效,但是必须保证Person中有Room对象、Room对象中有Person对象才使得数据不会乱。
  比如room添加了person1和person2,如果person2没有把room对象set进去那么session.save(room)结果person2是没有room的,但是我们以为person2已经对应room了。
 Session session = HibernateSessionFactory.getSession();
 Room r = new Room();
 r.setAddress("address1");
 Person p1 = new Person();
 p1.setName("p1");
 p1.setRoom(r);
 Person p2 = new Person();
 p2.setName("p2");
 //Room r2 = (Room) session.get(Room.class, 2);
 //r2.setId(2);
 //p2.setRoom(r2);
 p2.setRoom(r);
 
 r.getPersons().add(p1);
 r.getPersons().add(p2);  
 session.save(r);
 session.beginTransaction().commit(); 
 <hibernate-mapping>
     <class name="com.bean.Room" table="room" catalog="mytest">
         <id name="id" type="java.lang.Integer">
             <column name="id" />
             <generator class="native" />
         </id>
         <property name="address" type="java.lang.String">
             <column name="address" length="20" />
         </property>
         <set name="persons" inverse="false" cascade="all">
             <key>
                 <column name="rid" /><!--指的是person表的rid-->
             </key>
             <one-to-many class="com.bean.Person"/>
         </set>
     </class>
 </hibernate-mapping>
 
11、双向多对多(不需要桥表的bean和桥表的映射文件inverse属性不能同时相同即是只能由某一方维护)
 表结构:通过hibernate配置是不用桥表的,但是为了数据严谨还是在数据库上建立桥表。
 create table player(
  id int primary key auto_increment,
  name varchar(20)
 );
 create table game(
  id int primary key auto_increment,
  name varchar(20)
 );
 create table p_g_bridge(
  id int primary key auto_increment,
  pid int,
  gid int,
  foreign key(pid) references player(id),
  foreign key(gid) references game(id),
  unique(pid,gid)
 );
 Player.java属性private Integer id;private String name;private Set games = new HashSet(0);
 Game.java属性 private Integer id;private String name;private Set players = new HashSet(0);
 Player.hbm.xml映射文件:需要设置set元素的table属性为桥表的名字
 <hibernate-mapping>
     <class name="com.bean.Player" table="player" catalog="mytest">
         <id name="id" type="java.lang.Integer">
             <column name="id" />
             <generator class="native" />
         </id>
         <property name="name" type="java.lang.String">
             <column name="name" length="20" />
         </property>
         <set name="games" inverse="true" table="p_g_bridge" cascade="save-update" >
             <key column="pid" />
             <many-to-many class="com.bean.Game" column="gid"/>
         </set>
     </class>
 </hibernate-mapping>
 Game.hbm.xml映射文件:需要设置set元素的table属性为桥表的名字
 <hibernate-mapping>
     <class name="com.bean.Game" table="game" catalog="mytest">
         <id name="id" type="java.lang.Integer">
             <column name="id" />
             <generator class="native" />
         </id>
         <property name="name" type="java.lang.String">
             <column name="name" length="20" />
         </property>
         <set name="players" inverse="false" table="p_g_bridge" cascade="save-update">
             <key column="gid"/>
             <many-to-many class="com.bean.Player" column="pid" />
         </set>
     </class>
 </hibernate-mapping>
 
12、双向多对多(把维护权交给桥表,两个表与桥表形成一对多关系)
 表结构:通过hibernate配置是不用桥表的,但是为了数据严谨还是在数据库上建立桥表。
 create table player(
  id int primary key auto_increment,
  name varchar(20)
 );
 create table game(
  id int primary key auto_increment,
  name varchar(20)
 );
 create table p_g_bridge(
  id int primary key auto_increment,
  pid int,
  gid int,
  foreign key(pid) references player(id),
  foreign key(gid) references game(id),
  unique(pid,gid)
 );
 Player.java属性private Integer id;private String name;private Set PGBridges = new HashSet(0); 
 Game.java属性private Integer id; private String name;private Set PGBridges = new HashSet(0); 
 PGBridge.java属性private Integer id; private Game game;private Player player;
 Player.hbm.xml映射文件
 <hibernate-mapping>
     <class name="com.bean.Player" table="player" catalog="mytest">
         <id name="id" type="java.lang.Integer">
             <column name="id" />
             <generator class="native" />
         </id>
         <property name="name" type="java.lang.String">
             <column name="name" length="20" />
         </property>
         <set name="PGBridges" inverse="true" cascade="save-update">
             <key>
                 <column name="pid" /><!--指桥表的pid列-->
             </key>
             <one-to-many class="com.bean.PGBridge" />
         </set>
     </class>
 </hibernate-mapping>
 Game.hbm.xml映射文件
 <hibernate-mapping>
     <class name="com.bean.Game" table="game" catalog="mytest">
         <id name="id" type="java.lang.Integer">
             <column name="id" />
             <generator class="native" />
         </id>
         <property name="name" type="java.lang.String">
             <column name="name" length="20" />
         </property>
         <set name="PGBridges" inverse="true"  cascade="save-update">
             <key>
                 <column name="gid" /><!--指桥表的pid列-->
             </key>
             <one-to-many class="com.bean.PGBridge" />
         </set>
     </class>
 </hibernate-mapping>
 PGBridge.hbm.xml映射文件
 <hibernate-mapping>
     <class name="com.bean.PGBridge" table="p_g_bridge" catalog="mytest">
         <id name="id" type="java.lang.Integer">
             <column name="id" />
             <generator class="native" />
         </id>
         <many-to-one name="game" class="com.bean.Game" fetch="select" cascade="save-update">
             <column name="gid" /><!--本表的pid列-->
         </many-to-one>
         <many-to-one name="player" class="com.bean.Player" fetch="select" cascade="save-update">
             <column name="pid" /><!--本表的pid列-->
         </many-to-one>
     </class>
 </hibernate-mapping>
 
13、实体声明周期
 临时态transient:实体对象在内存中并且与数据库的记录无关。
 持久态persistent:临时状态的对象被session对象保存、查询、更新成为持久太。被session维护
 游离态detached:持久态的对象被session删除或者session关闭成为游离态。不再被session维护

14、一级缓存:是指session管理的缓存默认存在并且不允许卸载的用get和load方法查询都会先去一级缓存里面查找的。
 清空一级缓存:session.flush()方法
15、二级缓存:是指SessionFactory管理的缓存是共享的是可以开启和关闭的。
 使用二级缓存步骤:
 一、在hibernate.cfg.xml配置文件配置<property name="cache.provider_class">org.hibernate.cache.EhCacheProvider</property>这个类位于org.hibernate.cache下。
 二、在类映射文件里面的class元素里面加上子元素<cache usage="read-write" />usage还可以read-only、write-only。或者在hibernate.cfg.xml配置文件里面加上<class-cache class="com.bean.Ttt" usage="read-only"/>
 三、根据步骤一的提供商(根据提供商而定)。如果需要配置二级缓存的细节则需要在hibernate.cfg.xml同一级目录下新建一个ehcache.xml文件
 <ehcache>
    <diskStore path="java.io.tmpdir"/>
     <defaultCache>
         maxElementsInMemory="10000"<!--缓存中对象个数最大为10000-->
         eternal="false"<!--缓存中对象是否为永久的,如果是,超时设置将被忽略,对象从不过期-->
         timeToIdleSeconds="120"<!--缓存数据钝化时间(设置对象在它过期之前的空闲时间)-->
         timeToLiveSeconds="120"<!--缓存数据的生存时间(设置对象在它过期之前的生存时间)-->
         overflowToDisk="true"<!--内存不足时,是否启用磁盘缓存 -->
      </defaultCache>
 </ehcache>
 如果找不到这个文件则去找默认的配置文件ehcache-failsafe.xml文件(位于ehcache.jar包下的),文件内容是:
 <ehcache>
     <defaultCache
             maxElementsInMemory="10000"
             eternal="false"
             timeToIdleSeconds="120"
             timeToLiveSeconds="120"
             overflowToDisk="true"
             diskPersistent="false"
             diskExpiryThreadIntervalSeconds="120"
             memoryStoreEvictionPolicy="LRU"
             />
 </ehcache>
 注意:如果不是load和get方法而是Query query=session.createQuery(strSql)则需要把query.setCacheable(true)意思是允许本查询去查询缓存里面的数据。
 再注意:一级缓存、二级缓存、直接查询数据,速度依次降低。
 关闭二级缓存:在hibernate.cfg.xml配置<property name="cache.use_second_level_cache">false</property>
 清空二级缓存里面的数据:sessionFactory.evict(class)或者sessionFactory.evict(class,id)
16、查询缓存
 查询缓存默认不开启,如果要开启:在hibernate.cfg.xml配置<property name="cache.use_query_cache">true</property>
 如果不开启那么查询缓存数据只能是通过id查询。开启后可以通过条件查询来查询缓存数据。
 
17、批量处理
 需要配置:在hibernate.cfg.xml里面加上<property name="jdbc.batch_size">50</property>意思是批量提交的话每50条就去处理。
 注意:批量处理的话建议关闭二级缓存,提交效率。

18、注解
 一、声明实体
 @Entity
 @Table(name="表名")
 @Id 位于id属性声明的上一行或者在get方法上一行(前提是get方法的名称是由get+MethodName构成的)
 @GeneratedValue (strategy =GenerationType.AUTO) 位于@Id下方 表示自动增长,不写就是自动的
 @Column (name = "表的列名"s) 位于实体属性声明的上面或者在get方法上一行(前提是get方法的名称是由get+MethodName构成的)
 @Transient注明属性不映射到表上或者在get方法上一行(前提是get方法的名称是由get+MethodName构成的)
 二、在hibernate.cfg.xml文件加入元素<mapping class="包名+类名" />
 三、使用方法 
  Configuration config = new AnnotationConfiguration().configure();
  SessionFactory factory = config.buildSessionFactory();
  Session session = factory.openSession();
 例子:
 表结构
 create table ttt(
  id int primary key auto_increment,
  name varchar(20)
 );
 Ttt.java实体类
 @Entity
 @Table(name="ttt")
 public class Ttt implements java.io.Serializable {
  @Id
  @GeneratedValue (strategy =GenerationType.AUTO)
  private Integer id;
  @Column (name = "name")
  private String name;
 
  public Ttt() {
  }
  public Ttt(String name) {
   this.name = name;
  }
  
  public Integer getId() {
   return this.id;
  }
  public void setId(Integer id) {
   this.id = id;
  } 
  public String getName() {
   return this.name;
  }
  public void setName(String name) {
   this.name = name;
  }
 }
 
 
19、注解双向一对一
 
 Body.java
 @Entity
 public class Body {
  private int id;
  private String name;
  private Heart heart;
  @Id
  @GeneratedValue
  public int getId() {
   return id;
  }
  public void setId(int id) {
   this.id = id;
  }
  public String getName() {
   return name;
  }
  public void setName(String name) {
   this.name = name;
  }
  @OneToOne(cascade=CascadeType.ALL)//级联
  @JoinColumn(name="h_id",unique=true)//设置外键列名并加唯一约束
  public Heart getHeart() {
   return heart;
  }
  public void setHeart(Heart heart) {
   this.heart = heart;
  }
 }
 Heart.java类
 @Entity
 public class Heart {
  private int id;
  private String name;
  private Body body;
  @Id
  @GeneratedValue
  public int getId() {
   return id;
  }
  public void setId(int id) {
   this.id = id;
  }
  public String getName() {
   return name;
  }
  public void setName(String name) {
   this.name = name;
  }
  @OneToOne(mappedBy="heart")//指向关联实体的hear属性。本实体Heart的body属指向关联实体Body的heart属性
  public Body getBody() {
   return body;
  }
  public void setBody(Body body) {
   this.body = body;
  }
 }
20、注解多对一
 Department.java类
 @Entity
 @Table(name="t_dept")
 public class Department {
  private int id;
  private String dept_name;
  private Organizaiton org;
  @ManyToOne//多对一
  @JoinColumn(name="abc")
  public Organizaiton getOrg() {
   return org;
  }
  public void setOrg(Organizaiton org) {
   this.org = org;
  }  
  @Id
  @GeneratedValue
  public int getId() {
   return id;
  }
  public void setId(int id) {
   this.id = id;
  }
  public String getDept_name() {
   return dept_name;
  }
  public void setDept_name(String deptName) {
   dept_name = deptName;
  }
 }
 Organization.java类
 @Entity
 @Table(name="t_org")
 public class Organizaiton {
  private int id;
  private String org_name;
  @Id @GeneratedValue
  public int getId() {
   return id;
  }
  public void setId(int id) {
   this.id = id;
  }
  public String getOrg_name() {
   return org_name;
  }
  public void setOrg_name(String orgName) {
   org_name = orgName;
  }
 }
 
20、注解双向一对多
 Orgnization.java类,一的一方
 @Entity
 @Table(name="t_org")
 public class Organizaiton {
  private int id;
  private String org_name;
  private Set<Department> dept;
  @Id @GeneratedValue
  public int getId() {
   return id;
  }
  public void setId(int id) {
   this.id = id;
  }
  @OneToMany(mappedBy="org")//把维护权给对方Department
  @JoinColumn(name="org_id")
  public Set<Department> getDept() {
   return dept;
  }
  public void setDept(Set<Department> dept) {
   this.dept = dept;
  }
  public String getOrg_name() {
   return org_name;
  }
  public void setOrg_name(String orgName) {
   org_name = orgName;
  }
 }
 Department.java类,多的一方
 @Entity
 @Table(name = "t_dept")
 public class Department {
  private int id;
  private String dept_name;
  private Organizaiton org;
  
  @ManyToOne
  @JoinColumn(name="org_id")
  public Organizaiton getOrg() {
   return org;
  }
  public void setOrg(Organizaiton org) {
   this.org = org;
  }
  @Id
  @GeneratedValue
  public int getId() {
   return id;
  }
  public void setId(int id) {
   this.id = id;
  }
  public String getDept_name() {
   return dept_name;
  }
  public void setDept_name(String deptName) {
   dept_name = deptName;
  }
 }

20、注解双向多对多
 User.java类
 @Entity
 public class User {
  private int id;
  private String name;
  private Set<Role> roles = new HashSet<Role>();
  
  @ManyToMany
  /**
   * 默认,hibernate会自动创建一个中间表,来维护多对多关系
   * */
  @JoinTable(name="t_user_role",
    joinColumns={@JoinColumn(name="u_id")},
    inverseJoinColumns={@JoinColumn(name="r_id")}
  )
  /**
   * @JoinTable(name="t_user_role")指定中间表名称
   * joinColumns={@JoinColumn(name="u_id")}指定对象的外键
   * inverseJoinColumns={@JoinColumn(name="r_id")}指定关联对象的外键
   * */
  public Set<Role> getRoles() {
   return roles;
  }
  public void setRoles(Set<Role> roles) {
   this.roles = roles;
  }
  @Id @GeneratedValue
  public int getId() {
   return id;
  }
  public void setId(int id) {
   this.id = id;
  }
  public String getName() {
   return name;
  }
  public void setName(String name) {
   this.name = name;
  }
 }
 Role.java类
 @Entity
 public class Role {
  private int id;
  private String name;
  private Set<User> users = new HashSet<User>();
 
  @ManyToMany
  @JoinTable(name="t_user_role",
    joinColumns={@JoinColumn(name="r_id")},
    inverseJoinColumns={@JoinColumn(name="u_id")}
  )
  public Set<User> getUsers() {
   return users;
  }
  public void setUsers(Set<User> users) {
   this.users = users;
  }
  @Id @GeneratedValue
  public int getId() {
   return id;
  }
  public void setId(int id) {
   this.id = id;
  }
  public String getName() {
   return name;
  }
  public void setName(String name) {
   this.name = name;
  }
 }
 
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值