Hibernate与javax.persistence概述
javax.persistence包是J2EE原生包,其中提供了JPA 规范的核心注解和接口,例如:
@Entity、@Table、@Column等注解(用于实体类映射)EntityManager、Query等接口(用于数据库操作)@EntityListener、@PrePersist、@PostPersist、@PreUpdate、@PostUpdate、@PreRemove、@PostRemove、@PostLoad等用于监听器和回调相关注解
但是javax.persistence不实现这些接口,而是由业务提供方实现,例如Hibernate
Hibernate核心思想是将 Java 对象(POJO)映射到数据库表,将对象属性映射到数据库表的列。开发者可以直接操作 Java 对象,而 Hibernate 负责将这些操作转换为底层的 SQL 语句(如 INSERT, UPDATE, SELECT, DELETE)并执行,从而极大地简化了数据库持久层的开发
其核心概念包括:
Configuration(配置):负责读取 Hibernate 配置文件(hibernate.cfg.xml)和映射文件(*.hbm.xml)或注解,并用于创建SessionFactory。SessionFactory(会话工厂):一个重量级、线程安全的对象。它是数据库的编译后的内存镜像。一个应用通常只有一个SessionFactory。它是生成Session的工厂。Session(会话):一个轻量级、非线程安全的对象。它代表了应用程序与数据库之间的一次交互(一个工作单元)。它封装了 JDBC 的Connection,是进行 CRUD 操作、管理事务和获取查询对象的主要接口。核心中的核心。Transaction(事务):用于管理事务的接口,是对 JDBC 事务或 JTA 事务的抽象。Query/Criteria(查询):用于执行数据库查询的接口
Hibernate项目实战
创建Entity
@Entity
@Table(name = "t_user")
@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(name = "username")
private String username;
private String email;
}创建Hibernate配置文件
<?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="connection.driver_class">com.mysql.cj.jdbc.Driver</property>
<property name="connection.url">jdbc:mysql://localhost:3306/test_db</property>
<property name="connection.username">root</property>
<property name="connection.password">password</property>
<!-- JDBC 连接池(使用 Hibernate 内置的) -->
<property name="connection.pool_size">5</property>
<!-- 数据库方言 -->
<property name="dialect">org.hibernate.dialect.MySQL8Dialect</property>
<!-- 在控制台输出 SQL -->
<property name="show_sql">true</property>
<!-- 可选:格式化 SQL -->
<property name="format_sql">true</property>
<!-- DDL 自动创建/更新表 -->
<property name="hbm2ddl.auto">update</property>
<!-- 注解方式注册实体类 -->
<mapping class="com.example.entity.User"/>
</session-factory>
</hibernate-configuration>编写CRUD操作
public class UserDao {
public void saveUser(User user) {
// 1. 获取 SessionFactory
SessionFactory sessionFactory = new Configuration().configure().buildSessionFactory();
// 2. 获取 Session
Session session = sessionFactory.openSession();
// 3. 开启事务
Transaction tx = session.beginTransaction();
try {
// 4. 执行操作
session.save(user);
// 5. 提交事务
tx.commit();
} catch (Exception e) {
// 6. 回滚事务
if (tx != null) tx.rollback();
e.printStackTrace();
} finally {
// 7. 关闭 Session
session.close();
}
}
public User getUserById(Long id) {
try (Session session = HibernateUtil.getSessionFactory().openSession()) {
return session.get(User.class, id);
}
}
// ... 其他 update, delete, query 方法
}源码简读
Configuration
configure
public Configuration configure() throws HibernateException {
return configure( StandardServiceRegistryBuilder.DEFAULT_CFG_RESOURCE_NAME );
}这里即调用的默认位置
public static final String DEFAULT_CFG_RESOURCE_NAME = "hibernate.cfg.xml";public Configuration configure(String resource) throws HibernateException {
standardServiceRegistryBuilder.configure( resource );
// todo : still need to have StandardServiceRegistryBuilder handle the "other cfg.xml" elements.
// currently it just reads the config properties
properties.putAll( standardServiceRegistryBuilder.getSettings() );
return this;
}对xml中的配置内容进行配置
buildSessionFactory
public SessionFactory buildSessionFactory() throws HibernateException {
log.debug( "Building session factory using internal StandardServiceRegistryBuilder" );
standardServiceRegistryBuilder.applySettings( properties );
return buildSessionFactory( standardServiceRegistryBuilder.build() );
}在buildSessionFactory中完成配置,生成SessionFactory
SessionFactory
openSession
创建Session
public Session openSession() throws HibernateException {
//The defaultSessionOpenOptions can't be used in some cases; for example when using a TenantIdentifierResolver.
if ( this.defaultSessionOpenOptions != null ) {
return this.defaultSessionOpenOptions.openSession();
}
else {
return this.withOptions().openSession();
}
}Session/SessionImpl
是Hibernate的核心
看这个接口提供的方法是直接操作数据库的,例如
Serializable save(Object object);
void saveOrUpdate(Object object);
void delete(Object object);基于SessionImpl看它的设计理念
成员变量
private transient ActionQueue actionQueue;
private LockOptions lockOptions;
private transient LoadEvent loadEvent; //cached LoadEvent instance
private transient TransactionObserver transactionObserver;save
public Serializable save(String entityName, Object object) throws HibernateException {
return fireSave( new SaveOrUpdateEvent( entityName, object, this ) );
}执行在fireSave方法,同时将传进来的entity包装成了一个SaveOrUpdateEvent
public class SaveOrUpdateEvent extends AbstractEvent {
private Object object;
private Serializable requestedId;
private String entityName;
private Object entity;
private EntityEntry entry;
private Serializable resultId;这个包装类实际上就是为了存储一些entity相关的信息
fireSave
private Serializable fireSave(final SaveOrUpdateEvent event) {
checkOpen();
checkTransactionSynchStatus();
checkNoUnresolvedActionsBeforeOperation();
fastSessionServices.eventListenerGroup_SAVE.fireEventOnEachListener( event, SaveOrUpdateEventListener::onSaveOrUpdate );
checkNoUnresolvedActionsAfterOperation();
return event.getResultId();
}执行操作
Hibernate集成springboot
hibernate集成springboot是比较简单的
只要添加springboot相关依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>就会自动引入hibernate相关依赖
在springboot场景下
在 application.properties 或 application.yml 中配置数据源和 JPA 属性:
# 数据源配置
spring.datasource.url=jdbc:mysql://localhost:3306/test_db?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=UTC
spring.datasource.username=root
spring.datasource.password=password
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
# JPA 配置
spring.jpa.database-platform=org.hibernate.dialect.MySQL8Dialect
spring.jpa.hibernate.ddl-auto=update
spring.jpa.show-sql=true
spring.jpa.properties.hibernate.format_sql=true然后基于springboot提供的repository层接口就可以直接使用
public interface UserRepository extends JpaRepository<User, Long> {
// 可以根据方法名自动生成查询,也可以使用 @Query 注解自定义查询
User findByUsername(String username);
}@Service
public class UserService {
@Autowired
private UserRepository userRepository;
public User saveUser(User user) {
return userRepository.save(user);
}
public User findUserById(Long id) {
return userRepository.findById(id).orElse(null);
}
// 其他业务方法...
}
评论区