Hibernate框架简介②

本文详细介绍Hibernate ORM框架的应用实践,包括模型类的规范定义、映射文件的解析与配置、环境初始化流程,以及如何通过工具类简化开发过程。此外,还探讨了对象的状态变化及其在不同场景下的转换。

模型类的规范:

1 必须有默认构造方法, 查询时把数据表中的一条数据映射成一个对象时需要使用默认构造器来创建对象

2 必须提供一个OID, 作为对象的主键(就是userId了)

3 属性必须私有化封装, 就是提供set跟get方法

4 不要使用final来修饰模型类中的成员, 如果是final修饰在后续要讲到的延迟加载无法实现

5 最好使用封装类,

    基本类型 int  默认值是0

    包装类    Integer  默认值是null

    假如该值本来没有填写, 由于是基本类型, 系统将默认值0代替它而不是null, 因而你无法判断是填写了0还是默认值

 

映射文件详解:

<?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">

<!-- 
    package: 指定当前映射文件的实体类的包路径
 -->
<hibernate-mapping package="com.rl.hiber.model">

    <!-- 
        class: 实体类名
        table: 对应数据库表名
     -->
    <class name="User" table="t_user">
    <!--
                设置主键 
        generator: 主键的生成策略(后续再介绍)
     -->
        <id name="userId" column="user_id">
        <!-- 
            identity(常用): 使用mysql的自增策略, 这种自增没有并发问题, 前提是model的oid是数值类型, 所映射的column也是数值类型
            native(比较智能): 根据数据库的方言来翻译, 自动翻译成identity(mysql)或sequence(oracle)
            uuid(有大量使用, 由于没有锁机制, 性能较高): 没有并发问题, 按照自己的策略生成一个32位的字符串, 主键不重复, 前提是主键(oid)必须是字符串类型
            assigned: 手动指定id(在实际项目中不使用)
            increment: 主键自动自增(在实际项目中不去使用, 因为有并发安全性问题)
         -->
            <generator class="identity"></generator>
        </id>
        <!-- 
            name: 实体类的属性名
            column: 数据库表中的列名
            可选属性:
            type: 设置字段类型(一般不用设置)
            length: 设置字段长度
            not-null: 设置非空约束
            unique-key: 设置唯一键约束
         -->
        <property name="uname" column="uname"></property>
        <property name="gender" column="gender"></property>
        <property name="birthday" column="birthday"></property>
    </class>
</hibernate-mapping>

环境初始化详解:

Configuration: 创建Hibernate配置对象, 读取hibernate.cfg.xml文件初始化环境

ServiceRegistry: 注册hibernate属性信息

SessionFactory: Session工厂类, 这个类是一个重量级的对象, 线程安全的, 负责创建Session, 这个对象在服务器启动的时候创建一个即可

Session: 是一次和数据库的会话, 但是不一定是一次连接, Session给我们提供了很多操作数据库的方法, 操作的是对象, 影响的是数据库

Transaction: 事务对象, 控制我们Session对象数据库操作的事务

 

封装一个工具类以简化代码:

HibernateUtil类:

package com.rl.hiber.utils;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.hibernate.cfg.Configuration;
import org.hibernate.service.ServiceRegistry;

public class HibernateUtil {

    private static SessionFactory sf;
    
    //静态块
    static {
        
        Configuration cfg = new Configuration();
        cfg.configure("hibernate.cfg.xml");
        ServiceRegistry sr = new StandardServiceRegistryBuilder().applySettings(cfg.getProperties()).build();
        sf = cfg.buildSessionFactory(sr);
    }
    
    public static SessionFactory getSessionFactory() {
        return sf;
    }
    
    public static Session getSessoion() {
        return sf.openSession();
    }
    
    public static void closeSession(Session session) {
        session.close();
    }
    
    public static void closeResource(Session session) {
        session.close();
        sf.close();
    }
}

修改测试代码:

package com.rl.hiber.test;

import java.util.Date;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.hibernate.cfg.Configuration;
import org.hibernate.service.ServiceRegistry;
import org.junit.Test;

import com.rl.hiber.model.User;
import com.rl.hiber.utils.HibernateUtil;

public class TestHibernate {

    
    
    @Test
    public void test2() {
        
        //获取session
        Session session = HibernateUtil.getSessoion();
        //需要先开启事务
        Transaction tx = session.beginTransaction();
        try {
            //创建对象
            User user = new User();
            user.setUname("zhangsan");
            user.setGender(1);
            user.setBirthday(new Date());
            //保存user对象到数据库中
            session.save(user);
            //事务提交
            tx.commit();
        } catch (Exception e) {
            e.printStackTrace();
            tx.rollback();
        }finally {
            HibernateUtil.closeResource(session);
        }
    }
}

数据库结果与之前一致:

hibernate的对象的三种状态

瞬时对象(TransientObjects): 

    刚new出来的对象, 在数据库中没有相应的记录, 也没有被session管理起来的对象

持久化对象(PersistentObjects): 

    在数据库中有相应的记录并且被session管理来的对象

脱管对象(DetachObjects):

    在数据库中有相应的记录, 但没有被session管理起来的对象

这三种状态可以相互转换

    当瞬时对象执行save()或者update()时会转换为持久化对象

    当执行get()或load()或iterator()时从数据库中查询上来的对象就是持久化对象, 当持久化对象执行delete()时则转换为瞬时对象

    当持久化对象执行evict()或close()或clear()时则转换为脱管对象

    当脱管对象执行save()或update()时则转换为持久化对象

    当脱管对象执行delete()时则转换为瞬时对象

 

由于其中的某些转换较为简单, 我只贴出一些我认为需要记忆的点

脱管对象转换为持久化对象, 一旦成为脱管对象了, 那么久意味着该对象只存在于数据库中, 此时session已经关闭了, 要想重新转换为持久化对象, 则必须新创建出一个session, 请看测试代码:

package com.rl.hiber.test;

import java.util.Date;

import org.hibernate.Session;
import org.hibernate.Transaction;
import org.junit.Test;

import com.rl.hiber.model.User;
import com.rl.hiber.utils.HibernateUtil;

public class TestHibernate {

    
    @Test
    public void test3() {
        Session session = HibernateUtil.getSessoion();
        Transaction tx = session.beginTransaction();
        User user = new User();
        try {
            user.setUname("张三");
            user.setBirthday(new Date());
            user.setGender(1);
            session.save(user);
            tx.commit();
        } catch (Exception e) {
            e.printStackTrace();
            tx.rollback();
        }finally {
            //关闭session, 此时将对象user变成脱管对象
            HibernateUtil.closeSession(session);
        }
        
        //重新创建一个session
        Session session2 = HibernateUtil.getSessoion();
        Transaction tx2 = session2.beginTransaction();
        try {
            user.setUname("李四");
            session2.update(user);
            tx2.commit();
        } catch (Exception e) {
            e.printStackTrace();
            tx2.rollback();
        }finally {
            //关闭session2
            HibernateUtil.closeResource(session2);
        }
    }
}

此时就将user对象转成了持久化对象(既被session管理, 又存在于数据库中)

 

通过查询获得持久化对象, 请看测试代码:

package com.rl.hiber.test;

import java.util.Date;

import org.hibernate.Session;
import org.hibernate.Transaction;
import org.junit.Test;

import com.rl.hiber.model.User;
import com.rl.hiber.utils.HibernateUtil;

public class TestHibernate {

   
    
    @Test
    public void test2() {
        
        Session session = HibernateUtil.getSessoion();
        try {
            User user = (User) session.get(User.class, 1);
            System.out.println(user);
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            HibernateUtil.closeResource(session);
        }
    }
    
    
}

tip: 查询并不需要开事务

 

这里先贴上load()的查询, 后续会讲解它们的区别(与延迟加载有关)

测试代码:

package com.rl.hiber.test;

import java.util.Date;

import org.hibernate.Session;
import org.hibernate.Transaction;
import org.junit.Test;

import com.rl.hiber.model.User;
import com.rl.hiber.utils.HibernateUtil;

public class TestHibernate {

    
    
    @Test
    public void test4() {
        Session session = HibernateUtil.getSessoion();
        try {
            User user = (User) session.load(User.class, 1);
            System.out.println(user);
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            HibernateUtil.closeResource(session);
        }
    }
    
   
}

get()和load()方法查询出来的对象都是持久化对象

 

<think>我们正在创建一个项目并添加Hibernate进行配置。根据引用内容,Hibernate是一个ORM框架,用于映射Java对象到数据库表。配置Hibernate需要核心配置文件和映射信息。以下是步骤: 1. 创建项目(假设使用Maven) 2. 添加Hibernate依赖 3. 创建Hibernate配置文件(hibernate.cfg.xml) 4. 创建实体类(POJO) 5. 创建实体类的映射文件(或使用注解) 由于引用[2]提到配置文件可以是属性文件或XML文件,这里我们使用更常见的hibernate.cfg.xml。 详细步骤: 步骤1:创建Maven项目 可以使用IDE(如IntelliJ IDEA或Eclipse)创建一个Maven项目。 步骤2:添加Hibernate依赖 在pom.xml中添加Hibernate核心依赖和数据库驱动。例如,使用Hibernate 5.6.x和MySQL 8.0驱动: ```xml <dependencies> <!-- Hibernate core --> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-core</artifactId> <version>5.6.15.Final</version> </dependency> <!-- MySQL connector --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.33</version> </dependency> </dependencies> ``` 步骤3:创建Hibernate配置文件(hibernate.cfg.xml) 在resources目录下创建hibernate.cfg.xml,配置数据库连接和基本属性。 ```xml <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd"> <hibernate-configuration> <session-factory> <!-- 数据库连接设置 --> <property name="hibernate.connection.driver_class">com.mysql.cj.jdbc.Driver</property> <property name="hibernate.connection.url">jdbc:mysql://localhost:3306/your_database?useSSL=false&serverTimezone=UTC</property> <property name="hibernate.connection.username">root</property> <property name="hibernate.connection.password">your_password</property> <!-- JDBC连接池(使用内置) --> <property name="hibernate.connection.pool_size">1</property> <!-- SQL方言 --> <property name="hibernate.dialect">org.hibernate.dialect.MySQL8Dialect</property> <!-- 在控制台输出SQL语句 --> <property name="hibernate.show_sql">true</property> <property name="hibernate.format_sql">true</property> <!-- 自动创建/更新表结构 --> <property name="hibernate.hbm2ddl.auto">update</property> <!-- 映射文件或带注解的实体类的位置 --> <!-- 如果使用映射文件,则添加以下行 --> <!-- <mapping resource="com/example/User.hbm.xml"/> --> <!-- 如果使用注解,则添加实体类 --> <!-- <mapping class="com.example.User"/> --> </session-factory> </hibernate-configuration> ``` 步骤4:创建实体类(例如User) 使用注解方式(推荐)或XML映射文件。这里使用注解。 ```java package com.example; import javax.persistence.*; @Entity @Table(name = "user") public class User { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; private String name; private String email; // 必须有无参构造函数 public User() { } // Getter和Setter // ... 省略 } ``` 步骤5:在配置文件中指定实体类 在hibernate.cfg.xml中添加: ```xml <mapping class="com.example.User"/> ``` 步骤6:测试Hibernate 编写一个简单的测试类,保存一个User对象。 ```java import org.hibernate.Session; import org.hibernate.SessionFactory; import org.hibernate.cfg.Configuration; public class Main { public static void main(String[] args) { // 创建SessionFactory SessionFactory sessionFactory = new Configuration() .configure("hibernate.cfg.xml") // 默认加载类路径下的hibernate.cfg.xml .buildSessionFactory(); // 创建Session try (Session session = sessionFactory.openSession()) { // 开始事务 session.beginTransaction(); // 创建User对象 User user = new User(); user.setName("John Doe"); user.setEmail("john.doe@example.com"); // 保存User session.save(user); // 提交事务 session.getTransaction().commit(); } catch (Exception e) { e.printStackTrace(); } finally { sessionFactory.close(); } } } ``` 注意事项: - 确保数据库存在(在配置文件中指定的数据库),并且用户有权限。 - hibernate.hbm2ddl.auto属性设置为update,表示如果表不存在则创建,存在则更新结构(根据实体类)。在生产环境中应谨慎使用。 以上步骤完成了Hibernate项目的搭建和基本配置。 相关问题: 1. Hibernate中如何配置多对一关系? 2. Hibernate的SessionFactory和Session有什么区别? 3. 如何配置Hibernate使用连接池(如C3P0)? 4. Hibernate的缓存机制是什么? 5. 如何优化Hibernate的性能? </think> ### 建立项目并配置 Hibernate 的完整指南 #### 一、创建项目基础结构 1. **使用 Maven 创建项目** ```bash mvn archetype:generate -DgroupId=com.example -DartifactId=hibernate-demo -DarchetypeArtifactId=maven-archetype-quickstart -DinteractiveMode=false ``` 2. **项目结构** ``` hibernate-demo ├── src │ ├── main │ │ ├── java │ │ ├── resources <-- 配置文件目录 │ │ └── webapp │ └── test └── pom.xml ``` #### 、添加 Hibernate 依赖 在 `pom.xml` 中添加: ```xml <dependencies> <!-- Hibernate 核心 --> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-core</artifactId> <version>5.6.15.Final</version> </dependency> <!-- MySQL 驱动 --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.33</version> </dependency> </dependencies> ``` #### 三、配置 Hibernate 1. **创建配置文件 `hibernate.cfg.xml`** 位置:`src/main/resources/hibernate.cfg.xml` ```xml <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd"> <hibernate-configuration> <session-factory> <!-- 数据库连接 --> <property name="hibernate.connection.driver_class">com.mysql.cj.jdbc.Driver</property> <property name="hibernate.connection.url">jdbc:mysql://localhost:3306/your_db</property> <property name="hibernate.connection.username">root</property> <property name="hibernate.connection.password">your_password</property> <!-- 方言设置 --> <property name="hibernate.dialect">org.hibernate.dialect.MySQL8Dialect</property> <!-- 开发环境配置 --> <property name="hibernate.show_sql">true</property> <!-- 显示SQL --> <property name="hibernate.format_sql">true</property> <!-- 格式化SQL --> <property name="hibernate.hbm2ddl.auto">update</property> <!-- 自动更新表结构 --> <!-- 实体类映射 --> <mapping class="com.example.model.User"/> </session-factory> </hibernate-configuration> ``` 2. **关键配置说明** - `hbm2ddl.auto` 选项: - `update`:自动更新表结构(开发环境推荐) - `create`:每次重建表 - `validate`:验证表结构是否匹配 - `none`:禁用自动更新 - 数据库方言需按版本选择: - MySQL 5.x:`MySQL5Dialect` - MySQL 8.x:`MySQL8Dialect` #### 四、创建实体类 ```java package com.example.model; import javax.persistence.*; @Entity @Table(name = "users") // 映射到数据库表 public class User { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) // 自增主键 private Long id; @Column(name = "user_name", nullable = false, length = 50) private String name; @Column(unique = true) private String email; // 必须有无参构造函数 public User() {} // Getter/Setter 方法 // ... } ``` #### 五、测试 Hibernate 操作 ```java public class HibernateDemo { public static void main(String[] args) { // 1. 加载配置 Configuration config = new Configuration().configure(); // 2. 创建 SessionFactory try (SessionFactory sessionFactory = config.buildSessionFactory(); Session session = sessionFactory.openSession()) { // 3. 开启事务 session.beginTransaction(); // 4. 创建并保存对象 User user = new User(); user.setName("张三"); user.setEmail("zhangsan@example.com"); session.save(user); // 执行INSERT // 5. 提交事务 session.getTransaction().commit(); // 6. 查询验证 User savedUser = session.get(User.class, user.getId()); System.out.println("保存的用户: " + savedUser.getName()); } } } ``` #### 六、验证结果 1. **控制台输出**: ``` Hibernate: insert into users (email, name) values (?, ?) 保存的用户: 张三 ``` 2. **数据库检查**: ```sql SELECT * FROM users; ``` #### 七、配置优化建议 1. **生产环境配置**: - 移除 `hibernate.show_sql` 避免敏感信息泄露 - 将 `hbm2ddl.auto` 改为 `validate` - 添加连接池配置(如 HikariCP) 2. **连接池配置示例**: ```xml <property name="hibernate.c3p0.min_size">5</property> <property name="hibernate.c3p0.max_size">20</property> <property name="hibernate.c3p0.timeout">1800</property> ``` --- ### 相关问题 1. Hibernate 中 `@OneToMany` 和 `@ManyToOne` 注解如何配置关联关系?[^1] 2. 如何优化 Hibernate 的 N+1 查询问题?[^2] 3. Hibernate 的缓存机制有哪几种?各自适用什么场景?[^2] 4. 如何在 Spring Boot 项目中集成 Hibernate? 5. Hibernate 的悲观锁和乐观锁实现方式有什么区别?[^2]
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值