用 Hibernate 开发的朋友,是不是都被 XML 配置文件搞得头大过?一个实体类配一个.hbm.xml 文件,字段改一下俩地方都要改,文件堆得像小山似的,找起来都费劲。其实啊,Hibernate 早就支持注解开发了,用注解替代 XML 配置,代码和配置放一块,又清爽又好维护。今天兔子哥就带大家把注解开发吃透,以后跟繁琐的 XML 说拜拜,开发效率直接提一档!
一、先明白:注解开发到底好在哪儿?
估计有朋友会问:“XML 用惯了,为啥非要换注解?” 你要是遇到过这些情况,就知道注解多香了:改个字段名得在实体类和 XML 里两头改,结果漏改一处就报错;项目里 XML 文件比 Java 文件还多,找个配置得翻半天。
注解开发的好处可不止一点点:
- 代码和配置放一块:实体类上直接加注解,字段和配置对应关系一目了然,不用来回切换文件
- 少写重复代码:不用再写一堆 XML 标签,一个注解搞定映射关系
- 容易维护:改配置直接在实体类里改,不用惦记着还有个 XML 文件没更
- 开发效率高:新手不用学复杂的 XML 语法,记几个注解就能上手
刚开始用注解的时候,我也觉得 “这玩意儿能有 XML 靠谱?” 结果用了半个月就彻底真香了 —— 之前维护一个老项目,光 XML 配置文件就有 30 多个,后来用注解重构后,代码量少了一半,找问题也快多了。
二、核心注解大盘点:这些注解你必须会
注解开发的核心就是那几个 “明星注解”,记熟了基本就能应付大部分场景。兔子哥给大家整理了最常用的,一起往下看吧!
1. 实体类基础注解
这几个是给实体类和表做映射的,少了它们可不行:
- @Entity:标在类上,告诉 Hibernate“这是个实体类,要映射到数据库表哦”,忘了加这个注解,运行准报错
- @Table:跟 @Entity 搭配用,指定实体类对应哪个表,比如
@Table(name = "t_user")就是对应 t_user 表,表名和类名不一样时必须加 - @Id:标在字段上,指定这是主键,没有这个注解,Hibernate 找不到主键会一脸懵
- @GeneratedValue:主键生成策略,最常用的是
strategy = GenerationType.IDENTITY,就是数据库自增主键,省得自己写代码生成 ID
举个例子,一个简单的用户实体类注解是这样的:
java
@Entity@Table(name = "t_user")public class User {@Id@GeneratedValue(strategy = GenerationType.IDENTITY)private Integer id;private String username; // 字段名和表字段一致,不用额外注解private Integer age;// getter、setter别忘了写}2. 字段映射注解
字段和数据库列不一样时,就得靠这些注解调优了:
- @Column:指定字段对应的数据表列,比如
@Column(name = "user_name", length = 50),意思是对应表的 user_name 列,长度 50 - @Transient:标在字段上,告诉 Hibernate “这个字段不用映射到数据库”,比如计算出来的临时属性就用它
- @Temporal:处理日期类型,比如
@Temporal(TemporalType.DATE)对应数据库的 DATE 类型,存年月日
上次有个朋友字段名是 “userName”,数据库列是 “user_name”,没加 @Column 结果查不到数据,加上
@Column(name = "user_name")立马就好了,这小细节可得注意。3. 关联关系注解
多表关联是重点也是难点,这几个注解得吃透:
- @OneToMany:一对多关系,比如用户和订单是一对多,在 User 类里加
@OneToMany(mappedBy = "user"),mappedBy 指定由多的一方维护关系 - @ManyToOne:多对一关系,在 Order 类里加
@ManyToOne,配合@JoinColumn(name = "user_id")指定外键列 - @ManyToMany:多对多关系,比如用户和角色,得配中间表,一般用
@JoinTable指定中间表信息
兔子哥建议,写关联关系时先画个 ER 图,想清楚谁是一谁是多,不然注解加反了容易出问题。
三、实战步骤:用注解开发一个小项目
光说不练假把式,咱们一步步来做个用户 - 订单的小项目,感受下注解开发的爽快感。
1. 建实体类,加注解
先写 User 实体类,一对多关联订单:
java
@Entity@Table(name = "t_user")public class User {@Id@GeneratedValue(strategy = GenerationType.IDENTITY)private Integer id;@Column(name = "username", length = 50, nullable = false)private String username;@OneToMany(mappedBy = "user", cascade = CascadeType.ALL)private List<Order> orders = new ArrayList<>();// getter、setter}再写 Order 实体类,多对一关联用户:
java
@Entity@Table(name = "t_order")public class Order {@Id@GeneratedValue(strategy = GenerationType.IDENTITY)private Integer id;@Column(name = "order_no")private String orderNo;@ManyToOne@JoinColumn(name = "user_id") // 外键列private User user;// getter、setter}2. 配核心配置,开启注解
在 hibernate.cfg.xml 里加一行,告诉 Hibernate 用注解映射:
xml
<mapping class="com.example.entity.User"/><mapping class="com.example.entity.Order"/>不用再写.hbm.xml 文件了,是不是清爽多了?
3. 写测试代码,跑起来看看
用 Session 保存用户和订单,测试关联关系:
java
Session session = sessionFactory.openSession();session.beginTransaction();User user = new User();user.setUsername("兔子哥");Order order = new Order();order.setOrderNo("20240520001");order.setUser(user); // 关联用户user.getOrders().add(order);session.save(user); // 因为配了cascade,会级联保存订单session.getTransaction().commit();session.close();运行完去数据库看看,t_user 和 t_order 表都有数据,外键也关联上了,完美!
四、常见坑点:这些错误别再犯了
刚开始用注解,踩坑太正常了,兔子哥总结了几个高频错误,帮你避避坑:
1. 忘了加 @Id 注解
实体类没标 @Id,Hibernate 找不到主键,会报 “no identifier specified for entity” 错误。我刚开始就老忘,后来养成习惯,建实体类先加 @Id。
2. 关联关系没设 mappedBy
一对多关联时两边都配 @JoinColumn,会导致生成两个外键列。记住:多的一方加 @JoinColumn,一的一方用 mappedBy 指定由多的一方维护,比如 User 里的
mappedBy = "user"。3. 字段名和表字段对不上
实体类字段是 “userName”,表字段是 “user_name”,又没加 @Column,查询时会报 “unknown column” 错误。要么统一命名,要么加 @Column 指定对应关系。
五、兔子哥的实战心得
用注解开发 Hibernate 快三年了,真心觉得这玩意儿比 XML 舒服太多。代码里直接能看到映射关系,改字段不用翻好几个文件,团队协作时新人也容易上手。
但也得注意规范,别瞎用注解。比如不是所有字段都要加 @Column,字段名和表字段一致时完全可以省略;关联关系的 cascade 别随便用 ALL,不然删个用户把订单全删了就麻烦了。
刚开始可能记不住那么多注解,没关系,多写几个小例子,用着用着就熟了。建议大家从新项目开始用注解,老项目可以慢慢重构,体验一下这种 “代码即配置” 的爽快感。
希望这篇教程能帮你搞定注解开发,以后跟繁琐的 XML 说再见,开发效率 up up!
标签: GenerationType.IDENTITY GeneratedValue
版权声明:除非特别标注,否则均为本站原创文章,转载时请以链接形式注明文章出处。
还木有评论哦,快来抢沙发吧~