27.Hibernate的入门到提高(IDEA+Maven)

一.hibernate的简介

  1. Hibernate是数据持久化工具,是一个开源的ORM(对象关系映射)解决方案
  2. Hibernate底层封装了JDBC,简化数据库操作

  3. Hibernate面向对象,不需要编写SQL语句,支持多种数据库

优点

  1. Hibernate功能强大,与JDBC相比,代码量大大减少,提高持久化代码的开发速度,降低维护成本
  2. Hibernate支持面向对象编程,不需要编写SQL语句
  3. 可移植性好
  4. Hibernate框架开源免费

缺点

  1. 不适合以数据为中心大量使用存储过程的应用
  2. 大规模的批量插入、修改和删除不适合用Hibernate框架

二.创建项目进行CRUD操作

1.新增操作(使用opensession方式)

1.1. 创建maven项目,导入hibernate、mysql、jdbc依赖

  <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jdbc</artifactId>
            <version>5.3.3</version>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.42</version>
            <scope>compile</scope>
        </dependency>
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-core</artifactId>
            <version>5.4.27.Final</version>
            <scope>compile</scope>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>compile</scope>
        </dependency>

1.2. 创建hibernate.cfg.xml配置文件,放在resource目录下

<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
        "-//Hibernate/Hibernate Configuration DTD//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.username">root</property>
        <property  name="hibernate.connection.password">root</property>
        <property name="hibernate.connection.url">jdbc:mysql://localhost:3306/ceshi?useUnicode=true&amp;characterEncoding=UTF-8</property>
        <!-- 使用MySQL的innodb引擎 支持事务和外键;myISAM引擎不支持事务和外键-->
        <property name="hibernate.dialect.storage_engine">innodb</property>
    </session-factory>
</hibernate-configuration>

1.3. 创建test数据库及表user,添加持久类User并提供toString方法

public class User {
    private Integer id;
    private String username;
    private String password;

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }
    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", username='" + username + '\'' +
                ", password='" + password + '\'' +
                '}';
    }
}

1.4. 在resource/mapper/目录下添加User.hbm.xml

<?xml version="1.0"?>
<!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属性指定实体类
    name属性:表示持久化类的全限定名
    table属性:表示持久化类对应数据库的表名,类与表名一致时,可省略-->
    <class name="com.entity.User" table="user" >
    <!-- id:Id标签表示持久化类的OID(对象主键属性)和表的主键映射
       name:填写该实体类的属性名称(严格区分大小写)
       column:填写数据库表中的列名称(不区分大小写),当列名与实体类的属性名相同时可以省略
        type:填写该属性的数据类型
    -->
    <id name="id" column="id" type="java.lang.Integer">
    <!-- generator:用于指定主键的生成策略
        class元素:用于指定主键的生成策略
        Param标签:用于传递参数
        assigned:主键由程序提供(非自增)默认的生成策略
        increment:主键自增,支持long、int、short类型主键,先查询表中最大的id值,加1后使用 select max(deptno) from dept
        identity:自动增长,支持标识列的数据库才能使用,例如:mysql、SQLServer
        sequence:序列,Oracle等支持序列的数据库可以使用
        native:自动增长,但会根据数据库的不同自动选择
        uuid:根据uuid算法生成uuid字符串做主键
     -->
        <generator class="increment"/>
    </id>
    <!-- property:定义持久化类的属性和数据库表中的字段的对应关系
           name属性:表示持久化类属性的名称,和属性的get方法匹配
           type属性:持久化类属性的类型
           column属性:持久化类属性对应到表中的字段名称(填数据表中属性的字段)
    -->
        <!--column:用于指定其父元素代表的持久化类属性对应表中的列名称
            name:表示字段名称
            length:表示字段长度
            not-null设定是都不能为null,设置为true表示不能为null
        -->
    <property name="username" type="java.lang.String" column="username"/>
        <property name="password" type="java.lang.String">
            <column name="password"/>
        </property>
    </class>

</hibernate-mapping>

1.5. 在hibernate.cfg.xml中引入User.hbm.xml

1.6. 创建类测试,使用openSeesion必须关闭session

public class TestUser {
    @Test
    public  void testAdd() {
        //1.读取hibernate配置文件
        Configuration configuration = new Configuration().configure();
        //2.创建SessionFactory对象
        SessionFactory sessionFactory = configuration.buildSessionFactory();
        //3.创建Session对象(打开session)
        //注意:通过openSession()方法打开Session必须关闭session
        Session session = sessionFactory.openSession();
        //4.开启事务
        Transaction transaction = session.beginTransaction();
        try {
        //5.准备数据
            User user = new User();
            user.setUsername("小李");
            user.setPassword("123");
            //6.持久化数据
            session.save(user);
            //7.提交事务
            transaction.commit();
        } catch (HibernateException e) {
            e.printStackTrace();
            //8.回滚事务
            transaction.rollback();
        } finally {
            //9.关闭资源
            session.close();
        }
    }
}

1.7. 查询一下结果

1.新增操作(使用getCurrentSession方式)

1.1.在hibernate.cfg.xml中配置线程上下文,必须配置

1.2. 总结

2.根据主键查询

2.1. 封装工具类

public class HibernateUtil {
    //会话工厂对象
    private static SessionFactory sessionFactory; 

    //使用静态代码读取配置文件
    static {
        //1.读取并解析配置文件
        Configuration configuration = new Configuration().configure();
        //2.创建会话工厂对象
        sessionFactory = configuration.buildSessionFactory();
    }

    public static Session getSession() {
        //return sessionFactory.openSession();//需要关闭资源
        return sessionFactory.getCurrentSession();//需要在hibernate配置文件中配置线程上下文
    }


    public static void closeSession(Session session) {
        //判断Session是否为空或Session是否处于打开状态
        if (session != null && session.isOpen()) {
            session.close();//关闭session 40
        }
            //关闭工厂对象
            sessionFactory.close();
        }
 }

2.2. 使用get()方法查询

1.根据主键查询,主键不存在返回null
2.立即加载:无论是否使用到该对象,都会去查询数据库,效率低
3.获取Session对象,有两种情况,分别是:
    1.通过openSession()方式获取,则不需要加入事务
    2.通过getCurrentSession()方式获取,则查询需要加入事务

2.3. 编写代码

public class TestUser {
    @Test
    public void testGetDept() {
        //1.获取Session
        Session session = HibernateUtil.getSession();
        //2.开启事务
        Transaction transaction = session.beginTransaction();
        //3.根据主键查询
        User user = session.get(User.class, 1);
        System.out.println(user);
        //4.关闭资源
        HibernateUtil.closeSession(session);
    }
}

 2.4. 使用load()方法查询

1.根据主键查询,主键不存在会报错,发生ObjectNotFoundException(找不到对象)
2.延迟加载(懒加载):如果没有使用到该对象,则不会查询数据库

2.5. 编写代码测试

public class TestUser {
    public static void main(String[] args){
    //1.获取Session
    Session session = HibernateUtil.getSession();
    //2.开启事务
    Transaction transaction = session.beginTransaction();
    //3.根据主键查询
    User user = session.load(User.class, 2);
    System.out.println(user);
    //4.关闭资源
        HibernateUtil.closeSession(session);
    }
}

3. 根据主键修改信息

3.1. 传统方式-如果某个属性没有被赋值,那么原来的属性会被清空

3.2.这里我们没有设置password的值,发现数据库的属性值被清空了

3.3. 先查询后修改-没有赋值的属性不会被清空,保留原来的值,会发出两条SQL语句,分别是查询和修改

3.4. 我们先将id为1的password赋值为555

3.5. 测试一下

3.6. 查询一下数据库信息,发现其他没有赋值的属性没有被清空

4.根据主键删除信息

4.1.再次查看数据库的信息-成功删除

三.Hibernate中java对象的三种状态

1.java对象的三种状态

2.三种状态之间的转变

3.脏机制和刷新缓存机制

4.持久化方法

4.1. saveOrUpdate()

新增:没有指定主键的情况下会执行新增操作

修改:当指定的主键是存在的,执行修改操作,若主键不存在,会触发异常

生成策略:用此方法主键生成策略不能是assigned

4.2. 查询数据库信息,我们将修改id为2的信息

4.3.指定主键,测试

4.4. 查询数据信息,发现已经被修改

4.5. 测试不指定主键方式

4.6. 查询数据库信息,发现新增了一条数据

4.7. merge()方法

新增-当没有指定主键或者主键不存在时(先根据之间查询,对象为空则新增)执行新增操作

修改-执行的主键是存在的执行修改操作

四.Hibernate关联映射

1.表之间的关系

1.1. hibernate表关系分析步骤

第一步:首先确定两张表的关系

第二步:在数据库中实现两张表的关系

第三步:在实体类中描述出两个实体类的关系

第四步:配置出实体类的数据库表的关系映射(重点)

2.单向多对一关联

2.1. 需求:单项添加员工,配置多对一(多个员工对应一个部门)

2.2. 环境准备:

2.2.1. Department实体类

public class Department {
    private Integer deptNo;
    private String deptName; 
    private String location;

    public Integer getDeptNo() {
        return deptNo;
    }

    public void setDeptNo(Integer deptNo) {
        this.deptNo = deptNo;
    }

    public String getDeptName() {
        return deptName;
    }

    public void setDeptName(String deptName) {
        this.deptName = deptName;
    }

    public String getLocation() {
        return location;
    }

    public void setLocation(String location) {
        this.location = location;
    }

   
}

2.2.2. Enployee实体类

public class Employee {
    private Integer empNo;//员工编号
    private String empName;//员工姓名
    private String job;//职位
    private Double salary;//薪资
    private Integer deptNo;//部门编号
    private Date hireDate;//入职时间

    public Integer getEmpNo() {
        return empNo;
    }

    public void setEmpNo(Integer empNo) {
        this.empNo = empNo;
    }

    public String getEmpName() {
        return empName;
    }

    public void setEmpName(String empName) {
        this.empName = empName;
    }

    public String getJob() {
        return job;
    }

    public void setJob(String job) {
        this.job = job;
    }

    public Double getSalary() {
        return salary;
    }

    public void setSalary(Double salary) {
        this.salary = salary;
    }

    public Integer getDeptNo() {
        return deptNo;
    }

    public void setDeptNo(Integer deptNo) {
        this.deptNo = deptNo;
    }

    public Date getHireDate() {
        return hireDate;
    }

    public void setHireDate(Date hireDate) {
        this.hireDate = hireDate;
    }

    
}

2.2.3. 准备Department.hbm.xml

<?xml version="1.0"?> <!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.entity.Department" table="department" >
        <id name="deptNo" column="deptNo" type="java.lang.Integer">
            <generator class="increment"/>
        </id>
        <property name="deptName" type="java.lang.String" column="deptName"/>
        <property name="location" type="java.lang.String"> 
            <column name="location"/>
        </property> 
    </class>
</hibernate-mapping>

2.3.4. 准备Employee.hbm.xml

<?xml version="1.0"?> <!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.entity.Employee" table="employee" >
        <id name="empNo" column="empNo" type="java.lang.Integer"> 
            <generator class="increment"/> 
        </id> 
        <property name="empName" type="java.lang.String" column="empName"/> 
        <property name="job" type="java.lang.String" column="job"/> 
        <property name="salary" type="java.lang.Double" column="salary"/> 
        <property name="deptNo" type="java.lang.Integer" column="deptNo"/> 
        <property name="hireDate" type="java.util.Date" column="hireDate"/> 
    </class>
</hibernate-mapping>

2.3.5. 导入映射文件到hibernate.cfg.xml中

2.3.6. 修改员工类-将原来外键属性deptNo修改成类类型Department的属性:将deptNo变成department属性,别忘了把deptNo的getter和setter方法删除

2.3.7. 映射文件Employee.hbm.xml中部门编号配置修改成以下配置:

2.3.8. 在部门表中添加一行数据,写代码测试一下

public class TestManyToOne {
    public static void main(String[] args) {
        //获取Session
         Session session = HibernateUtil.getSession();
         //开启事务
        Transaction transaction = session.beginTransaction();
        try {
            //创建对象
             Employee employee = new Employee();
             employee.setEmpName("汤姆");
             employee.setHireDate(new Date());
             employee.setJob("经理");
             employee.setSalary(10000D);
             //获取部门信息
            Department department = session.get(Department.class,1);
            employee.setDepartment(department);//设置员工所在的部门
            // 保存员工
            session.save(employee);
            //提交事务
            transaction.commit();
        } catch (Exception e) {
            e.printStackTrace();
            //回滚
            transaction.rollback();
        }finally {
            //关闭资源
            HibernateUtil.closeSession(session);
        }
    }
}

2.3.9. 查询数据库信息,使用关联查询-成功

猜你喜欢

转载自blog.csdn.net/suchaoh/article/details/113723344