一对一关联主要有3种方式
1.两主键关联
2.外键关联
3.关联表关联
这三种方式hibernate annitation都提供了支持
这里重点讲第二种配置
配置步骤
一数据库表配置
表结构见附录
sns_topic表示一个论坛主题
sns_topic_views`表示帖子浏览量
topic.views_id持有topic_views.id,为多对一关联。但我们需要的是一对一关联
所以需要在views_id上增加唯一性约束
- UNIQUE KEY `views_id` (`views_id`),
ok 数据库端搞定
二 entity class 配置
两个entity class : Topic TopicViews,代码见附录
Topic.java
- @OneToOne(optional = true, cascade = CascadeType.ALL, fetch = FetchType.LAZY)
- @JoinColumn(name = "views_id")
- public TopicViews getTopicViews() {
- return topicViews;
- }
TopicViews.java
- @OneToOne(mappedBy = "topicViews")
- public Topic getTopic() {
- return topic;
- }
- public void setTopic(Topic topic) {
- this.topic = topic;
- }
这就配置完了
三 总结
这个例子中的帖子和帖子点击量,前者属于不经常变化的实体类,而后者更新非常频繁
配置成一对一的目的是为了更有效的利用缓存
但事实上效果不好 没能达到预期的效果
每次更新topicviews都需要先外连接()这两张表,虽然关联的效率很高,但相比主键关联还是差些
主键一对一关联可独立的访问每个表 而不需要任何的关联查询
附录1
- CREATE TABLE `sns_topic` (
- `id` INTEGER(11) NOT NULL AUTO_INCREMENT,
- `author_id` INTEGER(11) NOT NULL,
- `title` VARCHAR(256) COLLATE utf8_general_ci DEFAULT NULL,
- `content` TEXT COLLATE utf8_general_ci,
- `create_date` DATETIME DEFAULT NULL,
- `quan_id` INTEGER(11) DEFAULT NULL,
- `category_id` INTEGER(11) DEFAULT NULL,
- `stick` TINYINT(4) DEFAULT NULL,
- `digest` TINYINT(4) DEFAULT NULL,
- `locked` TINYINT(4) DEFAULT NULL,
- `hide` TINYINT(4) DEFAULT NULL,
- `views_id` INTEGER(11) DEFAULT NULL,
- `posts` INTEGER(11) DEFAULT NULL,
- `last_post` DATETIME DEFAULT NULL,
- `last_poster` VARCHAR(128) COLLATE utf8_general_ci DEFAULT NULL,
- `highlight` TINYINT(4) DEFAULT NULL,
- PRIMARY KEY (`id`),
- UNIQUE KEY `views_id` (`views_id`),
- KEY `author_id` (`author_id`),
- KEY `quan_id` (`quan_id`),
- CONSTRAINT `sns_topic_fk2` FOREIGN KEY (`views_id`) REFERENCES `sns_topic_views` (`id`),
- CONSTRAINT `sns_topic_fk` FOREIGN KEY (`author_id`) REFERENCES `sns_user` (`id`),
- CONSTRAINT `sns_topic_fk1` FOREIGN KEY (`quan_id`) REFERENCES `sns_quan` (`id`)
- )ENGINE=InnoDB
- AUTO_INCREMENT=14 CHARACTER SET 'utf8' COLLATE 'utf8_general_ci'
- COMMENT='InnoDB free: 11264 kB; (`author_id`) REFER `sns/sns_user`(`i; InnoDB free: 11264';
- //`sns_topic_views`表示帖子浏览量
- CREATE TABLE `sns_topic_views` (
- `id` INTEGER(11) NOT NULL AUTO_INCREMENT,
- `views` INTEGER(11) DEFAULT NULL,
- PRIMARY KEY (`id`)
- )ENGINE=InnoDB
- AUTO_INCREMENT=3 CHARACTER SET 'utf8' COLLATE 'utf8_general_ci'
- COMMENT='InnoDB free: 11264 kB';
附录2
- package com.justel.sns.domain;
- import static javax.persistence.GenerationType.IDENTITY;
- import java.util.Date;
- import java.util.HashSet;
- import java.util.Set;
- import javax.persistence.CascadeType;
- import javax.persistence.Column;
- import javax.persistence.Entity;
- import javax.persistence.FetchType;
- import javax.persistence.GeneratedValue;
- import javax.persistence.Id;
- import javax.persistence.JoinColumn;
- import javax.persistence.ManyToOne;
- import javax.persistence.OneToMany;
- import javax.persistence.OneToOne;
- import javax.persistence.PrimaryKeyJoinColumn;
- import javax.persistence.Table;
- import javax.persistence.Temporal;
- import javax.persistence.TemporalType;
- import org.hibernate.annotations.Cache;
- import org.hibernate.annotations.CacheConcurrencyStrategy;
- /**
- * 主贴 entity.
- *
- * @author xuliangyong
- */
- @Entity
- @Table(name = "sns_topic", catalog = "sns")
- @Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
- public class Topic implements java.io.Serializable {
- private static final long serialVersionUID = -5503914485019914680L;
- private Integer id;
- private User snsUser; //作者
- private Quan snsQuan; //所属圈子
- private String title;
- private String content;
- private Date createDate;
- private Integer categoryId; //帖子分类
- private boolean stick; //置顶
- private boolean digest; //精华
- private boolean lock; //锁定
- private boolean hide; //隐藏
- private Integer posts; //回复次数
- private Date lastPost; //最后回复时间
- private String lastPoster; //最后回复用户
- private boolean highlight; //高亮显示
- private Set<Post> snsPosts = new HashSet<Post>(0);
- private TopicViews topicViews; //访问次数
- // Constructors
- /** default constructor */
- public Topic() {
- }
- public Topic(Integer id){
- this.id = id;
- }
- /** minimal constructor */
- public Topic(User snsUser) {
- this.snsUser = snsUser;
- }
- /** full constructor */
- public Topic(User snsUser, Quan snsQuan, String title,
- String content, Date createDate, Integer categoryId, boolean stick,
- boolean digest, boolean lock, boolean hide, TopicViews topicViews, Integer posts,
- Date lastPost, String lastPoster, boolean highlight,
- Set<Post> snsPosts) {
- this.snsUser = snsUser;
- this.snsQuan = snsQuan;
- this.title = title;
- this.content = content;
- this.createDate = createDate;
- this.categoryId = categoryId;
- this.stick = stick;
- this.digest = digest;
- this.lock = lock;
- this.hide = hide;
- this.topicViews = topicViews;
- this.posts = posts;
- this.lastPost = lastPost;
- this.lastPoster = lastPoster;
- this.highlight = highlight;
- this.snsPosts = snsPosts;
- }
- // Property accessors
- @Id
- @GeneratedValue(strategy = IDENTITY)
- @Column(name = "id", unique = true, nullable = false)
- public Integer getId() {
- return this.id;
- }
- public void setId(Integer id) {
- this.id = id;
- }
- @ManyToOne(fetch = FetchType.LAZY)
- @JoinColumn(name = "author_id", nullable = false)
- public User getSnsUser() {
- return this.snsUser;
- }
- public void setSnsUser(User snsUser) {
- this.snsUser = snsUser;
- }
- @ManyToOne(fetch = FetchType.LAZY)
- @JoinColumn(name = "quan_id")
- public Quan getSnsQuan() {
- return this.snsQuan;
- }
- public void setSnsQuan(Quan snsQuan) {
- this.snsQuan = snsQuan;
- }
- @Column(name = "title", length = 256)
- public String getTitle() {
- return this.title;
- }
- public void setTitle(String title) {
- this.title = title;
- }
- @Column(name = "content", length = 65535)
- public String getContent() {
- return this.content;
- }
- public void setContent(String content) {
- this.content = content;
- }
- @Column(name = "create_date", length = 19)
- public Date getCreateDate() {
- return this.createDate;
- }
- public void setCreateDate(Date createDate) {
- this.createDate = createDate;
- }
- @Column(name = "category_id")
- public Integer getCategoryId() {
- return this.categoryId;
- }
- public void setCategoryId(Integer categoryId) {
- this.categoryId = categoryId;
- }
- @Column(name = "stick")
- public boolean getStick() {
- return this.stick;
- }
- public void setStick(boolean stick) {
- this.stick = stick;
- }
- @Column(name = "digest")
- public boolean getDigest() {
- return this.digest;
- }
- public void setDigest(boolean digest) {
- this.digest = digest;
- }
- @Column(name = "locked")
- public boolean getLock() {
- return this.lock;
- }
- public void setLock(boolean lock) {
- this.lock = lock;
- }
- @Column(name = "hide")
- public boolean getHide() {
- return this.hide;
- }
- public void setHide(boolean hide) {
- this.hide = hide;
- }
- @Column(name = "posts")
- public Integer getPosts() {
- return this.posts;
- }
- public void setPosts(Integer posts) {
- this.posts = posts;
- }
- @Temporal(TemporalType.DATE)
- @Column(name = "last_post", length = 19)
- public Date getLastPost() {
- return this.lastPost;
- }
- public void setLastPost(Date lastPost) {
- this.lastPost = lastPost;
- }
- @Column(name = "last_poster", length = 128)
- public String getLastPoster() {
- return this.lastPoster;
- }
- public void setLastPoster(String lastPoster) {
- this.lastPoster = lastPoster;
- }
- @Column(name = "highlight")
- public boolean getHighlight() {
- return this.highlight;
- }
- public void setHighlight(boolean highlight) {
- this.highlight = highlight;
- }
- @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "snsTopic")
- public Set<Post> getSnsPosts() {
- return this.snsPosts;
- }
- public void setSnsPosts(Set<Post> snsPosts) {
- this.snsPosts = snsPosts;
- }
- @OneToOne(optional = true, cascade = CascadeType.ALL, fetch = FetchType.LAZY)
- @JoinColumn(name = "views_id")
- public TopicViews getTopicViews() {
- return topicViews;
- }
- public void setTopicViews(TopicViews topicViews) {
- this.topicViews = topicViews;
- }
- }
- package com.justel.sns.domain;
- import static javax.persistence.GenerationType.IDENTITY;
- import java.io.Serializable;
- import javax.persistence.Column;
- import javax.persistence.Entity;
- import javax.persistence.GeneratedValue;
- import javax.persistence.Id;
- import javax.persistence.OneToOne;
- import javax.persistence.PrimaryKeyJoinColumn;
- import javax.persistence.Table;
- @Entity
- @Table(name = "sns_topic_views", catalog = "sns")
- public class TopicViews implements Serializable {
- private Integer id;
- private Topic topic;
- private Integer views;
- //http://blog.csdn.net/EJB_JPA/archive/2008/05/11/2433301.aspx
- @OneToOne(mappedBy = "topicViews")
- public Topic getTopic() {
- return topic;
- }
- public void setTopic(Topic topic) {
- this.topic = topic;
- }
- public Integer getViews() {
- return views;
- }
- public void setViews(Integer views) {
- this.views = views;
- }
- @Id
- @GeneratedValue(strategy = IDENTITY)
- public Integer getId() {
- return id;
- }
- public void setId(Integer topicId) {
- this.id = topicId;
- }
- }