Hibernate(15)Hibernate中如何定义一个实体的主键?

在Hibernate中,定义实体的主键是非常重要的步骤。主键用于唯一标识数据库表中的每一行记录。我们通常使用注解来定义实体的主键。

以下是一些常见的注解来定义实体的主键:

  1. @Id:标记字段为实体的主键。
  2. @GeneratedValue:指定主键的生成策略。
  3. @Column:指定数据库表中列的详细信息。

主键生成策略

@GeneratedValue注解有几种常用的生成策略:

  1. AUTO:默认策略,JPA提供的主键生成方式,依据底层数据库的不同自动选择合适的生成策略。
  2. IDENTITY:采用数据库的自增长字段,如MySQL的AUTO_INCREMENT。
  3. SEQUENCE:使用数据库的序列,主要适用于Oracle数据库。
  4. TABLE:通过一张表来生成主键,该表通常用于模拟序列。

示例代码

下面是一个完整的示例,通过不同的生成策略来定义实体的主键。

配置文件 hibernate.cfg.xml

xml 复制代码
<!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="hibernate.connection.driver_class">com.mysql.cj.jdbc.Driver</property>
        <property name="hibernate.connection.url">jdbc:mysql://localhost:3306/your_database</property>
        <property name="hibernate.connection.username">your_username</property>
        <property name="hibernate.connection.password">your_password</property>

        <!-- Hibernate 属性配置 -->
        <property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
        <property name="hibernate.show_sql">true</property>
        <property name="hibernate.format_sql">true</property>
        <property name="hibernate.hbm2ddl.auto">update</property>

        <!-- 映射类配置 -->
        <mapping class="com.example.domain.Student"/>
    </session-factory>
</hibernate-configuration>

HibernateUtil 类

java 复制代码
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;

public class HibernateUtil {
    private static final SessionFactory sessionFactory;

    static {
        try {
            // 从配置文件创建SessionFactory
            sessionFactory = new Configuration().configure("hibernate.cfg.xml").buildSessionFactory();
        } catch (Throwable ex) {
            // 记录启动失败的错误
            System.err.println("Initial SessionFactory creation failed." + ex);
            throw new ExceptionInInitializerError(ex);
        }
    }

    public static SessionFactory getSessionFactory() {
        return sessionFactory;
    }
}

实体类 Student

使用 AUTO 生成策略
java 复制代码
package com.example.domain;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;

@Entity
public class Student {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;
    
    private String name;
    private int age;

    public Student() {}

    public Student(String name, int age) {
        this.name = name;
        this.age = age;
    }

    // getters 和 setters
    public Long getId() {
        return id;
    }

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

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
}
使用 IDENTITY 生成策略
java 复制代码
package com.example.domain;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;

@Entity
public class Student {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    
    private String name;
    private int age;

    public Student() {}

    public Student(String name, int age) {
        this.name = name;
        this.age = age;
    }

    // getters 和 setters
    public Long getId() {
        return id;
    }

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

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
}
使用 SEQUENCE 生成策略

如果使用SEQUENCE策略,需要在数据库中创建一个序列。

sql 复制代码
CREATE SEQUENCE student_seq START WITH 1 INCREMENT BY 1;
java 复制代码
package com.example.domain;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.SequenceGenerator;

@Entity
public class Student {
    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "student_seq")
    @SequenceGenerator(name = "student_seq", sequenceName = "student_seq", allocationSize = 1)
    private Long id;
    
    private String name;
    private int age;

    public Student() {}

    public Student(String name, int age) {
        this.name = name;
        this.age = age;
    }

    // getters 和 setters
    public Long getId() {
        return id;
    }

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

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
}
使用 TABLE 生成策略

如果使用TABLE策略,需要在数据库中创建一个主键生成表。

sql 复制代码
CREATE TABLE hibernate_sequences (
    sequence_name VARCHAR(50) NOT NULL,
    sequence_next_val BIGINT NOT NULL,
    PRIMARY KEY (sequence_name)
);

INSERT INTO hibernate_sequences (sequence_name, sequence_next_val) VALUES ('student_seq', 1);
java 复制代码
package com.example.domain;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.TableGenerator;

@Entity
public class Student {
    @Id
    @GeneratedValue(strategy = GenerationType.TABLE, generator = "student_gen")
    @TableGenerator(name = "student_gen", table = "hibernate_sequences", pkColumnName = "sequence_name",
                    valueColumnName = "sequence_next_val", pkColumnValue = "student_seq", allocationSize = 1)
    private Long id;
    
    private String name;
    private int age;

    public Student() {}

    public Student(String name, int age) {
        this.name = name;
        this.age = age;
    }

    // getters 和 setters
    public Long getId() {
        return id;
    }

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

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
}

事务管理

在进行数据库操作时,需要开启事务,并在操作完成后提交事务。如果操作失败,则回滚事务以确保数据一致性。

java 复制代码
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;

public class HibernateExample {
    public static void main(String[] args) {
        // 获取SessionFactory
        SessionFactory sessionFactory = HibernateUtil.getSessionFactory();
        Session session = null;
        Transaction transaction = null;

        // 向数据库添加一个对象
        try {
            session = sessionFactory.openSession();
            transaction = session.beginTransaction();

            Student student = new Student("John Doe", 20);
            session.save(student);

            transaction.commit();
        } catch (Exception e) {
            if (transaction != null) {
                transaction.rollback();
            }
            e.printStackTrace();
        } finally {
            if (session != null) {
                session.close();
            }
        }

        // 关闭SessionFactory
        sessionFactory.close();
    }
}

总结

通过以上示例,可以看出Hibernate提供了多种策略来生成实体的主键,包括AUTOIDENTITYSEQUENCETABLE。不同的策略适用于不同的数据库和场景。理解这些主键生成策略,并在实际项目中正确应用,可以有效地管理数据库表中的主键。

相关推荐
前端Hardy29 分钟前
一个时代结束了:npm 终于对 install 脚本下手了
前端·javascript·后端
damaoyou30 分钟前
Cog3DRangeImagePlaneEstimatorTool完全指南
后端
Nturmoils1 小时前
分页别写太顺手,LIMIT 背后还有排序和边界
数据库·后端
神奇小汤圆1 小时前
国产版“Codex”初体验,智谱ZCode很强啊!
后端
站大爷IP1 小时前
Python里的“赋值”到底是什么意思?
后端
鹅城剑仙1 小时前
Spring Boot 微服务架构设计与最佳实践
spring boot·后端·微服务
Full Stack Developme2 小时前
Spring Integration 教程
java·后端·spring
爱勇宝2 小时前
AI 时代,前端工程师的话语权正在下降?
前端·后端
kymjs张涛2 小时前
一个月,纯VibeCoding,全平台云笔记APP
前端·javascript·后端
星辰_mya3 小时前
autowired和resource区别
java·后端·spring·架构·原理