Как настроить xml mapper для вставки объекта со свойством collection в mybatis - PullRequest
0 голосов
/ 11 декабря 2018

Я начинаю изучать концепции myBatis и пытаюсь сделать простую (или не очень) конфигурацию вставки в xml.У меня есть приложение на Java, которое читает, вставляет и обновляет некоторые книги в базе данных.Конфигурация xml для соединений с БД уже сделана.

В Java у меня есть 2 простых Pojo's:

public class Book {
    private Long id;
    private String name;
    private List<Author> authors;
    private String desc;

    public Book() {
        //Default Constructor
    }

    //constructors that takes args, setters & getters

}

и

public class Author {

    private String authorName;
    public Author() {
        // Default Constructor
    }
    public Author(String authorName) {
        this.authorName = authorName;
    }
    public String getAuthorName() {
        return authorName;
    }
    public void setAuthorName(String authorName) {
        this.authorName = authorName;
    }

}

А вот XMLконфиг для запроса:

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
 PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
 "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.kepler.learning.mybooks.dao.BookDao">

	<resultMap id="BookResult" type="Book">
		<id property="id" column="id"></id>
		<result property="name" column="name"></result>
		<result property="desc" column="desc"></result>
		<collection property="authors" ofType="Author">
			<result property="authorName" column="authorName"></result>
		</collection>
	</resultMap>
	<select id="readAll" resultMap="BookResult">
	    SELECT b.prod_id "id", b.name, a.name "authorName", b.description "desc"
		FROM tab_products b
			left outer join tab_authors a on b.PROD_ID = a.AUT_ID
	</select>
	
	<select id="findByName" parameterType="String" resultMap="BookResult">
	    SELECT b.prod_id "id", b.name, a.name "authorName", b.description "desc"
		FROM tab_products b
			left outer join tab_authors a on b.PROD_ID = a.AUT_ID
		WHERE b.name = #{name}
	</select>
	<insert id="insert" parameterType="Book">
		  INSERT INTO tab_products(prod_id,name,description)
      VALUES(SEQ_PRD_ID.nextVal,#{name},#{desc});
	</insert>
	
</mapper>

У меня также есть класс DBBookDao, который реализует все надлежащие методы, такие как «read all», «findByName», «insert»:

public class DBBookDao implements BookDao{
    private String resource = "mybatis.config.xml";
    private InputStream inputStream;
    private SqlSession sqlSession;
    private SqlSessionFactory sqlSessionFactory;
    public DBBookDao() {
        try {
            inputStream = Resources.getResourceAsStream(resource);
            sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        } catch (IOException e) {
            throw new BusinessException(e);
        }
    }

    public List<Book> readAll() {
        try {
            sqlSession = sqlSessionFactory.openSession();
            return sqlSession.selectList("com.kepler.learning.mybooks.dao.BookDao.readAll");
        } finally {
            sqlSession.close();
        }
    }

    public Book findByName(String name) {
        if (name == null) {
            throw new BusinessException("No book name provided!");
        }

        try {
            sqlSession = sqlSessionFactory.openSession();
            List<Book> books = sqlSession.selectList("com.kepler.learning.mybooks.dao.BookDao.findByName", name);

            return Optional.ofNullable(books).map(list -> list.get(0)).orElse(null);
        }
        finally {
            sqlSession.close();
        }

    }

    public boolean checkBookExists(Book book) {
        List<Book> allBooks = readAll();
        for(Book b : allBooks) {
            if(b.getName().equals(book.getName())) {
                return true;
            }
        }
        return false;
    }

    public void insert(Book book) {

        sqlSession = sqlSessionFactory.openSession();
        sqlSession.insert("com.kepler.learning.mybooks.dao.BookDao.insert",book);

    }

}

В базе данных у меня есть 2 разные таблицы: - таблица «TAB_PRODUCTS», где я храню информацию о книге, с 3 столбцами: PROD_ID, NAME, DESCRIPTION, - таблица «TAB_AUTHORS», где я храню информацию об авторе,с 3 столбцами: AUT_ID, NAME, DESCRIPTION.

Мне удалось успешно реализовать методы realAll () и findByName (), мне неудобна процедура вставки.

Есть ливложенная вставка?Как настроить конфигурацию вставки в XML, чтобы принять список авторов внутри книги?

1 Ответ

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

Вы можете сгенерировать операторы вставки, используя элемент foreach, например:

<insert id="insert" parameterType="Book">
    INSERT INTO tab_products(prod_id,name,description)
  VALUES(SEQ_PRD_ID.nextVal,#{name},#{desc});
    <foreach collection="authors" item="author" index="index">
       INSERT INTO tab_authors(aut_id,name,description)
  VALUES(SEQ_AUT_ID.nextVal,#{author.authorName},#{author.whateverDescProperty});
    </foreach>
</insert>

Обратите внимание, что в вашем классе автора нет поля описания, поэтому вам нужно указать правильное значение, а также я неНе знаю, каково имя последовательности для идентификаторов авторов, так что это черновик, чтобы проиллюстрировать идею.

Кроме того, вы можете перебрать список авторов в DAO:

public void insert(Book book) {

    sqlSession = sqlSessionFactory.openSession();
    sqlSession.insert("com.kepler.learning.mybooks.dao.BookDao.insert",book);
    for(Author author:book.getAuthors()) {
       sqlSession.insert(
         "com.kepler.learning.mybooks.dao.BookDao.insertAuthor",
         author);
    }
}

Выпотребуется создать метод сопоставления insertAuthor (или иметь другой сопоставитель для авторов).

Примечание : не проверять наличие одного элемента путем запроса всех объектов из базы данных, напримервы делаете в checkBookExists.Вместо этого используйте метод findByName.

...