Hibernate基本(笔记)

本文详细介绍了如何通过Maven或官网下载依赖,创建hibernate.cfg.xml和类名.hbm.xml配置文件,以及如何创建JavaBean实体类并进行CRUD操作。涵盖了数据库连接、主键策略和实体关系映射等内容。
摘要由CSDN通过智能技术生成

一、导入相关依赖

方法一:通过maven,直接在pom.xml中写需要的版本

 方法二:前往官网自己下载所需要的组件包

  • documentation:存放镶滚文件与API
  • lib:依赖,required子目录下为必须jar包
  • project:源码资源与用例

将required下的jar包放入lib中,(非JavaWeb,则直接放在src下面即可)

别忘记build inpath以及JDBC也要导入。

二、创建配置文件

两种xml

在hibernate主要以两类xml为主:

  • hibernate.cfg.xml:核心配置文件,用于连接数据库。本文以MySQL为例。
  • 类名.hbm.xml:用于映射持久化类。即,记录了数据库的表,对应存储的类。自动将表的属性存放于类对应的成员变量之中。

本文的hibernate放在了resource下:

hibernate.cfg.xml

<?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="hibernate.connection.url">jdbc:mysql://127.0.0.1/数据库名称</property>
        <!--驱动名-->
        <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
        <!--用户名、密码-->
        <property name="hibernate.connection.username">root</property>
        <property name="hibernate.connection.password">mysql</property>
        <!--hibernate方言路径,及hibernate的语法糖-->
        <property name="dialect">org.hibernate.dialect.MySQLDialect</property> 
        <!--可选设置-是否打印sql语句,即是否需要展现执行所对应的sql语句-->
        <property name="hibernate.show_sql">true</property>
        <!--可选设置-是否格式化sql语句,即sql语句是否以方便阅读的方式展现-->
        <property name="hibernate.format_sql">true</property>
        <!--hibernate映射路径,即我们所写的映射文件-->
        <mapping resource="路径:类名.hbm.xml“/>
    </session-factory>
</hibernate-configuration>

类名.hbm.xml 

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
    <!--名称相同时可以不用写数据库对应的部分-->
    <!--类与表的对应-->
    <class name="路径:类名" table="表名">
        <!--成员变量与键值的对应-->
        <id name="成员变量名" column="键名">
            <!--主键生成策略,“本地生成”-->
            <generator class="native"/>
            <!--外键
            <generator class="foreign">
            <param name="property">成员变量名(是一个成员类,它的主键即为外键)</param>
            </generator>
            -->
        </id>
        <!--name – 对应类的属性名称
            type – 指定属性的类型,一般情况下可以不用指定,由hibernate自动匹配(可参考文档中的有关说明)
            length – 指定长度
            column – 指定属性所对应的数据库字段的名称,如果不指定,就是属性的名称-->
        <property name="成员变量名" column="属性"/>
    </class>
</hibernate-mapping>

 映射的类也应该为JavaBean类,即每一个对象都有对应的get与set方法。

generator的策略

  • "assigned":主键由外部程序负责生成,需要在save()方法前指定(hibernate中的写入数据库方法)。这种主键的生成方式不建议使用,在数据库表设计时就应该使用代理主键(surrogate key),不应使用自然主键(natural key具有业务含义),在没有指定标签时,默认就是assigned主键的生成方式在插入数据的时候主键由用户自己添加,hibernate也不管。
  • "hilo":通过hi/lo算法实现的主键生成机制,³使用一个高/低位算法生成的long、short或int类型的标识符,给定一个表和字段作为高位值的来源,默认的表是hibernate_unique_key,默认的字段是next_hi。它将id的产生源分成两部分,DB+内存,然后按照算法结合在一起产生id值,可以在很少的连接次数内产生多条记录,提高效率。
  • "seqhilo":与"hilo"相似。sequence和hilo的结合,hilo的高位由sequence产生,所以也需要底层数据库的支持通过hilo算法实现,但是主键历史保存在Sequence中,适用于支持 Sequence 的数据库,如 Oracle(比较少用)。
  • "increment":主键按顺序递增。³这个是由Hibernate在内存中生成主键,每次增量为1,不依赖于底层的数据库,因此所有的数据库都可以使用,但问题也随之而来,由于是Hibernate生成的,所以只能有一个Hibernate应用进程访问数据库,否则就会产生主键冲突,不能在集群情况下使用插入数据的时候hibernate会给主键添加一个自增的主键,但是一个hibernate实例就维护一个计数器,所以在多个实例运行的时候不能使用这个方法 。
  • "identity":采用数据库的主键生成机制。适用于MySQL、DB2、MS SQL Server,采用数据库生成的主键,用于为long、short、int类型生成唯一标识 。
  • "sequence":采用数据库提供的sequence机制生成主键。DB2、Oracle均支持的序列,用于为long、short或int生成唯一标识 。
  • "native":hibernate自己判断,会根据底层数据库的能力,从identity、sequence、hilo中选择一个,灵活性更强,但此时,如果选择sequence或者hilo,则所有的表的主键都会从和hibernate默认的sequence或者hilo表中取。并且,有的数据库对于默认情况主键生成测试的支持,效率并不是很高。对于 oracle 采用 Sequence 方式,对于MySQL 和 SQL Server 采用。identity(自增主键生成机制),native就是将主键的生成工作交由数据库完成。
  • "uuid.hex":由hibernate基于128位UUID算法生成16位进制数值。(使用了IP地址+JVM的启动时间(精确到1/4秒)+系统时间+一个计数器值(在JVM中唯一) ),hibernate会算出一个128位的唯一值插入。
  • "uuid.string":与uuid.hex类似,只是生成的主键未进行编码
  • "foreign":使用另一个相关联的对象标识符作为主键(外键)

三、创建实体类

数据库

那么现在创建一个User类,其中uid为主键

package JavaBean;

public class User {
	private int uid;
	private String uname;
	private String uimage;
	private String pwd;
	public User() {
		this.uid = -1;
		this.uname = null;
		this.uimage = null;
		this.pwd = null;
	}
	public int getUid() {
		return this.uid;
	}
	public String getUname() {
		return this.uname;
	}
	public String getUimage() {
		return this.uimage;
	}
	public String getPwd() {
		return this.pwd;
	}
	public void setUid(int UID) {
		this.uid = UID;
	}
	public void setUname(String UNAME) {
		this.uname = UNAME;
	}
	public void setUimage(String UIMAGE) {
		this.uimage = UIMAGE;
	}
	public void setPwd(String PWD) {
		this.pwd = PWD;
	}
}

四、三个对象

  • 瞬时对象(Transient Objects):使用new 操作符初始化的对象不是立刻就持久的。它们的状态是瞬时的,也就是说它们没有任何跟数据库表相关联的行为,只要应用不再引用这些对象(不再被任何其它对象所引用),它们的状态将会丢失,并由垃圾回收机制回收。
  • 持久化对象(Persist Objects):持久实例是任何具有数据库标识的实例。它有持久化管理器Session统一管理,持久实例是在事务中进行操作的——它们的状态在事务结束时同数据库进行同步。当事务提交时,通过执行SQL的INSERT、UPDATE和DELETE语句把内存中的状态同步到数据库中。
  • 离线对象(Detached Objects):Session关闭之后,持久化对象就变为离线对象。离线表示这个对象不能再与数据库保持同步,它们不再受Hibernate管理。

五、创建实体类-关系映射文件

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
    <class name="JavaBean.User">
        <id name="uid" column="UID">
            <generator class="native"/>
        </id>
        <property name="uname" column="UName"/>
        <property name="pwd" column="Pwd"/>
        <property name="uimage" column="UImage"/>
    </class>
</hibernate-mapping>

六、调用hibernateAPI完成操作

一般异常捕捉格式。

try{

}
catch(HibernateException ex){
    ex.printStackTrace();
}
catch(Exception ex){
    ex.printStackTrace();
   //如果有事务的话,建议回滚 session.getTransaction().rollback();
}
finally{

}

package Util;

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

public class test {
	public static void main(String[] args) {
		//读取配置文件
		Configuration cfg = new Configuration().configure();
		//创建session级别的工厂,用于批量制造实例(工厂模式)
		//同时该类会限制连接个数,类似于连接池,会占用连接数
        //SessionFactory由Configuration对象创建,所以每个Hibernate配置文件,实际上是对SessionFactory的配置
		SessionFactory factory = cfg.buildSessionFactory();
        //此处的session是hibernate的会话,不是JavaWeb的
        //Session不是线程安全的,它代表与数据库之间的一次操作,它的概念介于Connection和Transaction之间。Session也称为持久化管理器,因为它是与持久化有关的操作接口。

		Session session = factory.openSession();
		//开始事务,从现在开始到事务提交,都为原子级
		session.beginTransaction();
		//创建User类
		User user = new User();
		user.setUname("管理员");
		user.setPwd("admin");
		//让user变为持久化数据
		session.save(user);
		//提交事务
		session.getTransaction().commit();
		//关闭session工厂
		if(session.isOpen()){
			session.close();
		}
	}
}

不需要提交事务

package Util;


import java.util.Iterator;
import java.util.List;

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

import JavaBean.User;

public class test {
	public static void main(String[] args) {
		//读取配置文件
		Configuration cfg = new Configuration().configure();
		SessionFactory factory = cfg.buildSessionFactory();
		Session session = factory.openSession();
		//语句,User是类名,不是表名
		Query query = session.createQuery("from User"); 
        //Query query = session.createQuery("from User where UID = 1"); 
		List users = query.list();
		for(Iterator iter = users.iterator();iter.hasNext();) {
			User user = (User)iter.next();
			System.out.print("UserName:"+user.getUname()+"\n");
		}
		//关闭session工厂
		if(session.isOpen()){
			session.close();
		}
	}
}

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

import JavaBean.User;

public class test {
	public static void main(String[] args) {
		//读取配置文件
		Configuration cfg = new Configuration().configure();
		SessionFactory factory = cfg.buildSessionFactory();
		Session session = factory.openSession();
		session.beginTransaction();
        //参数一持久化类/全类名,参数二主键,参数三锁选项
		User user = (User)session.get(User.class,3);
		user.setPwd("123");
		//提交事务
		session.getTransaction().commit();
		//关闭session工厂
		if(session.isOpen()){
			session.close();
		}
	}
}

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

import JavaBean.User;

public class test {
	public static void main(String[] args) {
		//读取配置文件
		Configuration cfg = new Configuration().configure();
		SessionFactory factory = cfg.buildSessionFactory();
		Session session = factory.openSession();
		session.beginTransaction();
		User user = new User();
		user.setUid(3);
		//语句
		session.delete(user);
		
		//提交事务
		session.getTransaction().commit();
		//关闭session工厂
		if(session.isOpen()){
			session.close();
		}
	}
}

session.get与session.load

  • get方法会在调用之后,立即会向数据库发出sql语句,返回持久化对象;
  • load方法会在调用后,会返回一个代理对象,该代理对象只保存了实体对象的id。直到使用对象的非主键属性时才会发出sql语句。
  • 查询数据库中不存在的数据时,get方法返回null,而load方法则是会抛出异常。

七、多对一与一对一与多对多

cascade级联问题:

  • all-代表在所有的情况下都执行级联操作
  • none-在所有情况下都不执行级联操作
  • save-update-在保存和更新的时候执行级联操作
  • delete-在删除的时候执行级联操作

该句用在了类名.hbm.xml之中,代表该表与name中的类column中的属性发生了关联。

<!--本表 to 另一张表-->
<many-to-one name="" column="" cascade="all"/>

在未添加级联的情况下:

        Group group = new Group();
		group.setName("jkjk");
		User user = new User();
		user.setName("管理员");
        //因为group为瞬时对象,此处无法继续
		user.setGroup(group);
		
		session.save(user);

我们需要这样做 

		Group group = new Group();
		group.setName("jkjk");
		
		//执行save操作之后,group对象变成持久化对象的状态
		session.save(group);
		
		User user = new User();
		user.setName("管理员");
		user.setGroup(group);
		
		session.save(user);

在添加了后,我们第一种写法就可以了

        Group group = new Group();
		group.setName("A");
		
		User user = new User();
		user.setName("管理员");
		user.setGroup(group);
		
		session.save(user);

一对一(one-to-one)

一张表的一条记录对应另一张表的唯一一条记录

主键关联映射

onstrained属性是在主键映射一对一关系的时候会用到,用在引用方。

当前类名.hbm.xml对于name为限制,即当前的外键是主键且仅在name的类中唯一存在。

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

有外键的类 

public class Person {
     private int id;
     private IdCard idCard;
}
<!--映射文件-->
<class name="com.bjsxt.hibernate.Person">
        <id name="id">
            <generator class="foreign">
            <param name="property">idCard</param>
            </generator>
        </id>
       <one-to-one name="idCard" constrained="true"/>
</class>

被引用主键的类

public class IdCard {
     private int id;
     private Person person;
}
<class name="com.bjsxt.hibernate.IdCard">
        <id name="id">
            <generator class="native"/>
        </id>
        <one-to-one name="person" cascade="all"/>
</class>

唯一外键关联映射

两个类本身都有一个自己的主码。我们想让他们关联,因为他们的主码都可以作为对方的候选码。那么,我们就会想让他们变为一对一关系,但又不想改动现在的主码,那么就需要这样写。

public class Mankind {
	private String id;
	private String name;
	private Nose nose;
}
 <class name="com.bjsxt.hibernate.Mankind">
        <id name="id">
            <generator class="uuid"/>
        </id>
        <property name="name"/>
        <!--unique属性,使得这端唯一-->
        <many-to-one name="nose" unique="true" cascade="all"></many-to-one>
 </class>

另一个类

public class Nose {
	private String id;
	private Mankind mankind;
}
 <class name="com.bjsxt.hibernate.Nose">
        <id name="id">
            <generator class="uuid"/>
        </id>
        <!--property-ref指定了关联类的成员类的名字,这个属性将会和本类的主键相对应。如果没有指定,会使用对方关联类的主键来跟本类的主键比较,-->
        <one-to-one name="mankind" property-ref="nose"  cascade="all"></one-to-one>
 </class>

一对多(one to many)

public class Classes {
	private String id;
	private String name;
	private Set students;
}
<hibernate-mapping>
    <class name="com.bjsxt.hibernate.Classes">
        <id name="id">
            <generator class="uuid"/>
        </id>
        <property name="name" lazy="false" inverse = "true"/>
        <set name="students">
        	<key column="classesid" ></key>
        	<one-to-many class="com.bjsxt.hibernate.Student" />
        </set>
    </class>
</hibernate-mapping>
public class Student {
	private String id;
	private String name;
}

多对多(many to many)

<class name="com.test.hibernate.Student">
	<id name="id" column="userId"><generator class="native"/></id>
	<set name="trainClasses" lazy="true" cascade="save-update">
		<key column="studentId"/>
		<many-to-many class="com.test.hibernate.TrainClass" column="trainClassId"/>
	</set>
</class>

<class name="com.test.hibernate.TrainClass" table="TBL_TRAIN_CLASS">
	<id name="id" column="trainClassId">
        <generator class="native"/>
    </id>
</class>

八、其他

inverse – 标记由哪一方来维护关联关系(双向关联中会用到)

lazy -- 延迟加载(懒加载),一般用于集合的抓取策略,也就是说只在需要用到的情况下,再发出select语句,将其相关的对象查询出来。默认为true

标准化查询

      Criteria criteria = session.createCriteria(User.class);
      criteria.add(Expression.like("name","J%"));
      List users = criteria.list();
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值