您现在的位置是:主页 > news > 简述网站建设过程/西安网站seo排名优化

简述网站建设过程/西安网站seo排名优化

admin2025/4/23 23:15:11news

简介简述网站建设过程,西安网站seo排名优化,男男做爰视频网站,vscode创建网页在Spring JPA 的级联操作中,当配置referencedColumnName为非主键列,FetchType.LAZY就会失效。 下面我们通过一个例子来看一看这个问题,以及 通过 PersistentAttributeInterceptable 接口来解决这个问题。 referencedColumnName为主键列时 …

简述网站建设过程,西安网站seo排名优化,男男做爰视频网站,vscode创建网页在Spring JPA 的级联操作中,当配置referencedColumnName为非主键列,FetchType.LAZY就会失效。 下面我们通过一个例子来看一看这个问题,以及 通过 PersistentAttributeInterceptable 接口来解决这个问题。 referencedColumnName为主键列时 …

在Spring JPA 的级联操作中,当配置referencedColumnName为非主键列,FetchType.LAZY就会失效。

下面我们通过一个例子来看一看这个问题,以及 通过 PersistentAttributeInterceptable 接口来解决这个问题。

referencedColumnName为主键列时

下面看一个 People 和 Address 的referencedColumnName为主键列的例子。

People

package com.johnfnash.learn.domain;import java.io.Serializable;
import java.sql.Timestamp;import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.OneToOne;@Entity
public class People implements Serializable {private static final long serialVersionUID = -4580187061659309868L;@Id@GeneratedValue(strategy = GenerationType.IDENTITY)@Column(name = "id", nullable = false)private Long id;@Column(name = "name", nullable = true, length = 20)private String name;@Column(name = "sex", nullable = true, length = 1)private String sex;@Column(name = "birthday", nullable = true)private Timestamp birthday;// People 是关系的维护段,当删除 people时,会级联删除 address@OneToOne(cascade = CascadeType.ALL, fetch = FetchType.LAZY)// people 中的 address_id 字段参考 address 表的id字段@JoinColumn(name = "address_id", referencedColumnName = "id")private Address address;public People() {super();}public People(String name, String sex, Timestamp birthday, Address address) {super();this.name = name;this.sex = sex;this.birthday = birthday;this.address = address;}// getter, setter@Overridepublic String toString() {return "People [id=" + id + ", name=" + name + ", sex=" + sex + ", birthday=" + birthday + "]";}}

由于 @JoinColumn 的配置,数据库中 people 表中会有一个 address_id 字段,通过外键引用 address 表的主键列(id)。

Address

import java.io.Serializable;import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;import com.fasterxml.jackson.annotation.JsonIgnoreProperties;@Entity
@JsonIgnoreProperties(value={"hibernateLazyInitializer","handler","fieldHandler"}) 
public class Address implements Serializable {private static final long serialVersionUID = -4960690362029661737L;@Id@GeneratedValue(strategy = GenerationType.IDENTITY)@Column(name = "id", nullable = false)private Long id;@Column(name = "phone", nullable = false, length = 11)private String phone;@Column(name = "zipcode", nullable = true, length = 6)private String zipcode;@Column(name = "address", nullable = true, length = 100)private String address;//如果不需要根据Address级联查询People,可以注释掉//  @OneToOne(mappedBy = "address", cascade = {CascadeType.MERGE, CascadeType.REFRESH}, optional = false)//  private People people;public Address() {super();}public Address(String phone, String zipcode, String address) {this.phone = phone;this.zipcode = zipcode;this.address = address;}// getter, setter// ......@Overridepublic String toString() {return "Address [id=" + id + ", phone=" + phone + ", zipcode=" + zipcode + ", address=" + address + "]";}}

测试

创建 PeopleRepository,如下:

public interface PeopleRepository extends JpaRepository<People, Long> {
}

测试类:

import java.sql.Timestamp;import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;import com.johnfnash.learn.domain.Address;
import com.johnfnash.learn.domain.People;
import com.johnfnash.learn.repository.PeopleRepository;@RunWith(SpringRunner.class)
@SpringBootTest
public class PeopleAddressTests {@Autowiredprivate PeopleRepository peopleRepository;@Testpublic void savePeople() {Address address = new Address("12345678901", "54002", "xxxx road");People people = new People("ZS", "1", new Timestamp(System.currentTimeMillis()), address);peopleRepository.save(people);System.out.println(people.getId());}@Testpublic void findPeople() {People people = peopleRepository.getOne(1L);System.out.println(people);//System.out.println(people.getAddress());}    }

先执行 savePeople 方法,再执行 findPeople 方法。通过下面的log,我们可以看到 people 对象中的address确实没有加载。

Hibernate: select people0_.id as id1_4_0_, people0_.address_id as address_5_4_0_, people0_.birthday as birthday2_4_0_, people0_.name as name3_4_0_, people0_.sex as sex4_4_0_ from people people0_ where people0_.id=?
People [id=1, name=ZS, sex=1, birthday=2019-01-19 18:09:57.0]

打开 findPeople 中的注释,如下

@Test
public void findPeople() {People people = peopleRepository.getOne(1L);System.out.println(people);System.out.println(people.getAddress());
}

再次执行 findPeople 方法,输出的日志如下

Hibernate: select people0_.id as id1_4_0_, people0_.address_id as address_5_4_0_, people0_.birthday as birthday2_4_0_, people0_.name as name3_4_0_, people0_.sex as sex4_4_0_ from people people0_ where people0_.id=?
People [id=1, name=ZS, sex=1, birthday=2019-01-19 18:09:57.0]
Hibernate: select address0_.id as id1_0_0_, address0_.address as address2_0_0_, address0_.phone as phone3_0_0_, address0_.zipcode as zipcode4_0_0_ from address address0_ where address0_.id=?
Address [id=1, phone=12345678901, zipcode=54002, address=xxxx road]

这次因为用到了 address 信息,所以进行了查询。

referencedColumnName为非主键列时

依旧使用上面的例子,只是 People 类的 address 属性中 referencedColumnName 引用的字段改成非主键列 address。

// People 是关系的维护段,当删除 people时,会级联删除 address
@OneToOne(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
// people 中的 address_id 字段参考 address 表的id字段
@JoinColumn(name = "address_id", referencedColumnName = "id")
private Address address;

通过下面的测试方法进行测试

@Test
public void findPeople() {People people = peopleRepository.getOne(1L);System.out.println(people);//System.out.println(people.getAddress());
}

输出日志如下,我们可以看到address对象立即就加载了,并没有延迟加载。

Hibernate: select people0_.id as id1_4_0_, people0_.address_id as address_5_4_0_, people0_.birthday as birthday2_4_0_, people0_.name as name3_4_0_, people0_.sex as sex4_4_0_ from people people0_ where people0_.id=?
Hibernate: select address0_.id as id1_0_0_, address0_.address as address2_0_0_, address0_.phone as phone3_0_0_, address0_.zipcode as zipcode4_0_0_ from address address0_ where address0_.address=?
People [id=1, name=ZS, sex=1, birthday=2019-01-19 18:47:31.0]

查询资料,网上说 ,当referencedColumnName指向的列不是主键列时,hibernate去查询address时,理论上懒加载是需要使用proxy的,需要proxy的情况是,知道每个people都对应了一个address对象,但是这个时候,hibernate不知道是不是每一个people都对应于一个address,那么这个时候,他就回去查询一次,确定是否有address,那么他都去查询一次了,所以这个时候懒加载也就失效了。

那么这种情况下有没有什么办法对address进行懒加载呢?在hibernate中,可以通过继承 PersistentAttributeInterceptable 接口来实现延迟加载字段。下面将进行介绍。

PersistentAttributeInterceptable 实现字段延迟加载

首先,修改一下 People 类,继承 PersistentAttributeInterceptable 接口并实现相应方法,修改注解的设置以及修改一下相关字段的set方法和get方法。

import java.io.Serializable;
import java.sql.Timestamp;import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.OneToOne;import org.hibernate.annotations.LazyToOne;
import org.hibernate.annotations.LazyToOneOption;
import org.hibernate.engine.spi.PersistentAttributeInterceptable;
import org.hibernate.engine.spi.PersistentAttributeInterceptor;@Entity
public class People implements PersistentAttributeInterceptable, Serializable {private static final long serialVersionUID = -4580187061659309868L;private PersistentAttributeInterceptor interceptor;private Long id;private String name;private String sex;private Timestamp birthday;private Address address;public People() {super();}public People(String name, String sex, Timestamp birthday, Address address) {super();this.name = name;this.sex = sex;this.birthday = birthday;this.address = address;}@Id@GeneratedValue(strategy = GenerationType.IDENTITY)@Column(name = "id", nullable = false)public Long getId() {return id;}public void setId(Long id) {this.id = id;}@Column(name = "name", nullable = true, length = 20)public String getName() {return name;}public void setName(String name) {this.name = name;}@Column(name = "sex", nullable = true, length = 1)public String getSex() {return sex;}public void setSex(String sex) {this.sex = sex;}@Column(name = "birthday", nullable = true)public Timestamp getBirthday() {return birthday;}public void setBirthday(Timestamp birthday) {this.birthday = birthday;}// People 是关系的维护段,当删除 people时,会级联删除 address@OneToOne(cascade = CascadeType.ALL, fetch = FetchType.LAZY)// people 中的 address_id 字段参考 address 表的id字段@JoinColumn(name = "address_id", referencedColumnName = "address")@LazyToOne(LazyToOneOption.NO_PROXY)public Address getAddress() {if (interceptor != null) {return (Address) interceptor.readObject(this, "address", address);}   return address;}public void setAddress(Address address) {if (interceptor != null) {this.address = (Address) interceptor.writeObject(this, "owner", this.address, address);return;}this.address = address;}@Overridepublic String toString() {return "People [id=" + id + ", name=" + name + ", sex=" + sex + ", birthday=" + birthday + "]";}@Overridepublic PersistentAttributeInterceptor $$_hibernate_getInterceptor() {return interceptor;}@Overridepublic void $$_hibernate_setInterceptor(PersistentAttributeInterceptor interceptor) {this.interceptor = interceptor;}}

再次执行测试方法 findPeople,发现address又可以延迟加载了。

Hibernate: select people0_.id as id1_4_0_, people0_.birthday as birthday2_4_0_, people0_.name as name3_4_0_, people0_.sex as sex4_4_0_ from people people0_ where people0_.id=?
People [id=1, name=ZS, sex=1, birthday=2019-01-19 18:47:31.0]

注意事项:实现PersistentAttributeInterceptor的实体,重写PersistentAttributeInterceptor的get,set方法后才可以使用

参考

  1. 使用@ManyToOne(fetch=FetchType.LAZY),懒加载无效,这是怎么回事

  2. Hibernate 5 & JPA 2.1 延迟加载大字段属性