Hibernate基础知识

1 概念

Hibernate是一个开放源代码的对象关系映射框架,它对JDBC进行了非常轻量级的对象封装,它将POJO与数据库表建立映射关系,是一个全自动的orm框架,hibernate可以自动生成SQL语句,自动执行,使得Java程序员可以随心所欲的使用对象编程思维来操纵数据库

概念解释

orm:object relational mapper 对象关系映射
    持久层实现java类的属性与rdbms表的列一一对应关系
    实现java对象和结果集行的对应关系
域模型:java中模型对象的思想
       java类之间的关系
       关联关系:订单和客户:订单要指定其所属客户  (部分依赖)
       聚集关系:轮胎和车:轮胎是车的一部分 (整体和部分)
       依赖关系:action和service:action中所有方法都要通过service来实现  (类似于寄生)
       一般关系:儿子和父亲:继承关系
      
关系模型:rdbms中的二维表
    :1对1  :把从表的主键定义为外键  来引用主表的主键
    :n对n  :定义一个关系表:定义两列作为联合主键  这两列作为外键 类分别引用另外两张表的主键
    :1对n  :把1定义为主表  把n定义为从表  在从表中定义一个外键来引用主表的主键

2 hibernate案例

2.1 创建项目:web/java

2.2 导入jar包

image

2.3 创建核心配置文件

  • 位置src
  • 名字:hibernate.properties
hibernate.dialect=org.hibernate.dialect.MySQLDialect  #指定方言
hibernate.connection.driver_class=com.mysql.jdbc.Driver
hibernate.connection.url=jdbc:mysql://localhost:3306/db_37
hibernate.connection.username=root
hibernate.connection.password=root
hibernate.show_sql=true                              #是否显示sql语句

2.4 创建数据库

DROP TABLE student;
CREATE TABLE `student` (
  `sid` INT(11) NOT NULL AUTO_INCREMENT,
  `sname` VARCHAR(11) DEFAULT NULL,
  `sex` CHAR(1) DEFAULT NULL,
  `score` FLOAT(4,1) DEFAULT NULL,
  `sdy` TINYINT(1) DEFAULT NULL,
  `sbirthday` DATE DEFAULT NULL,
  PRIMARY KEY (`sid`)
) ENGINE=INNODB AUTO_INCREMENT=221 DEFAULT CHARSET=utf8
INSERT INTO student VALUES(
   NULL,
   SUBSTRING(UUID(),1,8),
   IF(RAND()>0.5,"男","女"),
   CEIL(RAND()*100),
   RAND()>0.5,
   CONCAT(CEIL(RAND()*10+1990),"-",CEIL(RAND()*12),"-",CEIL(RAND()*31))
 );
 SELECT * FROM student;

2.5 mapper映射文件:

  • 创建实体类
public class Student implements Serializable {
    private Integer sid;
    private String sname;
    private String sex;
    private Float score;
    private Boolean sdy;
    private Date sbirthday;
    ...
}
  • 指定表的列与类的属性的对应关系:位置必须和实体类同一个包 名字必须是:实体类.hbm.xml
<?xml version="1.0" encoding="gbk"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd" >
<hibernate-mapping>
    <!-- 指定类名 和 表名 -->
    <class name="sss.entity.Student" table="student">
        <!-- 指定主键列对应的属性 -->
        <id name="sid" column="sid" type="int">
            <!-- 主键自增方式:数据库自增-->
            <generator class="identity"/>
        </id>
        <property name="sname" column="sname" type="string"/>
        <property name="sex" column="sex" type="string"/>
        <property name="sbirthday" column="sbirthday" type="date"/>
        <property name="sdy" column="sdy" type="boolean"/>
        <property name="score" column="score" type="float"/>
    </class>
</hibernate-mapping>

2.6 测试类

import org.hibernate.Query;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;
import org.hibernate.classic.Session;
import sss.entity.Student;

import java.util.Date;
import java.util.List;

public class Test {
    public static void main(String[] args) {
        //1 创建Configration对象 自动读取heibernate的核心配置文件
        Configuration conf = new Configuration();
        //2 读取指定实体类的mapper映射文件
        conf.addClass(Student.class);
        //3 通过Configuration创建sessionfactory对象
        SessionFactory factory = conf.buildSessionFactory();
        //4 获取连接
        Session session = factory.openSession();
        //5 创建事务
        Transaction transaction = session.beginTransaction();
        //6 开启事务
        transaction.begin();

        /*通过session实现crud*/
        //获取一个
        Student s1 = (Student) session.get(Student.class, 221);
        System.out.println(s1);
        //获取所有
        //hql语句:面向对象的
        Query query = session.createQuery("from sss.entity.Student");
        List<Student> list = query.list();
        System.out.println(list);
        //添加一个
        session.save(new Student(1, "叶晨", "男", 66f, false, new Date()));
        //修改一个:要求修改和删除之前必须先获取对象
        Student s2 = (Student) session.get(Student.class, 222);
        s2.setSbirthday(new Date());
        s2.setScore(33f);
        s2.setSname("楚灵");
        s2.setSex("女");
        session.update(s2);
        //删除一个
        Student s3 = (Student) session.get(Student.class, 223);
        session.delete(s3);
        //事务提交
        transaction.commit();
        //关闭连接
        session.close();
    }
}

3 hibernate改进(配置文件是xml)

3.1 创建xml核心配置文件:

  • 名字随意
  • 位置随意:hibernatepro.xml
<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
        "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
        "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>

    <session-factory>
        <!-- 指定方言 -->
        <property name="dialect">org.hibernate.dialect.MySQLDialect</property>
        <!-- 指定连接的四大参数 -->
        <property name="connection.url">jdbc:mysql://localhost:3306/ssr</property>
        <property name="connection.driver_class">com.mysql.jdbc.Driver</property>
        <property name="connection.username">root</property>
        <property name="connection.password">root</property>
        <!-- 是否显示sql语句 -->
        <property name="show_sql">true</property>

        <!-- 导入类与表的映射文件 -->
        <mapping resource="sss/entity/Student.hbm.xml"/>
    </session-factory>
</hibernate-configuration>

3.2创建测试类

  • TestPro
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;
import org.hibernate.classic.Session;
import sss.entity.Student;

public class TestPro {
    public static void main(String[] args) {
        //1 创建Configration对象 自动读取heibernate的核心配置文件
        Configuration conf = new Configuration();
        //2 读取核心配置文件
        conf.configure("sss/test/hibernatepro.xml");
        //3 通过Configuration创建sessionfactory对象
        SessionFactory factory = conf.buildSessionFactory();
        //4 获取连接
        Session session = factory.openSession();
        //5 创建事务
        Transaction transaction = session.beginTransaction();
        //6 开启事务
        transaction.begin();

		//增 删 改 ......
        
        //7 事务提交
        transaction.commit();
        //8 关闭连接
        session.close();
    }
}

4 主键自增方式(策略)

  • 在save插入行数据时 指定主键值的方式
  • 在xml中修改
<id name="sid" column="sid" type="int">
    <generator class="identity"/><!-- 主键自增方式:数据库自增-->
</id>

4.1 可选类型

* increment:适用于int/long/short类型的字段: hibernate自增
* identity:适用于int/long/short类型的字段:数据库自增:支持auto_increment的数据库:mysql
* sequence:通过sequence实现自增的数据库:oracle
* assinged:主键列由程序员手动赋值
* uuid:适用于string类型的字段:随机一个32位16进制的字符串
* hilo:适用于int/long/short类型的字段 根据高/低位算法自动生成
* native:由程序根据数据库自动选择:identity、sequence、hilo

4.2 increment自增

<id name="sid" column="sid" type="int">
    <--主键自增方式:auto_increment [数据库需要使用auto_increment 否则无效]-->
    <generator class="identity"/> 
        
    <!-- 主键自增方式:hibernate自增-->
    <generator class="increment"/>
</id>
  • 添加
//添加一个
session.save(new Student("韩梅3","女",11f,true,new Date()));//不指定sid 通过hibernate自增 自动赋值
  • sql语句::执行了两次sql语句
Hibernate: select max(sid) from student
Hibernate: insert into student (sname, sex, sbirthday, sdy, score, sid) values (?, ?, ?, ?, ?, ?)
  • 注意:
increment自增是hibernate自增:会先查询当前表的主键的最大值  然后最大值+1给添加的对象的主键列赋值
不适应于:多线程或者分布式项目

4.3 sequence序列自增

  • 创建oracle表,mysql不能用
CREATE TABLE stu(
  sid INT PRIMARY KEY,
  sname VARCHAR(20),
  sex CHAR(3),
  score FLOAT,
  sbirthday DATE
)

CREATE sequence seq_stu_11 START WITH 1000

INSERT INTO stu VALUES(
   seq_stu_11.nextval,
   dbms_random.string('x',6),
   '男',
   trunc(dbms_random.value*100,1),
   to_date(trunc(dbms_random.value*10+1990)||'-'||trunc(dbms_random.value*12+1)||'-'||trunc(dbms_random.value*30+1),'yyyy-MM-dd')
);
  • 创建实体类
public class Stu implements Serializable {
    private Integer sid;
    private String sname;
    private String sex;
    private Float score;
    private Date sbirthday;
    ...
}
  • 创建mqpper映射文件-->Stu.hbm.xml
<?xml version="1.0" encoding="gbk"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd" >
<hibernate-mapping>
    <!-- 指定类名 和 表名 -->
    <class name="sss.entity.Stu" table="stu">
        <!-- 指定主键列对应的属性 -->
        <id name="sid" column="sid" type="int">
            <!--<generator class="identity"/> 主键自增方式:数据库自增 auto_increment-->
            <!-- <generator class="increment"/>主键自增方式:hibernate自增-->
            <!-- sequence自增 -->
            <generator class="sequence">
                <param name="sequence">seq_stu_11</param>
            </generator>
        </id>
        <property name="sname" column="sname" type="string"/>
        <property name="sex" column="sex" type="string"/>
        <property name="score" column="score" type="float"/>
        <property name="sbirthday" column="sbirthday" type="date"/>

    </class>
</hibernate-mapping>
  • 创建hibernate.xml连接oracle
<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
        "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
        "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>

    <session-factory>
        <!-- 指定方言 -->
        <property name="dialect">org.hibernate.dialect.Oracle10gDialect</property>
        <property name="connection.url">jdbc:oracle:thin:@localhost:1521:orcl</property>
        <property name="connection.driver_class">oracle.jdbc.driver.OracleDriver</property>
        <property name="connection.username">wen</property>
        <property name="connection.password">123</property>
        <!-- 是否显示sql语句 -->
        <property name="show_sql">true</property>

        <!-- 导入类与表的映射文件-->
        <mapping resource="sss/entity/Stu.hbm.xml"/>
    </session-factory>
</hibernate-configuration>
  • 测试
//添加一个
session.save(new Stu("楚灵", "女", 11f, new Date()));

4.4 uuid自增:只适用于字符串类型的主键列

  • 创建表
CREATE TABLE tea(
    tid varchar(50) primary key,
    tname VARCHAR(20)
)
  • mapper映射文件
  • 注意:使用uuid定义id必须是String类型
<id name="sid" column="sid" type="int">
    <!-- uuid自增-->
    <generator class="uuid"/>
</id>
  • 测试
//插入一条数据
session.save(new Stu("楚宣", "女", 11f, new Date()));

5 表与表之间的关系

5.1 1对n

  • 在多的一方定义外键 来引用主表的主键

创建数据库

CREATE TABLE tea(
   tid INT PRIMARY KEY AUTO_INCREMENT,
   tname VARCHAR(11)
);
INSERT INTO tea VALUES(1,"李老师");
INSERT INTO tea VALUES(2,"郭老师");

CREATE TABLE stu(
   sid INT PRIMARY KEY AUTO_INCREMENT,
   sname VARCHAR(11),
   stid INT,
   CONSTRAINT fk_099 FOREIGN KEY(stid) REFERENCES tea(tid)
);
INSERT INTO stu VALUES(1001,"李老师学生1",1);
INSERT INTO stu VALUES(1002,"李老师学生2",1);
INSERT INTO stu VALUES(2001,"郭老师学生1",2);
INSERT INTO stu VALUES(2002,"郭老师学生2",2);

创建实体类

public class Stu implements Serializable {
    private Integer sid;
    private String sname;
    //定义引用记录老师
    private Tea tea;
    ...
}
public class Tea implements Serializable {
    private Integer tid;
    private String tname;
    //定义集合记录学生
    private Set<Stu> stuSet;
    ...
}

mapper映射文件

  • Stu.hbm.xml
<?xml version="1.0" encoding="gbk"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd" >
<hibernate-mapping>
    <!-- 指定类名 和 表名 -->
    <class name="sss.entity.Stu" table="stu">
        <!-- 指定主键列对应的属性 -->
        <id name="sid" column="sid" type="int">
            <!-- 自增-->
            <generator class="identity"/>
        </id>
        <property name="sname" column="sname" type="string"/>
        <!--n对1-->
        <!--
            many-to-one:
                name:n中定义的引用
                column:外键列名
        -->
        <many-to-one name="tea" column="stid" class="sss.entity.Tea"/>

    </class>
</hibernate-mapping>
  • Tea.hbm.xml
<?xml version="1.0" encoding="gbk"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd" >
<hibernate-mapping>
    <!-- 指定类名 和 表名 -->
    <class name="sss.entity.Tea" table="tea">
        <!-- 指定主键列对应的属性 -->
        <id name="tid" column="tid" type="int">
            <!-- 自增-->
            <generator class="identity"/>
        </id>
        <property name="tname" column="tname" type="string"/>
        <!--1对n-->
        <!--
            one-to-money:
                set的属性:name 对应的n集合的引用名
                key的column:从表的外键列名
                one-to-money的class:集合元素的类型
        -->
        <set name="stuSet" lazy="true">
            <key column="stid"/>
            <one-to-many class="sss.entity.Stu"/>
        </set>

    </class>
</hibernate-mapping>

测试

import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;
import org.hibernate.classic.Session;
import sss.entity.Stu;

public class TestPro {
    public static void main(String[] args) {
        //1 创建Configration对象 自动读取heibernate的核心配置文件
        Configuration conf = new Configuration();
        //2 读取核心配置文件
        conf.configure("sss/test/hibernatepro.xml");
        //3 通过Configuration创建sessionfactory对象
        SessionFactory factory = conf.buildSessionFactory();
        //4 获取连接
        Session session = factory.openSession();
        //5 创建事务
        Transaction transaction = session.beginTransaction();
        //6 开启事务
        transaction.begin();
        
        Stu s1 = (Stu) session.get(Stu.class, 1001);
        System.out.println(s1);

        //7 事务提交
        transaction.commit();
        //8 关闭连接
        session.close();
    }
}

5.2 1对1

创建数据库

CREATE TABLE husband(
   hid INT PRIMARY KEY AUTO_INCREMENT,
   hname VARCHAR(11)
);
INSERT INTO husband VALUES(1,"李先生");
INSERT INTO husband VALUES(2,"高先生");
CREATE TABLE wife(
   wid INT PRIMARY KEY AUTO_INCREMENT,
   wname VARCHAR(11),
   CONSTRAINT fk_091 FOREIGN KEY(wid) REFERENCES husband(hid)
);
INSERT INTO wife VALUES(1,"李太太");
INSERT INTO wife VALUES(2,"高太太");

实体类

public class Husband implements Serializable {
    private Integer hid;
    private String hname;
    //定义引用记录妻子
    private Wife wife;
    ...
}
public class Wife implements Serializable {
    private Integer wid;
    private String wname;
    private  Husband husband;
    ...
}

mapper映射文件

  • Husband.hbm.xml
<?xml version="1.0" encoding="gbk"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd" >
<hibernate-mapping>
    <!-- 指定类名 和 表名 -->
    <class name="sss.entity.Husband" table="husband">
        <!-- 指定主键列对应的属性 -->
        <id name="hid" column="hid" type="int">
            <!-- 自增-->
            <generator class="identity"/>
        </id>
        <property name="hname" column="hname" type="string"/>
        <!--1对1-->
        <one-to-one name="wife" class="sss.entity.Wife"/>

    </class>
</hibernate-mapping>
  • Wife.hbm.xml
<?xml version="1.0" encoding="gbk"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd" >
<hibernate-mapping>
    <!-- 指定类名 和 表名 -->
    <class name="sss.entity.Wife" table="wife">
        <!-- 指定主键列对应的属性 -->
        <id name="wid" column="wid" type="int">
            <!-- 自增-->
            <generator class="identity"/>
        </id>
        <property name="wname" column="wname" type="string"/>
        <!--1对1-->
        <one-to-one name="husband" class="sss.entity.Husband"/>

    </class>
</hibernate-mapping>
  • hibernatepro.xml
<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
        "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
        "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>

    <session-factory>
        <!-- 指定方言 -->
        <property name="dialect">org.hibernate.dialect.MySQLDialect</property>
        <property name="connection.url">jdbc:mysql://localhost:3306/ssr</property>
        <property name="connection.driver_class">com.mysql.jdbc.Driver</property>
        <property name="connection.username">root</property>
        <property name="connection.password">root</property>
        <!-- 是否显示sql语句 -->
        <property name="show_sql">true</property>

        <!-- 导入类与表的映射文件-->
        <mapping resource="sss/entity/Stu.hbm.xml"/>
        <mapping resource="sss/entity/Tea.hbm.xml"/>
        <mapping resource="sss/entity/Husband.hbm.xml"/>
        <mapping resource="sss/entity/Wife.hbm.xml"/>
    </session-factory>
</hibernate-configuration>

测试

import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;
import org.hibernate.classic.Session;
import sss.entity.Husband;
import sss.entity.Wife;

public class TestPro {
    public static void main(String[] args) {
        //1 创建Configration对象 自动读取heibernate的核心配置文件
        Configuration conf = new Configuration();
        //2 读取核心配置文件
        conf.configure("sss/test/hibernatepro.xml");
        //3 通过Configuration创建sessionfactory对象
        SessionFactory factory = conf.buildSessionFactory();
        //4 获取连接
        Session session = factory.openSession();
        //5 创建事务
        Transaction transaction = session.beginTransaction();
        //6 开启事务
        transaction.begin();

        Husband h1 = (Husband) session.get(Husband.class, 1);
        System.out.println(h1+":::"+h1.getWife());

        Wife w1 = (Wife) session.get(Wife.class, 2);
        System.out.println(w1+":::"+w1.getHusband());

        //7 事务提交
        transaction.commit();
        //8 关闭连接
        session.close();
    }
}

5.3 n对n

创建表

CREATE TABLE tab_goods(
   gid INT PRIMARY KEY AUTO_INCREMENT,
   gname VARCHAR(11),
   gprice FLOAT(6,1)
);
INSERT INTO tab_goods VALUE (1,"铅笔",2.1);
INSERT INTO tab_goods VALUE (2,"橡皮",0.5);
INSERT INTO tab_goods VALUE (3,"本子",1.0);

CREATE TABLE tab_order(
   oid INT PRIMARY KEY AUTO_INCREMENT,
   omoney FLOAT(9,1),
   otime DATE
);
INSERT INTO tab_order VALUES(1,10000,'2021-01-01');
INSERT INTO tab_order VALUES(2,2000,'2021-02-01');
INSERT INTO tab_order VALUES(3,300,'2021-03-01');

CREATE TABLE tab_goods_order(
   ooid INT,
   ggid INT,
   PRIMARY KEY(ooid,ggid),
   CONSTRAINT fk_092 FOREIGN KEY(ooid) REFERENCES tab_order(oid),
   CONSTRAINT fk_093 FOREIGN KEY(ggid) REFERENCES tab_goods(gid)   
);
INSERT INTO tab_goods_order VALUES(1,1),(1,2),(1,3);
INSERT INTO tab_goods_order VALUES(2,1),(2,2);
INSERT INTO tab_goods_order VALUES(3,1),(3,3);

实体类

public class Goods implements Serializable {
    private Integer gid;
    private String gname;
    private Float gprice;
    private Set<Order> orderSet;
	......
}
public class Order implements Serializable {
    private Integer oid;
    private Float omoney;
    private Date otime;
    private Set<Goods> goodsSet;
	......
}

映射文件

  • Goods.hbm.xml
<?xml version="1.0" encoding="gbk"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd" >
<hibernate-mapping>
    <!-- 指定类名 和 表名 -->
    <class name="sss.entity.Goods" table="tab_goods">
        <!-- 指定主键列对应的属性 -->
        <id name="gid" column="gid" type="int">
            <!-- 自增-->
            <generator class="identity"/>
        </id>
        <property name="gname" column="gname" type="string"/>
        <property name="gprice" column="gprice" type="float"/>
        <!--n对n-->
        <set name="orderSet" table="tab_goods_order">
            <!--key的column当前表tab_goods在关系表中的外键列-->
            <key column="ggid"/>
            <!--many-to-many的column对方表tab_order在关系表中的外键列-->
            <many-to-many column="ooid" class="sss.entity.Order"/>
        </set>

    </class>
</hibernate-mapping>
  • Order.hbm.xml
<?xml version="1.0" encoding="gbk"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd" >
<hibernate-mapping>
    <!-- 指定类名 和 表名 -->
    <class name="sss.entity.Order" table="tab_order">
        <!-- 指定主键列对应的属性 -->
        <id name="oid" column="oid" type="int">
            <!-- 自增-->
            <generator class="identity"/>
        </id>
        <property name="omoney" column="omoney" type="float"/>
        <property name="otime" column="otime" type="date"/>
        <!--n对n-->
        <set name="goodsSet" table="tab_goods_order">
            <!--key的column当前表tab_order在关系表中的外键列-->
            <key column="ooid"/>
            <!--many-to-many的column对方表tab_goods在关系表中的外键列-->
            <many-to-many column="ggid" class="sss.entity.Goods"/>
        </set>

    </class>
</hibernate-mapping>
  • hibernatepro.xml
<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
        "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
        "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>

    <session-factory>
        <!-- 指定方言 -->
        <property name="dialect">org.hibernate.dialect.MySQLDialect</property>
        <property name="connection.url">jdbc:mysql://localhost:3306/ssr</property>
        <property name="connection.driver_class">com.mysql.jdbc.Driver</property>
        <property name="connection.username">root</property>
        <property name="connection.password">root</property>
        <!-- 是否显示sql语句 -->
        <property name="show_sql">true</property>

        <!-- 导入类与表的映射文件-->
        <mapping resource="sss/entity/Stu.hbm.xml"/>
        <mapping resource="sss/entity/Tea.hbm.xml"/>
        <mapping resource="sss/entity/Husband.hbm.xml"/>
        <mapping resource="sss/entity/Wife.hbm.xml"/>
        <mapping resource="sss/entity/Goods.hbm.xml"/>
        <mapping resource="sss/entity/Order.hbm.xml"/>
    </session-factory>
</hibernate-configuration>

测试

import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;
import org.hibernate.classic.Session;
import sss.entity.Goods;
import sss.entity.Order;

public class TestPro {
    public static void main(String[] args) {
        //1 创建Configration对象 自动读取heibernate的核心配置文件
        Configuration conf = new Configuration();
        //2 读取核心配置文件
        conf.configure("sss/test/hibernatepro.xml");
        //3 通过Configuration创建sessionfactory对象
        SessionFactory factory = conf.buildSessionFactory();
        //4 获取连接
        Session session = factory.openSession();
        //5 创建事务
        Transaction transaction = session.beginTransaction();
        //6 开启事务
        transaction.begin();

        Goods g1 = (Goods) session.get(Goods.class, 2);
        System.out.println(g1 + ":::" + g1.getOrderSet());
        Order o1 = (Order) session.get(Order.class, 3);
        System.out.println(o1 + ":::" + o1.getGoodsSet());

        //7 事务提交
        transaction.commit();
        //8 关闭连接
        session.close();
    }
}

6 hibernate中get和load的区别

  • 相同之处
1 都是通过主键获取一个对象
2 都需要指定对象的类型
  • 不同之处
get和load的区别
1:当对应的主键值不存在时:
	get返回的是null
    load抛出异常:ObjectNotFoundException
2:正常运行时:
	get会立刻发送并执行sql语句 获取对应的结果对象
    load不会立刻发送sql语句 load方法获取的是proxy代理对象
    (此对象类型和id确定但其他属性无值)
    只有当调用代理对象时才发送和执行sql语句
    如果session关闭才第一次调用代理对象会抛出异常:LazyInitializationException

7 属性lazy和cascade

  • lazy:在xml中修改
懒加载:lazy="true" 默认:
	学生关联老师:获取学生时 如果不调用老师 
	学生的老师属性tea赋值的是代理对象:只有id属性
    只有在调用此老师属性时 才执行sql语句
    如果session关闭 才第一次调用此老师属性会报错:LazyInitializationException
立刻加载:lazy="false" 默认:
    学生关联老师:会执行两个sql语句:sql1获取学生 sql2获取学生关联的老师
  • cascade:在xml中修改
cascade="save-update":级联操作:添加或者修改学生时 学生关联的老师也会级联添加/修改
cascade="delete":级联操作:删除学生时 学生关联的老师也会删除
cascade="all":=cascade="save-update"+cascade="delete"
  • 代码测试
Order o1 = new Order(10, 11111f, new Date());
Set<Goods> set = new HashSet<>();
//注意:级联添加时:关联对象不能设置id
set.add(new Goods(null, "袜子1", 11f));
set.add(new Goods(null, "袜子2", 12f));
set.add(new Goods(null, "袜子3", 13f));
o1.setGoodsSet(set);
session.save(o1);
/*
    Hibernate: insert into tab_order (omoney, otime) values (?, ?)
    Hibernate: insert into tab_goods (gname, gprice) values (?, ?)
    Hibernate: insert into tab_goods (gname, gprice) values (?, ?)
    Hibernate: insert into tab_goods (gname, gprice) values (?, ?)
    Hibernate: insert into tab_goods_order (ooid, ggid) values (?, ?)
    Hibernate: insert into tab_goods_order (ooid, ggid) values (?, ?)
    Hibernate: insert into tab_goods_order (ooid, ggid) values (?, ?)
*/

session.delete(session.get(Goods.class,4));
/*
    先查询出所有有关联的表,然后删除
    Hibernate: delete from tab_goods_order where ggid=?
    Hibernate: delete from tab_goods_order where ooid=?
    Hibernate: delete from tab_goods_order where ggid=?
    Hibernate: delete from tab_goods_order where ggid=?
    Hibernate: delete from tab_goods where gid=?
    Hibernate: delete from tab_goods where gid=?
    Hibernate: delete from tab_order where oid=?
    Hibernate: delete from tab_goods where gid=?
*/
  • 注意:级联操作时,关联的对象不能设置id

8 hibernate的检索方式

  • 检索:查询方式

8.1 ognl对象导航:通过对象a来获取关联的对象b

/*
    检索方式:OGNL:通过Stu关联的tea属性来获取对象
    Stu s1 = (Stu) session.get(Stu.class, 1001);
    System.out.println(s1.getTea());
*/

8.2 OID检索方式:通过get/load方法由主键值获取对象

/*
	检索方式:OID:通过get/load方法获取对象
	Stu s2 = (Stu) session.get(Stu.class, 1001);
    System.out.println(s2);
*/

8.3 HQL检索方式:通过Query接口获取对象

/*	
	检索方式:HQL :通过Query接口方式hql(类sql语句:面向对象的sql语句)语句
	idea中 hql中涉及到属性名会编译报错 但不影响执行
	
	*** 执行查找 ***
	Query q1 = session.createQuery("from sss.entity.Stu where sname=?");
	(q1=session.createQuery("from sss.entity.Stu");)
    q1.setParameter(0,"李老师学生1");
    System.out.println(q1.list());
    
    *** 执行修改 ***
    Query q2 = session.createQuery("update sss.entity.Stu set sname=? 
    where sid=?");
    q2.setString(0,"依依").setInteger(1,1001);
    System.out.println(q2.executeUpdate());
    
    *** 执行删除 ***
    Query q3 = session.createQuery("delete from sss.entity.Stu where sid=?");
    q3.setInteger(0,1001);
    System.out.println(q3.executeUpdate());
*/

8.4 QBC检索方式:通过Criteria接口获取对象

/*
    检索方式:QBC:通过Criteria接口 实现完全面向对象方式访问数据库
    参考:https://www.cnblogs.com/lukelook/p/9692429.html
    
    *** 查询所有 ***
    Criteria c1 = session.createCriteria(Stu.class);
    System.out.println(c1.list());
    
    *** 模糊查询 ***
    Criterion s1 = Restrictions.eq("sname", "李老师的学生2");
    Criterion s2 = Restrictions.like("sname", "%1%");
    Criterion s3 = Restrictions.or(s1, s2);
    c1.add(s3);
    System.out.println(c1.list());
    
    *** 分页 ***
	c1.setFirstResult(0);//设置起始行的索引:索引从0开始
    c1.setMaxResults(2);//设置每页记录数
    System.out.println(c1.list());
    (System.out.println(c1.setFirstResult(0).setMaxResults(2).list());)
*/

8.5本地SQL检索方式:通过手写sql查询数据库

/*
	检索方式:本地SQL:通过SQLQuery接口 写sql对数据库进行增删改查
    SQLQuery sql1 = session.createSQLQuery("select * from stu where sid>? and sname=?");
    List<Object[]> list1 = sql1.setInteger(0, 2).setString(1, "郭老师学生1").list();
    for (int i = 0; i <list1.size(); i++) {
        for (int j = 0; j <list1.get(i).length ; j++) {
            System.out.println(list1.get(i)[j]);
        };
    }

    SQLQuery sql2 = session.createSQLQuery("select * from stu where sid>? 
    and sname=?").addEntity(Stu.class);
    List<Stu> list2 = sql2.setInteger(0, 1).setString(1, "郭老师学生1").list();
    for (int i = 0; i <list2.size() ; i++) {
        System.out.println(list2.get(i));
    }	
*/

image

9 hibernate自动创建表

<property name="hibernate.hbm2ddl.auto">create-drop</property>

hibernate.hbm2ddl.auto:通过mapper映射文件自动创建或者修改表
hibernate.hbm2ddl.auto=create:如果表存在先删除表再创建,如果表不存在直接创建
hibernate.hbm2ddl.auto=create-drop:如果表存在先删除表再创建,如果表不存在直接创建 
					   SessionFactory:关闭前会删除创建的表
hibernate.hbm2ddl.auto=udpate:如果表不存在直接创建,表存在使用已有的,列同理
常用:hibernate.hbm2ddl.auto=udpate   

10 hibernate中对象的状态

image

/*
	***对象状态***
	1:瞬时态=游离态:Transient
	通过new创建的对象:此对象和session的数据库中的行无关,
	对对象进行操作不会影响数据库中的行记录
	Student s1=new Student(1,"韩雪","女",66f,true,new Date());
	
	2:持久态:Persistent
	通过load/get/list/iterator/save/saveorupdate等方法获取的对象,
	此对象和sesson数据库中的某行是对应关系
	s1=(Student)session.get(Student.class.1);
	在session关闭前/事务提交前:hibernate会自动判断持久态对象和对应的行数据是否一致
	如果不一致:会自动执行update语句,根据持久态对象的属性值来更改对应的行数据
    List<Student> list1 = session.createQuery("from sss.entity.Student").list();
    for (Student s:list1) {
        if(s.getSex().equals("女")){
            s.setScore(s.getScore()+200);
            System.out.println(1);
        }
    }
    Iterator<Student> it = session.createQuery("from sss.entity.Student").iterate();
    while(it.hasNext()){
        Student next = it.next();
        System.out.println(next);
    }
    System.out.println(it);
    
    3:脱管态:Detached
    当session关闭/清空/事务提交后  
    持久态的对象转换为脱管态:此对象和session数据库行脱离关联关系
    Student s1=new Student("5","韩雪","女",66.6,true,new Date());
    session.evict(s1);//s1转换为脱管态
    session.clear();
    s1.setSex("圣");
    s1.setScore(100.0);
    Iterator<Student> it = session.createQuery("from sss.entity.Student").iterate();
    while(it.hasNext()){
        Student s = it.next();
        if(s.getSex().equals("女")){
            s.setScore(s.getScore()+200);
        }
    }
    System.out.println(it);
	
*/
posted @ 2021-12-07 20:24  RenVei  阅读(68)  评论(0编辑  收藏  举报