0

У меня есть две сущности:
- Trader.java
- Stockmarket.java

Я использую аннотацию @ManyToMany и у меня работает сохранение Trader, внутри которого содержится список Stockmarket, но не работает сохранение Stockmarket, в котором есть список трейдеров.

Trader.java

import lombok.*;

import javax.persistence.*;
import java.util.List;

@Data
@AllArgsConstructor
@NoArgsConstructor
@Entity
@Table(name = "trader")
public class Trader {

    @Id
    @GeneratedValue
    @Column(name = "trader_id")
    private Long id;

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

    @ManyToMany(cascade = { CascadeType.ALL })
    @JoinTable(name = "TRADER_STOCKMARKET",
            joinColumns = { @JoinColumn(name = "trader_id") },
            inverseJoinColumns = { @JoinColumn(name = "stockmarket_id") })
    private List<Stockmarket> stockmarket;

}

Stockmarket.java

import lombok.*;

import javax.persistence.*;
import java.util.List;

@Data
@AllArgsConstructor
@NoArgsConstructor
@Entity
@Table(name = "stockmarket")
public class Stockmarket{

    @Id
    @GeneratedValue
    @Column(name = "stockmarket_id")
    private Long id;

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

    @ManyToMany(mappedBy="stockmarket")
    private List<Trader> traders;

}

Контроллер:

(В MySQL уже есть 2 трейдера и 2 биржи.)

            Stockmarket stockmarket3 = new Stockmarket();
            stockmarket3.setStockmarketName("Marvel");
            List<Trader> allTraders = manyToManyBiService.findAllTraders();

            System.out.println("\n\n\n finally " + allTraders.toString() + "\n\n\n ");
            stockmarket3.setTraders(allTraders);

            manyToManyBiService.saveStockmarket(stockmarket3);

Дополнительные вещи, если помогут в решении проблемы

ManyToManyBiService.java:

@Service
public class ManyToManyBiService {

    @Autowired
    StockmarketRepository stockmarketRepository;

    @Autowired
    TraderRepository traderRepository;

    public void saveTrader(Trader trader){
        traderRepository.save(trader);
    }

    public void saveStockmarket(Stockmarket stockmarket){
        stockmarketRepository.save(stockmarket);
    }

    public Stockmarket findByNameStockmarket(String name){
        return stockmarketRepository.findByStockmarketName(name);
    }

    public List<Stockmarket> findAllStockmarket(){
        return stockmarketRepository.findAll();
    }

    public List<Trader> findAllTraders(){
        return traderRepository.findAll();
    }
}

StockmarketRepository и TraderRepository - Это интерфей, которые extend CrudRepository.

1 Answers1

0

Ответ найден.

Полный разбор аннотаций в Hibernate

Ошибка заключается в том, что я клал один объект в другой, но забывал ссылать вложенный объект на объект, в который он вложен.

грубо говоря у меня было так A->B->null, а надо A->B->A, чтобы получилось:
A->B->A->B->A->B->A->B->A->B->A... loop.

В итоге мои сущности должны выглядить вот так:

Trader.java

@Data
@AllArgsConstructor
@NoArgsConstructor
@Entity
@ToString(exclude = "stockmarkets")
@Table(name = "trader")
public class Trader {
@Id
@GeneratedValue
@Column(name = &quot;trader_id&quot;)
private Long id;

@Column(name = &quot;trader_name&quot;)
private String traderName;

@ManyToMany(cascade = {
    CascadeType.PERSIST,
    CascadeType.MERGE
})
@JoinTable(name = &quot;TRADER_STOCKMARKET&quot;,
        joinColumns = { @JoinColumn(name = &quot;trader_id&quot;) },
        inverseJoinColumns = { @JoinColumn(name = &quot;stockmarket_id&quot;) })
private Set&lt;Stockmarket&gt; stockmarkets = new HashSet&lt;&gt;();


/*
We need to add methods below to make everything work correctly
 */

public void addStockmarket(Stockmarket stockmarket) {
    stockmarkets.add(stockmarket);
    stockmarket.getTraders().add(this);
}

public void removeStockmarket(Stockmarket stockmarket) {
    stockmarkets.remove(stockmarket);
    stockmarket.getTraders().remove(this);
}

}



Stockmarket.java:

@Data
@AllArgsConstructor
@NoArgsConstructor
@Entity
@ToString(exclude = "traders")
@Table(name = "stockmarket")
public class Stockmarket{
@Id
@GeneratedValue
@Column(name = &quot;stockmarket_id&quot;)
private Long id;

@Column(name = &quot;stockmarket_name&quot;)
private String stockmarketName;

@ManyToMany(mappedBy=&quot;stockmarkets&quot;)
private Set&lt;Trader&gt; traders = new HashSet&lt;&gt;();

/*
We need to add methods below to make everything work correctly
 */

public void addTrader(Trader trader) {
    traders.add(trader);
    trader.getStockmarkets().add(this);
}

public void removeTrader(Trader trader) {
    traders.remove(trader);
    trader.getStockmarkets().remove(this);
}

}

Update 1:

В случае, если будут проблемы с Set<>, то используйте List<> .... = new ArrayList<>();,

  • не сработало в моём случае. Помогло вместо @ManyToMany(mappedBy="stockmarkets") поставить @ManyToMany(cascade = { CascadeType.ALL }) @JoinTable(...). Как в статье http://java-online.ru/hibernate-entities.xhtml – Max Lich Dec 03 '19 at 09:46
  • @MaxLich то есть вы два раза продублировали один и тот же код? Ибо CascadeType.ALL и @JoinTable я написал в trader.java – Antonio112009 Dec 04 '19 at 12:09
  • @MaxLich я уверен, что у вас допущена ошибка. Рассмотрите лучше вот эту ссылку. Это сайт одного из разработчиков Hibernate. – Antonio112009 Dec 04 '19 at 12:11
  • нет, не два раза один и тот. Просто зеркально отобразил этот блок кода (аннотаций) – Max Lich Dec 04 '19 at 17:06
  • @MaxLich честно, звучит это странно) Просто поменять местами, чтобы сработало – Antonio112009 Dec 05 '19 at 19:07
  • Я до конца не углублялся в эти аннотации, но я воспринимаю связи между объектами как "parent" и "child". В parent описываются важные зависимости по отношению к "child", а в "child", если зависимость "bidirectional" просто указывается ссылка на родителя. Таким образом описывать основной объект "child", а второстепенный - "parent" - это уже звучит неправильно – Antonio112009 Dec 05 '19 at 19:15
  • а если нет основного объекта? если оба равноправны? – Max Lich Dec 05 '19 at 19:53