实体类:
@Data
@Entity
@Table(name = "people")
@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonIgnoreProperties({ "hibernateLazyInitializer", "handler" })
public class People {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer id;
    @Column(name = "username")
    private String username;
}
@Data
@Entity
@Table(name = "cat")
@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonIgnoreProperties({ "hibernateLazyInitializer", "handler" })
public class Cat {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer id;
    @Column(name = "name")
    private String name;
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "owner")
    private People owner;
}
复制代码
	表数据:
mysql> select * from people; +----+----------+ | id | username | +----+----------+ | 1 | zhangsan | | 2 | laoli | +----+----------+ 2 rows in set (0.00 sec) mysql> select * from cat; +----+-------+-------+ | id | name | owner | +----+-------+-------+ | 1 | kitty | 1 | | 2 | mao | 2 | | 3 | mi | 2 | +----+-------+-------+ 3 rows in set (0.00 sec) 复制代码
测试代码如下:
public interface PeopleRepo extends JpaRepository<People, Integer>, JpaSpecificationExecutor<People> {
    @Transactional
    @Modifying
    @Query(value = "update people set username = :username where id = :id", nativeQuery = true)
    void updateUsernameById(@Param("id") int id, @Param("username") String username);
}
@Service
public class PeopleAndCatService {
    @Autowired
    private PeopleRepo peopleRepo;
    @Transactional
    public String test1(int id) {
        People p1 = peopleRepo.findById(id).get()			// 1
        System.out.println("p1: " + p1);
        peopleRepo.updateUsernameById(id, "ceeeeb");	// 2
        People p2 = peopleRepo.findById(id).get()			// 3
        System.out.println("p2: " + p2);
        return null;
    }
}
复制代码
	当调用接口 test1(1) 时,返回结果如下:
p1: People(id=1, username=zhangsan) p2: People(id=1, username=zhangsan) 复制代码
但是数据库中的数据已更改。
@Modifying(clearAutomatically = true)
org.hibernate.LazyInitializationException: could not initialize proxy - no Session
错误	测试代码:
@Service
public class PeopleAndCatService {
    @Autowired
    private CatRepo catRepo;
    
    @Transactional
    public Cat test2(int id) {
        Cat c = catRepo.findById(id).get();	// 1
        return c;
    }
}
@RestController
@RequestMapping("/jpa")
public class PeopleAndCatController {
    @Autowired
    private PeopleAndCatService peopleAndCatService;
    @GetMapping("/test2")
    public Cat test2(@RequestParam("id") int id) {
        Cat cat = peopleAndCatService.test2(id);
        return cat;		// 2
    }
}
复制代码
	select * from cat where id = ?
,并没有关联查询 People 表(但是拿到 owner 的 id 了)。	
不用懒加载,更改为				@ManyToOne(fetch = FetchType.EAGER)
;			
在事务未结束时,比如步骤 1 后面,调用				c.getOwner().getUsername()
触发查询 People 表操作;			
上面的方案最终还是查询了 People 表,如果我根本就不关心 owner,不想查 People 表呢;可以改写方法如下:
@Transactional
public Cat test2(int id) {
    Cat c = catRepo.findById(id).get();
    People people = new People();
    people.setId(c.getOwner().getId());
    c.setOwner(people);
    return c;
}
复制代码
		不用外键,更改 Cat 类的 owner 字段为 int 类型,涉及关联查询时需要手写 sql,表之间的关联控制通过程序实现(涉及到数据库设计中是否需要外键之争了。。。)