Как остановить спящий режим от вставки в таблицу в ManyToMany Mapping? - PullRequest
0 голосов
/ 28 декабря 2018

Проблема: мое веб-приложение MVC вставляется в таблицу ингредиентов.Я не хочу этого, потому что я уже наполнил этот стол 1000 различными компонентами шампуня.

Я пробовал возиться с установкой «cascade = CascadeType.ALL», но обычно получал «объект ссылается на несохраненный временный экземпляр - сохраните временный экземпляр перед сбросом: com.app.entity.Ingredient».Но я действительно не уверен, что это хоть что-нибудь исправит.

Изображение консоли

DB DIAGRAM

* 1013Вывод * toString () после представления результатов пользователем и до вставки в БД:

Shampoo [id=0, name=sas, company=Company [id=0, name=asassa], ingredients=[Ingredient [id=0, name=1-Dodecene, shampoos=null], Ingredient [id=0, name=Acetylated, shampoos=null]]]

Hibernate Stuff:

Hibernate: insert into company (company_name) values (?)
Hibernate: insert into shampoo (shampoo_company, shampoo_name) values (?, ?)
Hibernate: insert into ingredient (ingredient_name) values (?)
Hibernate: insert into ingredient (ingredient_name) values (?)

Я не хочу, чтобы он вставлялся в таблицу ингредиентов, потому что я уже заполнил таблицу 1000 наименованиями ингредиентов.Реально я просто хотел бы вставить в shampoo_ingredients ключом данного ингредиента.

Hibernate: insert into shampoo_ingredients (fk_shampoo, fk_ingredient) values (?, ?)
Hibernate: insert into shampoo_ingredients (fk_shampoo, fk_ingredient) values (?, ?)

Шампунь Entity

@Entity
@Table(name="shampoo")
public class Shampoo {

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

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

    @OneToOne(cascade=CascadeType.ALL)
    @JoinColumn(name="shampoo_company")
    private Company company;

    @ManyToMany(cascade=CascadeType.ALL)
    @JoinTable(
            name="shampoo_ingredients",
            joinColumns=@JoinColumn(name="fk_shampoo"),
            inverseJoinColumns=@JoinColumn(name="fk_ingredient")
            )
    private List<Ingredient> ingredients;

    public Shampoo() {

    }



    public Shampoo(String name) {
        this.name = name;
    }



    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Company getCompany() {
        return company;
    }

    public void setCompany(Company company) {
        this.company = company;
    }


    public List<Ingredient> getIngredients() {
        return ingredients;
    }

    public void setIngredients(List<Ingredient> ingredients) {
        this.ingredients = ingredients;
    }



    @Override
    public String toString() {
        return "Shampoo [id=" + id + ", name=" + name + ", company=" + company + ", ingredients=" + ingredients + "]";
    }


}

ИнгредиентEntity

@Entity
@Table(name="ingredient")
public class Ingredient {

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

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

    @ManyToMany(cascade=CascadeType.ALL)
    @JoinTable(
            name="shampoo_ingredients",
            joinColumns=@JoinColumn(name="fk_ingredient"),
            inverseJoinColumns=@JoinColumn(name="fk_shampoo")
            )
    private List<Shampoo> shampoos;

    public Ingredient() {

    }


    public Ingredient(String name) {
        this.name = name;
    }


    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }


    public List<Shampoo> getShampoos() {
        return shampoos;
    }

    public void setShampoos(List<Shampoo> shampoos) {
        this.shampoos = shampoos;
    }


    @Override
    public String toString() {
        return "Ingredient [id=" + id + ", name=" + name + ", shampoos=" + shampoos + "]";
    }


}

Контроллер шампуня

@Controller
@RequestMapping("/shampoo")
public class ShampooController {

    //inject DAO into controller
    @Autowired
    private ShampooDAO shampooDAO;
    @Autowired
    private CompanyDAO companyDAO;
    @Autowired
    private IngredientDAO ingredientDAO;
    @Autowired
    private ConversionService cs;
    @RequestMapping("/list")
    public String listShampoos(Model theModel) {

        //get shampoo from DAO
        List<Shampoo> theShampoos = shampooDAO.getShampoos();

        //add shampoo to model
        theModel.addAttribute("shampoos", theShampoos);
        return "list-shampoos";
    }

    @GetMapping("/showFormForAdd")
    public String showFormForAdd(Model theModel, ModelMap modelMap) {
        //create model attribute to bind form data

        Shampoo theShampoo = new Shampoo();
        modelMap.addAttribute("shampoo", theShampoo);


        List<Ingredient> theIngredients = ingredientDAO.getIngredients();

        modelMap.addAttribute("ingredient", theIngredients);




        return "shampoo-form";
    }

    @PostMapping("/saveShampoo")
    public String saveShampoo(@ModelAttribute("shampoo") Shampoo theShampoo) {


        System.out.println(theShampoo.getIngredients());
        System.out.println(theShampoo.toString());
        shampooDAO.saveShampoo(theShampoo);
        return "redirect:/shampoo/list";

    }
}

Шампунь DAO

@Repository
public class ShampooDAOImpl implements ShampooDAO {

    @Autowired
    private SessionFactory sessionFactory;

    @Transactional
    public List<Shampoo> getShampoos() {

        //get current hibernate session
        Session currentSession = sessionFactory.getCurrentSession();
        //create query
        Query<Shampoo> theQuery = currentSession.createQuery("from Shampoo", Shampoo.class);
        //execute query and get result list
        List<Shampoo> shampoos = theQuery.getResultList();
        //return list of shampoo
        return shampoos;
    }

    @Transactional
    public void saveShampoo(Shampoo theShampoo) {

        Session currentSession = sessionFactory.getCurrentSession();

        currentSession.save(theShampoo);

    }

}

Форма шампуня

<%@ taglib uri="http://www.springframework.org/tags/form" prefix="form" %>

<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>


<!DOCTYPE html>
<html>
<head>
    <title>Add New Shampoo</title>
    <script src="${pageContext.request.contextPath}/resources/jquery-3.3.1.min.js"></script>
    <script src="${pageContext.request.contextPath}/resources/chosen.jquery.js"></script>


    <link type="text/css" href="<%=request.getContextPath() %>/resources/chosen.css" rel="stylesheet"/> 
<script>

$(document).ready(function(e){
    // first initialize the Chosen select
    $('.test').chosen();

});


</script>

</head>
<body>

        <form:form cssClass="form" action="saveShampoo" modelAttribute="shampoo" method="POST">

            <table>
                <tbody>
                    <tr>
                        <td><label>Name:</label></td>
                        <td><form:input path="name" /></td>
                    </tr>
                    <tr>
                        <td><label>Company:</label></td>
                        <td><form:input path="company" /></td>
                    </tr>

                    <tr>
                        <td><label>Ingredients:</label></td>
                        <td><form:select cssClass="test" multiple="true" path="Ingredients" >
                            <form:options items="${ingredient}" itemValue="name" itemLabel="name" />

                            </form:select></td>
                    </tr>

                </tbody>

            </table>
            <input id= "submit" type="submit" value="Save"/>
        </form:form>

</body>

</html>

1 Ответ

0 голосов
/ 28 декабря 2018

Дело в том, что когда вы пытаетесь объединить шампунь и ингредиенты для сущностей, вы должны извлечь их из БД.

Предположим, вы создаете новый шампунь.Вы можете сделать:

Shampoo s = new Shampoo();
//All your own stuffs about Shampoo object

Теперь вы хотите присоединить шампунь и ингредиенты;и давайте предположим, что ингредиенты, к которым вы хотите присоединиться, называются «IngrA» и «IngrB», которые вы не можете сделать:

Ingredient a = new Ingredient();
a.setName("IngrA");
Ingredient b = new Ingredient();
b.setName("IngrB");
List<Ingredient> ingrs = new ArrayList<>(2);
ingrs.add(a);
ingrs.add(b);
s.setIngredients(ingrs);
repository.save(s); //Error will be thrown here; If you have CascadeType.All an insert will be done

Почему у вас будет ошибка?Потому что в соответствии с Hibernate a и b являются «новыми» объектами, которые вы никогда не сохраняли.Поэтому hibernate говорит вам: «Прежде чем вы сможете присоединиться к ним, вы должны сохранить их».

С другой стороны, поскольку у вас есть CascadeType.All hibernate пытается вставить эти «новые» объекты

ЧтоВы должны сделать, чтобы найти ингредиенты в БД и затем установить их.

Я имею в виду что-то вроде этого:

Ingredient a = ingredientDao.findByName("IngrA");
Ingredient b = ingredientDao.findByName("IngrB");
List<Ingredient> ingrs = new ArrayList<>(2);
if(a!=null)
   ingrs.add(a);
if(b!=null)
   ingrs.add(b);
s.setIngredients(ingrs);
repository.save(s); //No error will be thrown here

Почему нет ошибок?Потому что вы извлекли ингредиенты из БД, и теперь они больше не отделены.

Надеюсь, это полезно

Анджело

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...