以前用的QQ公众号登录不进去了,求助。QQ是3153823749

hibernate注解单向一对多关系 - ITeye问答
做一个文章发布系统,信息是一个类,自定义属性是一个类,大体意思就是,一条文章对象会包含多个自定义属相,比如说一条信息,有精华、加粗、头条等属性,在传统的做法中,文章是一个表,属性配置是一个表,还需一个关联表,用来维护对应关系,现采用了Hibernate注解,因属性配置是相对对立的,类似字典表,基本不需要维护,所以在文章中加入一对多关系,生成的表共有三张,但在维护关系表中,只有文章编号与自定义属性编号,这样当添加第一条数剧是没有问题,添加第二条就会出错,约束出错,hibernate一对多单关联,如何能生成 id articleId customattrsId类似于这样的呢?
而还是articleId customattrsId
麻烦大家给看看,或提供个思路
目前还没有答案
已解决问题
未解决问题MySql(1)
在hibernate中,通常配置对象关系映射关系有两种,一种是基于xml的方式,另一种是基于annotation的注解方式,熟话说,萝卜青菜,可有所爱,每个人都有自己喜欢的配置方式,我在试了这两种方式以后,发现使用annotation的方式可以更简介,所以这里就简单记录下通过annotation来配置各种映射关系,在hibernate4以后已经将annotation的jar包集成进来了,如果使用hibernate3的版本就需要引入annotation的jar包。
一、单对象操作
@Entity  ---&如果我们当前这个bean要设置成实体对象,就需要加上Entity这个注解
@Table(name=&t_user&)  ----&设置数据库的表名
public class User
&&& private S
&&& private S
&&& private D
&&& private Date registerD
@Column(name=&register_date&)  ---&Column中的name属性对应了数据库的该字段名字,里面还有其他属性,例如length,nullable等等
&&& public DategetRegisterDate()
&&&&&&& return registerD
&&& public void setRegisterDate(DateregisterDate)
&&&&&&& this.registerDate =registerD
@Id  ---&定义为数据库的主键ID  (建议不要在属性上引入注解,因为属性是private的,如果引入注解会破坏其封装特性,所以建议在getter方法上加入注解)
&&& @GeneratedValue  ----&ID的生成策略为自动生成
&&& public int getId()
&&& public void setId(int id)
&&&&&&& this.id =
&............
最后只需要在hibernate.cfg.xml文件里面将该实体类加进去即可:
&!-- 基于annotation的配置 --&
&&&&&&& &mappingclass=&com.xiaoluo.bean.User&/&
&!-- 基于hbm.xml配置文件 --&
&&&&&&& &mappingresource=&com/xiaoluo/bean/User.hbm.xml&/&
这样我们就可以写测试类来进行我们的CRUD操作了。
二、一对多的映射(one-to-many)
这里我们定义了两个实体类,一个是ClassRoom,一个是Student,这两者是一对多的关联关系。
ClassRoom类:
@Table(name=&t_classroom&)
public class ClassRoom
&&& private String classN
&&& private Set&Student&
&&& public ClassRoom()
&&&&&&& students = newHashSet&Student&();
&&& public void addStudent(Studentstudent)
&&&&&&& students.add(student);
&&& @GeneratedValue
&&& public int getId()
publicvoid setId(int id)
&&&&&&& this.id =
publicString getClassName()
&&&&&&& return classN
publicvoid setClassName(String className)
&&&&&&& this.className =classN
@OneToMany(mappedBy=&room&)  ---&OneToMany指定了一对多的关系,mappedBy=&room&指定了由多的那一方来维护关联关系,mappedBy指的是多的一方对1的这一方的依赖的属性,(注意:如果没有指定由谁来维护关联关系,则系统会给我们创建一张中间表)
&& &@LazyCollection(LazyCollectionOption.EXTRA)  ---&LazyCollection属性设置成EXTRA指定了当如果查询数据的个数时候,只会发出一条 count(*)的语句,提高性能
&&& public Set&Student&getStudents()
publicvoid setStudents(Set&Student& students)
&&&&&&& this.students =
Student类:
@Table(name=&t_student&)
public class Student
&&& private S
&&& private ClassR
&&& @ManyToOne(fetch=FetchType.LAZY)  ---&ManyToOne指定了多对一的关系,fetch=FetchType.LAZY属性表示在多的那一方通过延迟加载的方式加载对象(默认不是延迟加载)
&& &@JoinColumn(name=&rid&)  ---&通过JoinColumn 的name属性指定了外键的名称 rid (注意:如果我们不通过JoinColum来指定外键的名称,系统会给我们声明一个名称)
&&& public ClassRoom getRoom()
&&& public void setRoom(ClassRoomroom)
&&&&&&& this.room =
&&& @GeneratedValue
&&& public int getId()
&&& public void setId(int id)
&&&&&&& this.id =
&&& public String getName()
&&& public void setName(Stringname)
&&&&&&& this.name =
&&& public int getAge()
&&& public void setAge(intage)
&&&&&&& this.age =
三、一对一映射(One-to-One)
一对一关系这里定义了一个Person对象以及一个IDCard对象
Person类:
@Table(name=&t_person&)
public class Person
&&& private S
&&& private IDC
&& &@OneToOne(mappedBy=&person&)  ---&指定了OneToOne的关联关系,mappedBy同样指定由对方来进行维护关联关系
&&& public IDCard getCard()
&&& public void setCard(IDCardcard)
&&&&&&& this.card =
&&& @GeneratedValue
&&& public int getId()
&&& public void setId(int id)
&&&&&&& this.id =
&&& public String getName()
&&& public void setName(Stringname)
&&&&&&& this.name =
IDCard类:
@Table(name=&t_id_card&)
public class IDCard
&&& private S
&&& private P
&&& @GeneratedValue
&&& public int getId()
&&& public void setId(int id)
&&&&&&& this.id =
&&& public String getNo()
&&& public void setNo(String no)
&&&&&&& this.no =
&&& @OneToOne  ---&OnetoOne指定了一对一的关联关系,一对一中随便指定一方来维护映射关系,这里选择IDCard来进行维护
&&& @JoinColumn(name=&pid&)  ---&指定外键的名字pid
&&& public Person getPerson()
&&& public void setPerson(Personperson)
&&&&&&& this.person =
注意:在判断到底是谁维护关联关系时,可以通过查看外键,哪个实体类定义了外键,哪个类就负责维护关联关系。
四、Many-to-Many映射(多对多映射关系)
多对多这里通常有两种处理方式,一种是通过建立一张中间表,然后由任一一个多的一方来维护关联关系,另一种就是将多对多拆分成两个一对多的关联关系
1.通过中间表由任一一个多的一方来维护关联关系
Teacher类:
@Table(name=&t_teacher&)
public class Teacher
&&& private S
&&& private Set&Course&
&&& public Teacher()
&&&&&&& courses = newHashSet&Course&();
&&& public void addCourse(Coursecourse)
&&&&&&& courses.add(course);
&&& @GeneratedValue
&&& public int getId()
&&& public void setId(int id)
&&&&&&& this.id =
&&& public String getName()
&&& public void setName(Stringname)
&&&&&&& this.name =
&& &@ManyToMany(mappedBy=&teachers&)  ---&表示由Course那一方来进行维护
&&& public Set&Course&getCourses()
&&& public voidsetCourses(Set&Course& courses)
&&&&&&& this.courses =
Course类:
@Table(name=&t_course&)
public class Course
&&& private S
&&& private Set&Teacher&
&&& public Course()
&&&&&&& teachers = newHashSet&Teacher&();
&&& public void addTeacher(Teacherteacher)
&&&&&&& teachers.add(teacher);
&&& @ManyToMany   ---&ManyToMany指定多对多的关联关系
&&& @JoinTable(name=&t_teacher_course&,joinColumns={ @JoinColumn(name=&cid&)},
&&& inverseJoinColumns={ @JoinColumn(name= &tid&) })  ---&因为多对多之间会通过一张中间表来维护两表直接的关系,所以通过 JoinTable这个注解来声明,name就是指定了中间表的名字,JoinColumns是一个 @JoinColumn类型的数组,表示的是我这方在对方中的外键名称,我方是Course,所以在对方外键的名称就是 rid,inverseJoinColumns也是一个@JoinColumn类型的数组,表示的是对方在我这放中的外键名称,对方是Teacher,所以在我方外键的名称就是
&&& publicSet&Teacher& getTeachers()
publicvoid setTeachers(Set&Teacher& teachers)
&&&&&&& this.teachers =
&&& @GeneratedValue
&&& public int getId()
publicvoid setId(int id)
&&&&&&& this.id =
publicString getName()
publicvoid setName(String name)
&&&&&&& this.name =
2.将Many-to-Many拆分成两个One-to-Many的映射(Admin、Role、AdminRole)
@Table(name=&t_admin&)
public class Admin
&&& private S
&&& private Set&AdminRole&
&&& public Admin()
&&&&&&& ars = newHashSet&AdminRole&();
&&& public void add(AdminRolear)
&&&&&&& ars.add(ar);
&&& @GeneratedValue
&&& public int getId()
&&& public void setId(int id)
&&&&&&& this.id =
&&& public String getName()
&&& public void setName(Stringname)
&&&&&&& this.name =
&&&@OneToMany(mappedBy=&admin&)  ---&OneToMany关联到了AdminRole这个类,由AdminRole这个类来维护多对一的关系,mappedBy=&admin&
&&&@LazyCollection(LazyCollectionOption.EXTRA)
&&& public Set&AdminRole&getArs()
&&& public voidsetArs(Set&AdminRole& ars)
&&&&&&& this.ars =
@Table(name=&t_role&)
public class Role
&&& private S
&&& private Set&AdminRole&
&&& public Role()
&&&&&&& ars = newHashSet&AdminRole&();
&&& public void add(AdminRolear)
&&&&&&& ars.add(ar);
&&& @GeneratedValue
&&& public int getId()
&&& public void setId(int id)
&&&&&&& this.id =
&&& public String getName()
&&& public void setName(Stringname)
&&&&&&& this.name =
&&& @OneToMany(mappedBy=&role&)  ---&OneToMany指定了由AdminRole这个类来维护多对一的关联关系,mappedBy=&role&
&&&@LazyCollection(LazyCollectionOption.EXTRA)
&&& public Set&AdminRole&getArs()
&&& public voidsetArs(Set&AdminRole& ars)
&&&&&&& this.ars =
AdminRole类:
@Table(name=&t_admin_role&)
public class AdminRole
&&& private S
&&& private A
&&& private R
&&& @GeneratedValue
&&& public int getId()
&&& public void setId(int id)
&&&&&&& this.id =
&&& public String getName()
&&& public void setName(Stringname)
&&&&&&& this.name =
&&& @ManyToOne  ---&ManyToOne关联到Admin
&&&@JoinColumn(name=&aid&)
&&& public Admin getAdmin()
&&& public void setAdmin(Adminadmin)
&&&&&&& this.admin =
&&& @ManyToOne  ---&
&&&@JoinColumn(name=&rid&)
&&& public Role getRole()
&&& public void setRole(Rolerole)
&&&&&&& this.role =
小技巧:通过hibernate来进行插入操作的时候,不管是一对多、一对一还是多对多,都只需要记住一点,在哪个实体类声明了外键,就由哪个类来维护关系,在保存数据时,总是先保存的是没有维护关联关系的那一方的数据,后保存维护了关联关系的那一方的数据,如:
Personp = new Person();
&&&&&&&&&&&p.setName(&xiaoluo&);
&&&&&&&&&&& session.save(p);
&&&&&&&&&&&
&&&&&&&&&&& IDCard card = newIDCard();
&&&&&&&&&&&card.setNo(&&);
&&&&&&&&&&& card.setPerson(p);
&&&&&&&&&&& session.save(card);
以上就是对hibernateannotation注解方式来配置映射关系的一些总结。
PS:注解要么全部写在字段上,
要么全部写在getter方法上
如果在API中需要JSON化对象,则应该
在get/set方法中加入@JsonIgnore 以防止
无限递归造成的程序报错
@Table(name=&t_teacher&)
public class Teacher
&&& private S
&&& private Set&Course&
&&& public Teacher()
&&&&&&& courses = newHashSet&Course&();
&&& public void addCourse(Coursecourse)
&&&&&&& courses.add(course);
&&& @GeneratedValue
&&& public int getId()
&&& public void setId(int id)
&&&&&&& this.id =
&&& public String getName()
&&& public void setName(Stringname)
&&&&&&& this.name =
@JsonIgnore
&& &@ManyToMany(mappedBy=&teachers&)  ---&表示由Course那一方来进行维护
&&& public Set&Course&getCourses()
@JsonIgnore
&&& public void setCourses(Set&Course&courses)
&&&&&&& this.courses =
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:8582次
排名:千里之外
原创:12篇
(8)(1)(9)(3)2495人阅读
javaweb(65)
hibernate(15)
在上一篇文章里,我们从端方向一端建立关联关系,完成了从文章到作者的关联关系建立,但在实际的博客网站中,用户肯定还需要获取自己所写的文章,这时可以建立用户(一)对文章(多)的单向关联映射。
先来看我们的一方配置实例
package com.zeng.
import java.util.S
import javax.persistence.CascadeT
import javax.persistence.E
import javax.persistence.FetchT
import javax.persistence.GeneratedV
import javax.persistence.GenerationT
import javax.persistence.Id;
import javax.persistence.OneToM
import javax.persistence.T
@Table(name = "t_user")
public class User {
@GeneratedValue(strategy = GenerationType.AUTO)
@OneToMany(cascade = CascadeType.ALL,fetch = FetchType.LAZY,mappedBy = "user",targetEntity = Article.class,orphanRemoval = true)
private Set&Article&
public String getName() {
public void setName(String name) {
this.name =
public Integer getId() {
public void setId(Integer id) {
public Set&Article& getArticles() {
public void setArticles(Set&Article& articles) {
this.articles =
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((id == null) ? 0 : id.hashCode());
result = prime * result + ((name == null) ? 0 : name.hashCode());
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
User other = (User)
if (id == null) {
if (other.id != null)
return false;
} else if (!id.equals(other.id))
return false;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
return true;
下面是我们对应的多方配置
package com.zeng.
import javax.persistence.E
import javax.persistence.GeneratedV
import javax.persistence.GenerationT
import javax.persistence.Id;
import javax.persistence.T
@Table(name = "t_article1")
public class Article {
@GeneratedValue(strategy = GenerationType.AUTO)
public Integer getId() {
public void setId(Integer id) {
public String getContent() {
public void setContent(String content) {
this.content =
根据这些配置,我们来编写测试方法:
package com.zeng.
import java.util.HashS
import java.util.S
import org.hibernate.S
import org.hibernate.SessionF
import org.hibernate.T
import org.junit.A
import org.junit.AfterC
import org.junit.B
import org.junit.BeforeC
import org.junit.T
import org.springframework.context.ApplicationC
import org.springframework.context.support.ClassPathXmlApplicationC
import com.zeng.model.A
import com.zeng.model.U
public class Test2 {
private ApplicationC
private SessionFactory sessionF
private Tra
@BeforeClass
public static void before(){
public void setup(){
ac = new ClassPathXmlApplicationContext("spring-datasource.xml");
sessionFactory = (SessionFactory) ac.getBean("sessionFactory");
session = sessionFactory.openSession();
transaction = session.beginTransaction();
public void test2(){
User user = new User();
user.setName("oneObject");
Set&Article& articles = new HashSet&Article&();
for(int i = 0 ; i & 3;i ++){
Article article = new Article();
article.setContent("moreContent" + i) ;
articles.add(article);
user.setArticles(articles);
session.save(user);
public void teardown(){
if(transaction.isActive()){
session.clear();
session.close();
sessionFactory.close();
public void after(){
执行测试方法,我们会看到控制台打印下列sql语句:
Hibernate: insert into t_user1 (name) values (?)
Hibernate: insert into t_article1 (content) values (?)
Hibernate: insert into t_article1 (content) values (?)
Hibernate: insert into t_article1 (content) values (?)
Hibernate: insert into t_user1_t_article1 (t_user1_id, articles_id) values (?, ?)
Hibernate: insert into t_user1_t_article1 (t_user1_id, articles_id) values (?, ?)
Hibernate: insert into t_user1_t_article1 (t_user1_id, articles_id) values (?, ?)
在前四句,我们看到在保存user对象时,级联保存了我们的文章对象,最后面三条信息又是什么?原来在我们没有设置@JoinColumn(具体使用方法请参考我的上篇文章)。那么在一对多的关联配置中,hibernate会默认帮我们生成中间表来完成两者的映射关系,查询数据库,我们会发现
mysql& select * from t_user1_t_article1;
+————+————-+
| t_user1_id | articles_id |
+————+————-+
+————+————-+
3 rows in set (0.00 sec)
确实是通过中间表,将用户和文章关联起来了。
这时进行级联删除测试:
User user = (User) session.get(User.class, 1);
session.delete(user);
&我们会得到打印信息:
Hibernate: delete from t_user1_t_article1 where t_user1_id=?
Hibernate: delete from t_article1 where id=?
Hibernate: delete from t_article1 where id=?
Hibernate: delete from t_article1 where id=?
Hibernate: delete from t_user1 where id=?
可见,它的删除顺序是&font color=red&先清楚中间表数据-&再删除多方文章4数据-&最后清楚一方用户数据&/font&
如果我们不像使用中间表,而想像上一篇配置多对一关联那样,在文章表生成user_id,我们就要一方配置@JoinColumn属性,对应属性的实例如下:
@OneToMany(cascade = CascadeType.ALL,fetch = FetchType.LAZY,targetEntity = Article.class,orphanRemoval = true
@JoinColumn(name = "user_id"
private Set&Article& articles
&div class="se-preview-section-delimiter"&&/div&
修改对应表名,让hibernate重新在数据库中生成表,此时再运行我们的测试方法,会看到:
Hibernate: insert into t_user2 (name) values (?)
Hibernate: insert into t_article2 (content) values (?)
Hibernate: insert into t_article2 (content) values (?)
Hibernate: insert into t_article2 (content) values
Hibernate: update t_article2 set user_id=? where id=?
Hibernate: update t_article2 set user_id=? where id=?
Hibernate: update t_article2 set user_id=? where id=?
此时我们会看到,最后三行换成了更新我们的表属性值。从这里我们看出为了更新aritlce表中user_id对应值,我们额外使用多了三条数据,这是很不值的,会额外消耗数据库的性能,有没方法使得在插入文章表的同时插入user_id的值呢?查看hibernate源码,我们会发现这是因为user作为主动方,它处理关联对象时必须通过update来完成,如果我们想取消update,应该将user放弃主动,让另一方(多方)去维护,这又涉及到我们的一对多、多对一双向关联了,我们在下一篇文章再具体解决这一问题。
这个时候我们来测试级联删除:
User user = (User) session.get(User.class, 1);
session.delete(user);
&div class="se-preview-section-delimiter"&&/div&
会得到如下打印信息:
Hibernate: update t_article2 set user_id=null where user_id=?
Hibernate: delete from t_article2 where id=?
Hibernate: delete from t_article2 where id=?
Hibernate: delete from t_article2 where id=?
Hibernate: delete from t_user2 where id=?
注意到,它的删除顺序是:清除用户表和文章表的关联关系(这又是因为用户表作为主动方,它必须通过此方法来维护关联关系-&然后清除多方文章信息-&最后才删除我们的一方用户
上面我们基本完成了我们的测试工作,下面我们对配置属性加以分析:
1. 相对于上一篇我们提到的ManyToOne属性,OneToMany独有的属性有:mapperBy和orphanRemoval,mpperBy是指放弃维护级联关系,具体我们在双向关联中再详细分析,这里比较独特的属性是orphanRemoval
表面意思是去除孤儿,当一方不再关联多方某一实体A时,自动从数据库中删除A。下面来看实例测试,假如我们先将其设为false
@OneToMany(cascade = CascadeType.ALL,fetch = FetchType.LAZY,targetEntity = Article.class,orphanRemoval = false)
@JoinColumn(name = "user_id")
private Set&Article&
&div class="se-preview-section-delimiter"&&/div&
先看看我们数据库的初始记录信息:
+—-+———–+
| id | name
+—-+———–+
2 | oneObject |
+—-+———–+
1 row in set (0.00 sec)
mysql& select * from t_article2;
+—-+————–+———+
| id | content
| user_id |
+—-+————–+———+
6 | moreContent0 |
5 | moreContent1 |
4 | moreContent2 |
+—-+————–+———+
3 rows in set (0.00 sec)
接着开始我们的测试:
User user = (User) session.get(User.class,2);
Article article = user.getArticles().iterator().next();
user.getArticles().remove(article);
session.update(user);
&div class="se-preview-section-delimiter"&&/div&
运行测试代码,我们会看到控制台仅输出一条sql语句:
Hibernate: update t_article2 set user_id=null where user_id=? and id=?
查询数据库,此时变成:
mysql& select * from t_article2;
+—-+————–+———+
| id | content
| user_id |
+—-+————–+———+
6 | moreContent0 |
5 | moreContent1 |
4 | moreContent2 |
+—-+————–+———+
3 rows in set (0.00 sec)
现在我们先恢复测试前的数据:
mysql& update t_article2 set user_id = 2 where id = 4;
然后再将对应注解里的orphanRemoval设为true
@OneToMany(cascade = CascadeType.ALL,fetch = FetchType.LAZY,targetEntity = Article.class,orphanRemoval = true)
@JoinColumn(name = "user_id")
private Set&Article&
&div class="se-preview-section-delimiter"&&/div&
再次运行我们的测试代码,控制台输出:
Hibernate: update t_article2 set user_id=null where user_id=? and id=?
Hibernate: delete from t_article2 where id=?
我们的文章记录就对应被删除了,这就是去除“孤儿”的含义,在实际开发中,正如我们的身份证总是从属于某个人的,如果失去这种从属关系,身份证就没有意义而可以去除了。
2. @JoinTable
在默认不使用@JoinColumn时,多对一关联中hibernate会为我们自动生成中间表,但如果我们像自己来配置中间表,就可以使用@JoinTable注解。它的实例配置如下:
@OneToMany(cascade = CascadeType.ALL,fetch = FetchType.LAZY,targetEntity = Article.class,orphanRemoval = true)
@JoinTable(name = "t_user_articles",inverseJoinColumns = {@JoinColumn(name = "article_id")},joinColumns = {@JoinColumn(name = "article_id")})
private Set&Article&
&div class="se-preview-section-delimiter"&&/div&
1. name为创建的中间表名称。
2. inverseJoinColumns指向对方的表,在这里指多方的表。
3. joinColumns指向自己的表,即一方的表,这些指向都是通过主键映射来完成的。
运行我们的测试代码:
User user = new User();
user.setName("oneObject");
Set&Article& articles = new HashSet&Article&();
for(int i = 0 ; i & 3;i ++){
Article article = new Article();
article.setContent("moreContent" + i) ;
articles.add(article);
user.setArticles(articles);
session.save(user);
&div class="se-preview-section-delimiter"&&/div&
会发现我们的用户、文章对应关系都在中间表中建立起来了:
mysql& select * from t_user_
+———+————+
| user_id | article_id |
+———+————+
+———+————+
3 rows in set (0.00 sec)
使用中间表的好处是对原来两张表的结构不对造成任何影响。尤其是在一些老项目中我们可以不修改既定的表结构(事实上在一个项目古老庞大到一定程度就很难去改)、以不侵入原来表的方式构建出一种更清淅更易管理的关系。当然缺点是我们的我们需要维护多一张表,一旦中间表多了,维护起来会愈加麻烦。但综合来看,我们显然更推荐用中间表的方式来完成配置。
3. eqauls和hashCode方法
在我们开始配置一对多的一方时,我们通过Set来和多方建立关系,其中提到的一点是可以防止多方相同对象出现。这个相同对应我们数据库中就是某些属性列相同,比如:对于Article,如果id和content在两条记录中都一样,我们就可以认为两条记录是一致的,因此会自动去重那么我们来判断它们的重复关系呢?这个时候就要通过重写hashCode和equals方法了。
示例如下:
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
User other = (User)
if (id == null) {
if (other.id != null)
return false;
} else if (!id.equals(other.id))
return false;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
return true;
一般来说,我们重写equal方法就能判断两个对象是否相等了,为什么还要重写hashCode方法呢?主要是考虑到效率的问题,对于equals方法,当比较规则比较复杂的话就会比较耗时了,而hashCode为每一个对象生成一个散列码(通过一种神秘的算法,一般为关键属性乘以一个质数),避免了比较慢的运算。不过我们不能因为快就单凭hash码来判断两个对象是否相等,因为hashCode并不能保证能为每一个不同的对象生成唯一的散列码,所以可能会有两个hash码相同,但对象确实不一致的情况。不过我们知道的是如果连hash码都不一致,那两个对象肯定是不一致的。根据此思路,我们可以很好地理解在java内部,是如何判断两个对象是否相等的:
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:93253次
积分:1824
积分:1824
排名:第16965名
原创:80篇
评论:31条
文章:15篇
阅读:32655
阅读:4739
文章:44篇
阅读:46102

我要回帖

更多关于 微信公众号登录平台 的文章

 

随机推荐