Jpa中 @OneToOne 懒加载失效的问题

Jpa中 @OneToOne 懒加载失效的问题

说明一下关系。useruser_seting, 是一个一对一的关系。一个用户记录,关联了一条相关的设置记录。(设置字段太多了,单独列张表出来)。关联列是由 user_seting 在维护,它包含了一个 user_id 字段。

现在的问题就是,根据id检索User的时候,User 中的 UserSeting 不会懒加载。会立即发出一条检索语句。

实体类

@Entity
@Table(name = "user")
public class User implements Serializable {
	
	private static final long serialVersionUID = 8175166175439387541L;
	
	@Id
	@Column(columnDefinition = "INT(11) UNSIGNED COMMENT '用户id'")
	@GeneratedValue(strategy = GenerationType.IDENTITY)
	private Integer id;
	
	@Column(columnDefinition = "varchar(20) COMMENT '昵称'")
	private String name;
	
	// 设置
	@OneToOne(fetch = FetchType.LAZY)
	@JoinColumn(name = "id", referencedColumnName = "user_id", 
		foreignKey = @ForeignKey(value = ConstraintMode.NO_CONSTRAINT))
	private UserSeting userSeting;
}
@Entity
@Table(name = "user_seting")
public class UserSeting implements Serializable {
	
	/**
	 * 
	 */
	private static final long serialVersionUID = -1007318207008996614L;

	@Id
	@Column(columnDefinition = "INT(11) unsigned COMMENT '设置id'")
	@GeneratedValue(strategy = GenerationType.IDENTITY)
	private Integer id;
	
	@Column(columnDefinition = "TINYINT(1) unsigned COMMENT '是否接受通知'")
	private Boolean notify;
	
	@OneToOne(fetch = FetchType.LAZY)
	@JoinColumn(name = "user_id", referencedColumnName = "id", unique = true, nullable = false, foreignKey = @ForeignKey(value = ConstraintMode.NO_CONSTRAINT))
	private User user;
}

CREATE TABLE `user` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '用户id',
  `gender` tinyint(1) unsigned NOT NULL COMMENT '性别。0:女,1:男',
  `name` varchar(20) DEFAULT NULL COMMENT '昵称',
  `version` int(11) unsigned NOT NULL COMMENT '版本号',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4;

CREATE TABLE `user_seting` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '设置id',
  `notify` tinyint(1) unsigned DEFAULT NULL COMMENT '是否接受通知',
  `user_id` int(11) unsigned NOT NULL COMMENT '用户id',
  PRIMARY KEY (`id`),
  UNIQUE KEY `UK_rdchrax5rp1m1y4kpax285krw` (`user_id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4;

根据id检索UserSeting

测试代码

@Test
@Transactional
@Rollback(false)
public void jpaTest () {
	UserSeting userSeting = this.userSetingService.getOne(1);
	System.out.println(userSeting.getNotify());
}

执行了一次查询

正常

SELECT
	userseting0_.id AS id1_4_0_,
	userseting0_.notify AS notify2_4_0_,
	userseting0_.user_id AS user_id3_4_0_ 
FROM
	user_seting userseting0_ 
WHERE
	userseting0_.id =?

根据id检索User

测试代码

@Test
@Transactional
@Rollback(false)
public void jpaTest () {
	this.userRepository.findById(1).get();
}

执行了两次查询

第一次查询,正常。
第二次查询就比较诡异,明明设置了 fetch = FetchType.LAZY,并且也没操作到 userSeting 属性。居然立即发出了一条检索语句。
而且WHERE条件并不是根据关联字段 user_id,而是它的主键id

SELECT
	user0_.id AS id1_2_0_,
	user0_.gender AS gender2_2_0_,
	user0_.NAME AS name3_2_0_,
	user0_.version AS version4_2_0_ 
FROM
	USER user0_ 
WHERE
	user0_.id =?
---------------------------------------------------------------
SELECT
	userseting0_.id AS id1_4_0_,
	userseting0_.notify AS notify2_4_0_,
	userseting0_.user_id AS user_id3_4_0_ 
FROM
	user_seting userseting0_ 
WHERE
	userseting0_.id =?

为什么双向 @OneToOne 关联,没有外键的一方,延迟加载会出现这个问题?

1 Like