最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Spring Data JPA多表聯(lián)合查詢的實(shí)例演示

 更新時(shí)間:2025年09月18日 11:17:51   作者:UndefinedMan  
本文主要介紹了Spring Data JPA多表聯(lián)合查詢的實(shí)例演示,包括一對(duì)一、一對(duì)多、多對(duì)一、多對(duì)多關(guān)系,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧

 對(duì)于JPA的基本操作以及動(dòng)態(tài)查詢可以查看這篇文章: SpringBoot整合JPA

目前市場(chǎng)上對(duì)于ORM框架選型一般只有兩種, 一種是Mybatis/MybatisPlus, 另一種就是JPA, 之前參與的項(xiàng)目都是使用MybatisPlus沒(méi)有系統(tǒng)的了解JPA, 而到新的項(xiàng)目組中使用的是JPA正當(dāng)學(xué)習(xí)時(shí)發(fā)現(xiàn)網(wǎng)絡(luò)上對(duì)于JPA的文章紛繁雜亂, 尤其是對(duì)JPA多表聯(lián)查使我看的摸不到頭腦, 所以本著方便自己日后學(xué)習(xí)以及分享開(kāi)發(fā)經(jīng)驗(yàn)的出發(fā)點(diǎn), 寫下這篇文章.

Mysql版本: Mysql8.0

一. 簡(jiǎn)單復(fù)習(xí)數(shù)據(jù)庫(kù)表之間的關(guān)系

表之間存在哪幾種關(guān)系?

數(shù)據(jù)庫(kù)表之間存在多種關(guān)系: 一對(duì)一(例子: 一夫一妻), 一對(duì)多(例子: 用戶與賬單), 多對(duì)多(例子: 學(xué)生與教師)

各個(gè)關(guān)系如何關(guān)聯(lián)起來(lái)?

一對(duì)一: 建立外鍵

一對(duì)多: 一對(duì)多的關(guān)系我們?cè)诙嗟囊环椒湃胍?id)來(lái)唯一標(biāo)識(shí)

多對(duì)多: 多對(duì)多的關(guān)系通過(guò)一張關(guān)系表來(lái)維持多多關(guān)系, 關(guān)系表存儲(chǔ)了兩個(gè)表的主鍵作為外鍵

綜上所述: JPA的多表查詢就是基于外鍵來(lái)實(shí)現(xiàn)的(實(shí)際上JPA并沒(méi)有對(duì)多表查詢做封裝, 完全使用的是底層Hibernate框架的多表查詢實(shí)現(xiàn))

Hibernate對(duì)多表聯(lián)合查詢的策略: 通過(guò)@OneToOne, @OneToMany, @ManyToOne, @ManyToMany注解自動(dòng)維護(hù)表之間的關(guān)聯(lián)關(guān)系, 在CRUD時(shí)如果設(shè)計(jì)到關(guān)聯(lián)表自動(dòng)建立外鍵關(guān)系對(duì)關(guān)聯(lián)表也執(zhí)行相關(guān)操作, 同時(shí)提供多個(gè)屬性支撐懶加載, 過(guò)刪除等功能.

二. 實(shí)現(xiàn)多表聯(lián)查

在application.peoperties中添加如下配置

server.port=9000
#mysql驅(qū)動(dòng)
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
#mysql的jdbc連接
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/${your.database}
#用戶名
spring.datasource.username=root
#密碼
spring.datasource.password=${your.password}
#jpa配置, 顯示執(zhí)行的sql語(yǔ)句
spring.jpa.show-sql=true
#設(shè)置hibernate的方言 MySQL5Dialect
spring.jpa.database-platform=org.hibernate.dialect.MySQL5Dialect
#自動(dòng)創(chuàng)建表
spring.jpa.hibernate.ddl-auto=update

包結(jié)構(gòu):

 

1. 一對(duì)一 (OneToOne)

建立兩張表consumer(用戶表), account(賬戶表), 我們規(guī)定一個(gè)用戶只能有一個(gè)賬戶, 一個(gè)賬戶只能屬于一個(gè)用戶, 這樣便有了一對(duì)一的關(guān)系, 一對(duì)一的關(guān)系分為單向一對(duì)一, 雙向一對(duì)一.

首先設(shè)計(jì)這兩個(gè)表(因?yàn)橐呀?jīng)設(shè)置了自動(dòng)創(chuàng)建表所以不用創(chuàng)建數(shù)據(jù)庫(kù)表只需要?jiǎng)?chuàng)建實(shí)體類映射)

public class Customer {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "cust_id")
    private Integer custId;

    @Column(name = "cust_name")
    private String custName;

    @Column(name = "cust_address")
    private String custAddress;
}
@Entity
@Table(name = "account")
@Data
public class Account {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id")
    private Integer id;

    @Column(name = "name")
    private String name;

    @Column(name = "password")
    private String password;
}

1. 單向一對(duì)一

在Consumer中添加對(duì)Account的關(guān)聯(lián)

    @OneToOne(targetEntity = Account.class,
            cascade = CascadeType.ALL,
            fetch = FetchType.EAGER,
            optional = false,
            orphanRemoval = false)
    @JoinColumn(name = "account_id")
    private Account account;

這里主要介紹一下@OneToOne()中屬性的含義

1. targetEntity: 目標(biāo)對(duì)象, 也就是 "和誰(shuí)一對(duì)一"默認(rèn)值是注解標(biāo)注的對(duì)象

2. cascade: 設(shè)置關(guān)聯(lián)操作, 定義了當(dāng)主實(shí)體做了一些持久化操作時(shí)是否級(jí)聯(lián)到關(guān)系實(shí)體上

有多個(gè)可選值 : 

類型含義示例說(shuō)明
ALL級(jí)聯(lián)所有操作相當(dāng)于 PERSIST + MERGE + REMOVE + REFRESH + DETACH
PERSIST級(jí)聯(lián)保存當(dāng)保存主實(shí)體時(shí),如果關(guān)聯(lián)實(shí)體未被保存,則自動(dòng)保存
MERGE級(jí)聯(lián)合并更新主實(shí)體時(shí),也同步更新關(guān)聯(lián)實(shí)體的狀態(tài)(適用于脫離狀態(tài)的對(duì)象)
REMOVE級(jí)聯(lián)刪除刪除主實(shí)體時(shí),同時(shí)刪除其關(guān)聯(lián)實(shí)體
REFRESH級(jí)聯(lián)刷新刷新主實(shí)體時(shí),也刷新關(guān)聯(lián)實(shí)體的狀態(tài)(從數(shù)據(jù)庫(kù)重新加載數(shù)據(jù))
DETACH級(jí)聯(lián)分離主實(shí)體從持久化上下文中移除時(shí),關(guān)聯(lián)實(shí)體也一并被分離

3. fetch: 定義了是否使用懶加載模式, 默認(rèn)是即刻加載, 懶加載為L(zhǎng)AZY

4. optional: 是否允許標(biāo)注對(duì)象為空, 默認(rèn)true允許為空

5. orphanRemoval: 是否啟用過(guò)刪除, 如果啟用當(dāng)關(guān)系表屬性為null時(shí)直接刪除數(shù)據(jù)庫(kù)表中對(duì)          應(yīng)的關(guān)聯(lián)數(shù)據(jù)

@JoinColumn()定義了生成的外鍵名

這樣就將Customer與Account關(guān)聯(lián)起來(lái)了.之后在CRUD時(shí)Customer時(shí)會(huì)自動(dòng)將Account CRUD前提是定義了允許的關(guān)聯(lián)操作等級(jí).

先進(jìn)行數(shù)據(jù)插入:

@SpringBootTest
public class JPAOneToOneTest {

    @Autowired
    private CustomerDao customerDao;

    @Test
    public void test01() {
        Customer customer = new Customer();
        customer.setCustName("測(cè)試數(shù)據(jù)1");
        Account account = new Account();
        account.setName("測(cè)試賬戶1");
        customer.setAccount(account);
        customerDao.save(customer);
        System.out.println("---------保存成功----------");
    }
}

數(shù)據(jù)查詢(級(jí)聯(lián)):

@SpringBootTest
public class JPAOneToOneTest {

    @Autowired
    private CustomerDao customerDao;

    @Test
    public void test01() {
        Customer customer = new Customer();
        customer.setCustName("測(cè)試數(shù)據(jù)1");
        Account account = new Account();
        account.setName("測(cè)試賬戶1");
        customer.setAccount(account);
        customerDao.save(customer);
        System.out.println("---------保存成功----------");
    }

    @Test
    public void test02() {
        System.out.println("Customer: " + customerDao.findById(1).get());
    }
}

刪除(級(jí)聯(lián)):

@SpringBootTest
public class JPAOneToOneTest {

    @Autowired
    private CustomerDao customerDao;

    @Test
    public void test01() {
        Customer customer = new Customer();
        customer.setCustName("測(cè)試數(shù)據(jù)1");
        Account account = new Account();
        account.setName("測(cè)試賬戶1");
        customer.setAccount(account);
        customerDao.save(customer);
        System.out.println("---------保存成功----------");
    }

    @Test
    public void test02() {
        System.out.println("Customer: " + customerDao.findById(1).get());
    }

    @Test
    public void test03() {
        customerDao.deleteById(1);
        System.out.println("----------刪除成功----------");
    }
}

 修改: 對(duì)于修改如果開(kāi)啟了過(guò)刪除, 當(dāng)設(shè)置account為null時(shí)會(huì)刪除掉account表中沒(méi)有被關(guān)聯(lián)的數(shù)據(jù), 注意前提是optinal = true, orphanRemoval = true

@SpringBootTest
public class JPAOneToOneTest {

    @Autowired
    private CustomerDao customerDao;

    @Test
    public void test01() {
        Customer customer = new Customer();
        customer.setCustName("測(cè)試數(shù)據(jù)1");
        Account account = new Account();
        account.setName("測(cè)試賬戶1");
        customer.setAccount(account);
        customerDao.save(customer);
        System.out.println("---------保存成功----------");
    }

    @Test
    public void test02() {
        System.out.println("Customer: " + customerDao.findById(1).get());
    }

    @Test
    public void test03() {
        customerDao.deleteById(1);
        System.out.println("----------刪除成功----------");
    }

    @Test
    public void test04() {
        Customer customer = new Customer();
        customer.setCustId(2);
        customer.setCustName("測(cè)試數(shù)據(jù)2");
        customer.setAccount(null);
        customerDao.save(customer);
    }
}

2. 雙向一對(duì)一

如果也在Account中添加@OneToOne() @JoinColumn()這種定義一對(duì)一關(guān)系就會(huì)再次建立一個(gè)外鍵關(guān)聯(lián)Customer, 造成的問(wèn)題就是互相關(guān)聯(lián)導(dǎo)致兩個(gè)表中的數(shù)據(jù)都無(wú)法刪除, 可以使用@OneToOne(mappedBy = ...)來(lái)解決這個(gè)問(wèn)題, mappedBy的意思就是指定這個(gè)關(guān)聯(lián)關(guān)系的維護(hù)者, 簡(jiǎn)單來(lái)說(shuō)就是總體上只維護(hù)一個(gè)關(guān)聯(lián)關(guān)系.

    /**
     * mappedBy, 用來(lái)標(biāo)識(shí)在一個(gè)雙向關(guān)系中哪一方是關(guān)系的維護(hù)方
     */
    @OneToOne(mappedBy = "account")
    private Customer customer;

這里只測(cè)試查詢, 整體與單向一樣, 只是方向不同

@SpringBootTest
public class JPAOneToOneAccountTest {

    @Autowired
    private AccountDao accountDao;

    @Test
    public void test01() {

        System.out.println("Account: " + accountDao.findById(3));

    }
}

這里輸出時(shí)會(huì)報(bào)錯(cuò): 

java.lang.StackOverflowError
	at java.lang.AbstractStringBuilder.append(AbstractStringBuilder.java:449)
	at java.lang.StringBuilder.append(StringBuilder.java:142)
	at com.yangyang.jpa.entity.Customer.toString(Customer.java:16)
	at java.lang.String.valueOf(String.java:2994)
	at java.lang.StringBuilder.append(StringBuilder.java:137)
	at com.yangyang.jpa.entity.Account.toString(Account.java:11)
	at java.lang.String.valueOf(String.java:2994)
	at java.lang.StringBuilder.append(StringBuilder.java:137)
	at com.yangyang.jpa.entity.Customer.toString(Customer.java:16)

可以看出是一個(gè)棧溢出, 原因是兩個(gè)toString循環(huán)調(diào)用了, 因?yàn)檩敵龅那疤岫际钦{(diào)用各自的toString, 我們重寫toString來(lái)解決一下

    @Override
    public String toString() {
        return "Account{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", password='" + password + '\'' +
                ", customer=" + customer.getCustName() +
                '}';
    }

2. 一對(duì)多(OneToMany)

建立Message表, 依然自動(dòng)生成

/**
 * 一對(duì)多, 多的一方
 */
@Entity
@Table(name = "message")
@Data
public class Message {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id")
    private Integer id;


    @Column(name = "info")
    private String info;
}

Customer和Message一對(duì)多的關(guān)系, 一個(gè)用戶對(duì)應(yīng)多個(gè)消息, 一個(gè)消息只屬于一個(gè)用戶.

現(xiàn)在對(duì)一對(duì)多的關(guān)系進(jìn)行關(guān)聯(lián), 這里@JoinColumn(name)設(shè)置的是放在多的一斷一的字段名

@Entity
@Table(name = "customer")
@Data
public class Customer {


    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "cust_id")
    private Integer custId;

    @Column(name = "cust_name")
    private String custName;

    @Column(name = "cust_address")
    private String custAddress;


    // 一對(duì)一
    @OneToOne(targetEntity = Account.class,
            cascade = CascadeType.ALL,
            fetch = FetchType.EAGER,
            optional = true,
            orphanRemoval = true)
    @JoinColumn(name = "account_id")
    private Account account;
    
    
    // 一對(duì)多
    @OneToMany(cascade = CascadeType.ALL
            , fetch = FetchType.EAGER
            , orphanRemoval = false)
    @JoinColumn(name = "customer_id")
    private List<Message> messages;
}

插入(級(jí)聯(lián)):

@SpringBootTest
public class JPAOneToManyTest {

    @Autowired
    private CustomerDao customerDao;

    @Test
    public void test01() {
        Customer customer = new Customer();
        customer.setCustName("測(cè)試數(shù)據(jù)3");
        List<Message> messages = new ArrayList<>();
        messages.add(new Message("haha"));
        messages.add(new Message("hehe"));
        customer.setMessages(messages);
        customerDao.save(customer);

    }
}

查詢(級(jí)聯(lián))

@SpringBootTest
public class JPAOneToManyTest {

    @Autowired
    private CustomerDao customerDao;

    @Test
    public void test01() {
        Customer customer = new Customer();
        customer.setCustName("測(cè)試數(shù)據(jù)3");
        List<Message> messages = new ArrayList<>();
        messages.add(new Message("haha"));
        messages.add(new Message("hehe"));
        customer.setMessages(messages);
        customerDao.save(customer);

    }

    @Test
    public void test02() {
        System.out.println("Customer: " + customerDao.findById(4));
    }
}

刪除(級(jí)聯(lián))

@SpringBootTest
public class JPAOneToManyTest {

    @Autowired
    private CustomerDao customerDao;

    @Test
    public void test01() {
        Customer customer = new Customer();
        customer.setCustName("測(cè)試數(shù)據(jù)3");
        List<Message> messages = new ArrayList<>();
        messages.add(new Message("haha"));
        messages.add(new Message("hehe"));
        customer.setMessages(messages);
        customerDao.save(customer);

    }

    @Test
    public void test02() {
        System.out.println("Customer: " + customerDao.findById(4));
    }


    @Test
    public void test03() {
        customerDao.deleteById(4);
        System.out.println("----------刪除成功----------");
    }
}

修改(級(jí)聯(lián))

@SpringBootTest
public class JPAOneToManyTest {

    @Autowired
    private CustomerDao customerDao;

    @Test
    public void test01() {
        Customer customer = new Customer();
        customer.setCustName("測(cè)試數(shù)據(jù)3");
        List<Message> messages = new ArrayList<>();
        messages.add(new Message("haha"));
        messages.add(new Message("hehe"));
        customer.setMessages(messages);
        customerDao.save(customer);

    }

    @Test
    public void test02() {
        System.out.println("Customer: " + customerDao.findById(4));
    }


    @Test
    public void test03() {
        customerDao.deleteById(4);
        System.out.println("----------刪除成功----------");
    }

    @Test
    public void test04() {
        Customer customer = new Customer();
        customer.setCustId(5);
        Message message = new Message();
        message.setId(3);
        message.setInfo("更改數(shù)據(jù)1");
        Message message1 = new Message();
        message1.setId(4);
        message1.setInfo("更改數(shù)據(jù)2");
        List<Message> messages = new ArrayList<>();
        messages.add(message);
        messages.add(message1);
        customer.setMessages(messages);
        customerDao.save(customer);
    }
}

3. 多對(duì)一(ManyToOne)

message與customer之間是多對(duì)一的關(guān)系

定義多對(duì)一關(guān)系:

@Entity
@Table(name = "message")
@Data
public class Message {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id")
    private Integer id;


    @Column(name = "info")
    private String info;

    public Message(String info) {
        this.info = info;
    }

    public Message() {
    }

    @ManyToOne(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
    @JoinColumn(name = "customer_id")
    private Customer customer;
}

以查詢(級(jí)聯(lián))為例, 其他同一對(duì)多

@SpringBootTest
public class JPAManyToOneTest {

    @Autowired
    private MessageDao messageDao;

    @Test
    public void test01() {
        System.out.println(messageDao.findById(3));
    }
}

4. 多對(duì)多

多對(duì)多關(guān)系分為單向多對(duì)多, 雙向多對(duì)多

首先還是建立測(cè)試表: role, 依然是自動(dòng)生成

@Entity
@Table(name = "role")
@Data
public class Role {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id")
    private Integer id;


    @Column(name = "role_name")
    private String rName;

}

仔細(xì)想一下, 其實(shí)多對(duì)多關(guān)系與一對(duì)多關(guān)系很相似, 問(wèn)題就在于多對(duì)多關(guān)系被拆分了, 拆分為兩個(gè)表對(duì)一個(gè)中間表的一對(duì)多關(guān)系, 那么關(guān)鍵就在于定義一個(gè)中間關(guān)系表, 同時(shí)JPA也會(huì)自動(dòng)為我們維護(hù)這個(gè)關(guān)系表無(wú)需自己建立.

現(xiàn)在來(lái)定義多對(duì)多的關(guān)系

@Entity
@Table(name = "customer")
@Data
public class Customer {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "cust_id")
    private Integer custId;

    @Column(name = "cust_name")
    private String custName;

    @Column(name = "cust_address")
    private String custAddress;


    // 一對(duì)一
    @OneToOne(targetEntity = Account.class,
            cascade = CascadeType.ALL,
            fetch = FetchType.EAGER,
            optional = true,
            orphanRemoval = true)
    @JoinColumn(name = "account_id")
    private Account account;


    // 一對(duì)多
    @OneToMany(cascade = CascadeType.ALL
            , fetch = FetchType.EAGER
            , orphanRemoval = false)
    @JoinColumn(name = "customer_id")
    private List<Message> messages;
    
    
    // 多對(duì)多
    @ManyToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
    @JoinTable(
            name = "customer_role_relation", // 中間關(guān)系表名
            joinColumns = {@JoinColumn(name = "c_id")}, // 當(dāng)前表的關(guān)聯(lián)外鍵名
            inverseJoinColumns = {@JoinColumn(name = "r_id")} // 另一個(gè)多表的關(guān)聯(lián)外鍵名
    )
    private List<Role> role;
}

著重說(shuō)一下@JoinTable, 因?yàn)樾枰S護(hù)一個(gè)關(guān)聯(lián)表, 所以不能使用@JoinColumn, 其中三個(gè)參數(shù)的意義是name: 關(guān)系表表名, joinColumns: 當(dāng)前表關(guān)聯(lián)外鍵名, inverseJoinColumns: 另一個(gè)表的關(guān)聯(lián)外鍵名

插入(級(jí)聯(lián)):

@SpringBootTest
public class JPAManyToManyTest {

    @Autowired
    private CustomerDao customerDao;


    @Test
    public void test01() {
        List<Role> rols = new ArrayList<>();
        Role role = new Role();
        role.setRName("測(cè)試role1");
        Role role1 = new Role();
        role1.setRName("測(cè)試role2");
        rols.add(role);
        rols.add(role1);
        Customer customer = new Customer();
        customer.setCustName("多對(duì)多測(cè)試數(shù)據(jù)1");
        customer.setRole(rols);
        customerDao.save(customer);
    }
}

查詢(級(jí)聯(lián))

@SpringBootTest
public class JPAManyToManyTest {

    @Autowired
    private CustomerDao customerDao;


    @Test
    public void test01() {
        List<Role> rols = new ArrayList<>();
        Role role = new Role();
        role.setRName("測(cè)試role1");
        Role role1 = new Role();
        role1.setRName("測(cè)試role2");
        rols.add(role);
        rols.add(role1);
        Customer customer = new Customer();
        customer.setCustName("多對(duì)多測(cè)試數(shù)據(jù)1");
        customer.setRole(rols);
        customerDao.save(customer);
    }

    @Test
    @Transactional
    public void test02() {
        System.out.println("Customer: " + customerDao.findById(6).get());
    }
}

刪除(級(jí)聯(lián)):

@SpringBootTest
public class JPAManyToManyTest {

    @Autowired
    private CustomerDao customerDao;


    @Test
    public void test01() {
        List<Role> rols = new ArrayList<>();
        Role role = new Role();
        role.setRName("測(cè)試role1");
        Role role1 = new Role();
        role1.setRName("測(cè)試role2");
        rols.add(role);
        rols.add(role1);
        Customer customer = new Customer();
        customer.setCustName("多對(duì)多測(cè)試數(shù)據(jù)1");
        customer.setRole(rols);
        customerDao.save(customer);
    }

    @Test
    @Transactional
    public void test02() {
        System.out.println("Customer: " + customerDao.findById(6).get());
    }

    @Test
    public void test03() {
        customerDao.deleteById(6);
        System.out.println("----------刪除成功----------");
    }
}

刪除這里涉及到一個(gè)問(wèn)題, 如果關(guān)聯(lián)表中存在其他引用關(guān)系例如另一個(gè)customer也對(duì)role有引用, 那么這次這次刪除就會(huì)失敗

修改(級(jí)聯(lián)):

@SpringBootTest
public class JPAManyToManyTest {

    @Autowired
    private CustomerDao customerDao;

    @Autowired
    private RoleDao roleDao;


    @Test
    public void test01() {
        List<Role> rols = new ArrayList<>();
        Role role = new Role();
        role.setRName("測(cè)試role1");
        Role role1 = new Role();
        role1.setRName("測(cè)試role2");
        rols.add(role);
        rols.add(role1);
        Customer customer = new Customer();
        customer.setCustName("多對(duì)多測(cè)試數(shù)據(jù)1");
        customer.setRole(rols);
        customerDao.save(customer);
    }

    @Test
    @Transactional
    public void test02() {
        System.out.println("Customer: " + customerDao.findById(6).get());
    }

    @Test
    public void test03() {
        customerDao.deleteById(6);
        System.out.println("----------刪除成功----------");
    }

    @Test
    @Transactional
    @Commit
    public void test04() {
//        Role role = new Role();
//        role.setId(3);
//        role.setRName("測(cè)試role3");
//        Role role1 = new Role();
//        role1.setId(4);
//        role1.setRName("測(cè)試role4");
        List<Role> roles = new ArrayList<>();
        Role role1 = roleDao.findById(3).get();
        roles.add(role1);
        Role role2 = roleDao.findById(4).get();
        roles.add(role2);
        Customer customer = new Customer();
        customer.setCustName("多對(duì)多測(cè)試數(shù)據(jù)2");
        customer.setRole(roles);
        customerDao.save(customer);
    }
}

這里注意一下, 修改時(shí)不可以手動(dòng)對(duì)象id賦值來(lái)指定修改哪個(gè)字段, 因?yàn)樵贖ibernate中實(shí)體有四種狀態(tài):

Transient(瞬時(shí)態(tài))對(duì)象剛 new 出來(lái),尚未與數(shù)據(jù)庫(kù)關(guān)聯(lián),也未被 EntityManager 管理
Persistent(持久態(tài))已被 EntityManager 管理,比如通過(guò) find()、merge() 獲取或保存的對(duì)象
Detached(游離態(tài))曾經(jīng)是持久態(tài),但現(xiàn)在不再被 EntityManager 管理(例如 session 關(guān)閉后)
Removed(刪除態(tài))已從數(shù)據(jù)庫(kù)中刪除

我們直接賦值指定的對(duì)象被認(rèn)為是游離態(tài)的, 需要是持久態(tài)才可以進(jìn)行更改.簡(jiǎn)單來(lái)說(shuō)就是在數(shù)據(jù)庫(kù)中查出來(lái)的才可以證明是存在的才可以進(jìn)行關(guān)聯(lián).

補(bǔ)充: 想要關(guān)聯(lián)Role表中已經(jīng)存在的字段:

    /**
     * 補(bǔ)充, 想要關(guān)聯(lián)role表中已經(jīng)存在的字段
     */
    @Test
    @Transactional
    @Commit
    public void test05() {
        List<Role> rols = new ArrayList<>();
        Role role = roleDao.findById(3).get();
        rols.add(role);
        Role role2 = roleDao.findById(4).get();
        rols.add(role2);

        Customer customer = new Customer();
        customer.setCustName("補(bǔ)充測(cè)試數(shù)據(jù)");
        customer.setRole(rols);
        customerDao.save(customer);
    }

到此這篇關(guān)于Spring Data JPA多表聯(lián)合查詢的實(shí)例演示的文章就介紹到這了,更多相關(guān)Spring Data JPA 多表聯(lián)合查詢內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • IntelliJ?IDEA教程之clean或者install?Maven項(xiàng)目的操作方法

    IntelliJ?IDEA教程之clean或者install?Maven項(xiàng)目的操作方法

    這篇文章主要介紹了IntelliJ?IDEA教程之clean或者install?Maven項(xiàng)目的操作方法,本文分步驟給大家介紹兩種方式講解如何調(diào)試出窗口,需要的朋友可以參考下
    2023-04-04
  • Java8常用的新特性詳解

    Java8常用的新特性詳解

    這篇文章主要介紹了Java8常用的新特性詳解,文中有非常詳細(xì)的代碼示例,對(duì)正在學(xué)習(xí)Java8新特性的小伙伴們有非常好的幫助,需要的朋友可以參考下
    2021-04-04
  • springboot集成RocketMQ過(guò)程及使用示例詳解

    springboot集成RocketMQ過(guò)程及使用示例詳解

    這篇文章主要為大家介紹了springboot集成RocketMQ過(guò)程及使用示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-07-07
  • SpringBoot Actuator埋點(diǎn)和監(jiān)控及簡(jiǎn)單使用

    SpringBoot Actuator埋點(diǎn)和監(jiān)控及簡(jiǎn)單使用

    最近做的項(xiàng)目涉及到埋點(diǎn)監(jiān)控、報(bào)表、日志分析的相關(guān)知識(shí),于是搗鼓的一番,下面把涉及的知識(shí)點(diǎn)及SpringBoot Actuator埋點(diǎn)和監(jiān)控的簡(jiǎn)單用法,給大家分享下,感興趣的朋友一起看看吧
    2021-11-11
  • Java中比較器Comparator和Comparable的區(qū)別

    Java中比較器Comparator和Comparable的區(qū)別

    這篇文章主要介紹了Java中比較器Comparator和Comparable的區(qū)別,我們?cè)谑褂?Collections.sort()對(duì)鏈表進(jìn)行排序時(shí),常常需要根據(jù)不同情況自定義排序規(guī)則,今天我們來(lái)看看比較器之間的區(qū)別,需要的朋友可以參考下
    2023-08-08
  • Kafka的安裝及接入SpringBoot的詳細(xì)過(guò)程

    Kafka的安裝及接入SpringBoot的詳細(xì)過(guò)程

    Kafka 是一種高性能、分布式的消息隊(duì)列系統(tǒng),最初由 LinkedIn 公司開(kāi)發(fā),并于2011年成為 Apache 頂級(jí)項(xiàng)目,這篇文章主要介紹了Kafka的安裝及接入SpringBoot,需要的朋友可以參考下
    2024-05-05
  • Elasticsearch 的索引管理與映射配置實(shí)戰(zhàn)指南

    Elasticsearch 的索引管理與映射配置實(shí)戰(zhàn)指南

    在本文中,我們深入探討了 Elasticsearch 中索引與映射的基本概念及其重要性,通過(guò)詳細(xì)的操作示例,我們了解了如何創(chuàng)建、更新和刪除索引,以及如何定義和修改映射,以優(yōu)化數(shù)據(jù)存儲(chǔ)和查詢性能,感興趣的朋友跟隨小編一起看看吧
    2025-11-11
  • SpringBoot讀取配置文件的五種方法總結(jié)

    SpringBoot讀取配置文件的五種方法總結(jié)

    這篇文章主要為大家詳細(xì)介紹了SpringBoot讀取配置文件的五種方法,文中的示例代碼講解詳細(xì),對(duì)我們學(xué)習(xí)SpringBoot有一定幫助,需要的可以參考一下
    2022-08-08
  • MyBatis多表聯(lián)查返回List僅一條數(shù)據(jù)?主鍵沖突BUG排查與解決方案

    MyBatis多表聯(lián)查返回List僅一條數(shù)據(jù)?主鍵沖突BUG排查與解決方案

    在項(xiàng)目開(kāi)發(fā)中,通過(guò)MyBatis實(shí)現(xiàn)“管理員-角色-權(quán)限”多表關(guān)聯(lián)查詢時(shí),遇到SQL執(zhí)行返回多條結(jié)果但MyBatis映射后List集合只顯示一條數(shù)據(jù)的BUG,最終定位到是主鍵字段命名沖突導(dǎo)致,通過(guò)為SQL中同名字段起別名并修正ResultMap配置,成功修復(fù)了BUG
    2026-04-04
  • springboot集成swagger3與knife4j的詳細(xì)代碼

    springboot集成swagger3與knife4j的詳細(xì)代碼

    這篇文章主要介紹了springboot集成swagger3與knife4j,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-08-08

最新評(píng)論

宜昌市| 会宁县| 调兵山市| 乐业县| 册亨县| 会宁县| 闽清县| 虹口区| 佛冈县| 宝坻区| 阿尔山市| 临夏县| 特克斯县| 奉化市| 盐亭县| 九龙城区| 江永县| 滦平县| 松江区| 沙雅县| 科技| 墨江| 金乡县| 永靖县| 岑溪市| 保康县| 长宁区| 高清| 龙南县| 永济市| 奉节县| 宣威市| 东阳市| 吉木萨尔县| 昂仁县| 奉化市| 安化县| 丰台区| 铁岭县| 灌南县| 东乌|