Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / Java [игнор отключен] [закрыт для гостей] / JPA EclipseLink cascade CRUD / 22 сообщений из 22, страница 1 из 1
14.02.2012, 15:21:47
    #37661214
Joe R
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
JPA EclipseLink cascade CRUD
Всем привет.

Помогите разобраться с такой задачей. Работаю с JPA EclipseLink EJB. Есть две сущности Book и Author, связанные many-to-many. В базе данных таблицы books и authors связаны через join таблицу authors_books по их id. В таблице authors не должно быть дубликатов, т.е. при вставке сущности Book должна производится проверка для авторов. Если автора нет, то добавить его, если есть то не добавлять, а в join table добавить его id.
И вот тут непонятно как вклиниться в эту проверку, не разрывая каскадных связей. Как это лучше сделать?

Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
@Entity
@Table(name="books")
public class Book implements Serializable {
	
	@Id
	@GeneratedValue(strategy=IDENTITY)
	@Column(name="book_id")
	private int bookId;

//bi-directional many-to-many association to Author
	@ManyToMany(fetch = EAGER, cascade = { MERGE, DETACH, REFRESH, PERSIST })
	@JoinTable(name = "authors_books", joinColumns = { @JoinColumn(name = "book_id") }, 
	inverseJoinColumns = { @JoinColumn(name = "author_id") })	
private List<Author> authors = new ArrayList<Author>();
.
.
.



Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
@Entity
@Table(name = "authors")
public class Author implements Serializable
{
	
	@Id
	@GeneratedValue(strategy = IDENTITY)
	@Column(name = "author_id")
	private int authorId;
@Column(unique = true)
	private String name;

	// bi-directional many-to-many association to Book
	@ManyToMany(fetch = EAGER, mappedBy = "authors", cascade = { MERGE, REFRESH, DETACH })
	private List<Book> books;
.
.
.



Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
@Stateless

public class BookServiceBean {
       
public Book create(Book entity)
	{		
		getEntityManager().persist(entity);
		return entity;
	}
.
.
.
}
...
Рейтинг: 0 / 0
14.02.2012, 15:50:21
    #37661301
Petro123
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
JPA EclipseLink cascade CRUD
Joe R,
ну дак код вставки и сохранения сессии то где?
Ты сделай сначала, чтобы они повторялись (запрос и покажи повтор).
...
Рейтинг: 0 / 0
14.02.2012, 16:00:44
    #37661329
Joe R
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
JPA EclipseLink cascade CRUD
Petro123Joe R,
ну дак код вставки и сохранения сессии то где?
Ты сделай сначала, чтобы они повторялись (запрос и покажи повтор).

Код вставки я написал:
getEntityManager().persist(entity);

База MySQL. Поле name для авторов стоит уникальным. При добавлении дубликата вылетает DatabaseException.
...
Рейтинг: 0 / 0
14.02.2012, 16:09:46
    #37661342
Blazkowicz
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
JPA EclipseLink cascade CRUD
Joe RБаза MySQL. Поле name для авторов стоит уникальным. При добавлении дубликата вылетает DatabaseException.
При этом authorId имеет значение, или null? Если имеет, то покажите польностью исключение. Если authorId null, то соответсвенно, как ORM узнает, что это сущствующая запись?
...
Рейтинг: 0 / 0
14.02.2012, 16:32:44
    #37661389
Joe R
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
JPA EclipseLink cascade CRUD
author_id генерится автоматом, вылетает на имени.


FINE: INSERT INTO authors (NAME) VALUES (?)
bind => [1 parameter bound]
FINE: SELECT 1
WARNING: Local Exception Stack:
Exception [EclipseLink-4002] (Eclipse Persistence Services - 2.3.0.v20110604-r9504): org.eclipse.persistence.exceptions.DatabaseException
Internal Exception: com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Duplicate entry 'Joe Smith' for key 'ind_name'
Error Code: 1062
Call: INSERT INTO authors (NAME) VALUES (?)
bind => [1 parameter bound]
Query: InsertObjectQuery(Joe Smith)
...
Рейтинг: 0 / 0
14.02.2012, 16:39:29
    #37661407
Blazkowicz
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
JPA EclipseLink cascade CRUD
Joe Rauthor_id генерится автоматом, вылетает на имени.

Я спрашиваю про authorId, а не author_id. В момент до вызова em.persist(). Это такой сложный вопрос?
...
Рейтинг: 0 / 0
14.02.2012, 16:41:46
    #37661412
Blazkowicz
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
JPA EclipseLink cascade CRUD
Судя по
FINE: INSERT INTO authors (NAME) VALUES (?)
у вас во время сохранения книги, у автора не проставлен PK. Вот ОРМ и не знает что это существующий автор.
...
Рейтинг: 0 / 0
14.02.2012, 16:54:51
    #37661448
Joe R
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
JPA EclipseLink cascade CRUD
Вот код создания сущности:
Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
....
Book book = new Book();
		book.setTitle("Title");
		book.setFileSize(10);
		book.setPagesCount(400);
		book.setPicture("pic" + rnd.nextInt(50) + ".jpg");
		book.setYear(2007 + rnd.nextInt(6));
		book.setDescription("Description");
		book.addAuthor(new Author("Joe Smith"));
		book.addAuthor(new Author("Randall Osborn"));

getEntityManager().persist(book);



authorId я не создаю, он в базе автоинкрементно генерится, это в сущности отображено:

Код: java
1.
2.
3.
4.
        @Id
	@GeneratedValue(strategy = IDENTITY)
	@Column(name = "author_id")
	private int authorId;



BlazkowiczСудя по
FINE: INSERT INTO authors (NAME) VALUES (?)
у вас во время сохранения книги, у автора не проставлен PK. Вот ОРМ и не знает что это существующий автор.

Вот в этом и вопрос, как этот РК создать то?
...
Рейтинг: 0 / 0
14.02.2012, 16:55:58
    #37661451
Blazkowicz
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
JPA EclipseLink cascade CRUD
Вот таким нехитрым способом.
Код: java
1.
2.
book.addAuthor(findAuthor("Joe Smith"));
book.addAuthor(findAuthor("Randall Osborn"));
...
Рейтинг: 0 / 0
14.02.2012, 17:02:45
    #37661474
Joe R
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
JPA EclipseLink cascade CRUD
Blazkowicz,

findAuthor('Joe Smith') это должен быть query типа?:

SELECT c FROM Author c WHERE c.name = 'Joe Smith'
...
Рейтинг: 0 / 0
14.02.2012, 17:06:17
    #37661481
Blazkowicz
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
JPA EclipseLink cascade CRUD
Joe RfindAuthor('Joe Smith') это должен быть query типа?:
SELECT c FROM Author c WHERE c.name = 'Joe Smith'
Это, уж, как вам удобнее.
...
Рейтинг: 0 / 0
14.02.2012, 17:14:16
    #37661503
Joe R
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
JPA EclipseLink cascade CRUD
А нет, проблема не в том, чтобы найти автора, а в том, чтобы добавить ссылку на него в таблицу authors_books. У меня ведь нет для неё сущности, ORM ведь должен сам разруливать каскадные зависимости. Что тут делать?
...
Рейтинг: 0 / 0
14.02.2012, 17:17:11
    #37661512
Blazkowicz
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
JPA EclipseLink cascade CRUD
Joe RА нет, проблема не в том, чтобы найти автора, а в том, чтобы добавить ссылку на него в таблицу authors_books. У меня ведь нет для неё сущности, ORM ведь должен сам разруливать каскадные зависимости. Что тут делать?
ORM отлично разруливает. Если проблема не в том, а в этом, то объясните это а не то.
...
Рейтинг: 0 / 0
14.02.2012, 17:43:18
    #37661589
Joe R
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
JPA EclipseLink cascade CRUD
В общем задача в следующем:
- если автор есть, то не добавлять его в таблицу authors, а добавить на него ссылку в таблицу authors_books, к которой у меня нет доступа. На SQL это выглядело бы так:

Код: sql
1.
INSERT INTO authors_books (author_id, book_id) VALUES ($author_id, $book_id)



Как это через ORM сделать?
...
Рейтинг: 0 / 0
14.02.2012, 17:44:53
    #37661593
Petro123
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
JPA EclipseLink cascade CRUD
Joe RА нет, проблема не в том, чтобы найти автора, а в том, чтобы добавить ссылку на него в таблицу authors_books. У меня ведь нет для неё сущности, ORM ведь должен сам разруливать каскадные зависимости. Что тут делать?
это многопользовательская система.
Представь что 2 чела рядом вводят
"Joe Smith"
- разные это авторы или один?
Т.е. код должен содержать findAuthor либо в Бизнес-слое вверху, либо внизу в сущности-DAO
...
Рейтинг: 0 / 0
14.02.2012, 17:47:14
    #37661599
Petro123
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
JPA EclipseLink cascade CRUD
Joe RВ общем задача в следующем:
- если автор есть, то не добавлять его в таблицу authors, а добавить на него ссылку в таблицу authors_books, к которой у меня нет доступа. На SQL это выглядело бы так:

Код: sql
1.
INSERT INTO authors_books (author_id, book_id) VALUES ($author_id, $book_id)


Как это через ORM сделать?
на SQL ты получишь райзе.
Т.е. тоже два запроса.
...
Рейтинг: 0 / 0
14.02.2012, 17:57:39
    #37661628
Blazkowicz
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
JPA EclipseLink cascade CRUD
Joe RНа SQL это выглядело бы так:
Код: sql
1.
INSERT INTO authors_books (author_id, book_id) VALUES ($author_id, $book_id)


Как это через ORM сделать?
book.addAuthor(findAuthor(name));
...
Рейтинг: 0 / 0
14.02.2012, 17:59:40
    #37661633
svenom
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
JPA EclipseLink cascade CRUD
Joe RВ общем задача в следующем:
- если автор есть, то не добавлять его в таблицу authors, а добавить на него ссылку в таблицу authors_books, к которой у меня нет доступа. На SQL это выглядело бы так:
Код: sql
1.
INSERT INTO authors_books (author_id, book_id) VALUES ($author_id, $book_id)


Как это через ORM сделать?Господи, да что у вас за проблема то? Вам не надо руками ничего добавлять в эту промежуточную таблицу. Вам надо просто добавить в список авторов еще одного автора. Все остальное JPA сделает за вас.
Но! Разумеется, вы не можете сделать что-то типа
Код: java
1.
2.
3.
Author a = new Author("John Smith");
book.getAuthors().add(a);
em.persist(book);

Ведь в этом случае, будет создан новый автор, а судя по вот этому исключению:
logcom.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Duplicate entry 'Joe Smith' for key 'ind_nameимена авторов у вас должны быть уникальными.
Вам Blazkowicz уже правильно сказал, что вам требуется сделать - вместо создания нового автора, сначала производить поиск сущеуствующего.
То есть надо делать что-то типа (псведокод):
Код: java
1.
2.
3.
4.
5.
6.
7.
Author a = findAuthorByName("John Smith");
if (a == null) {
    a = new Author("John Smith");
    em.persist(a);
}
book.getAuthors.add(a);
em.book(persist);

Если ваши маппинги прописаны верно, то такой вариант отработает на ура.
...
Рейтинг: 0 / 0
14.02.2012, 18:03:55
    #37661640
Blazkowicz
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
JPA EclipseLink cascade CRUD
svenomТо есть надо делать что-то типа (псведокод):

Персистить, автора при создании, не обязательно, если каскада прописаны. Само добавит.
...
Рейтинг: 0 / 0
14.02.2012, 21:37:55
    #37661915
Joe R
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
JPA EclipseLink cascade CRUD
Разобрался, сделал findAuthorByName и заработало.
Всем спасибо за помощь.
...
Рейтинг: 0 / 0
14.02.2012, 22:21:52
    #37661961
Blazkowicz
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
JPA EclipseLink cascade CRUD
Кстати, никогд ане понимал почему
findAuthorByName(String name)
может быть лучше чем
findAuthor(String name)
...
Рейтинг: 0 / 0
14.02.2012, 23:09:51
    #37661999
забыл ник
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
JPA EclipseLink cascade CRUD
авторКстати, никогд ане понимал почему
findAuthorByName(String name)
может быть лучше чем
findAuthor(String name)

А если есть потребность в findAuthorByBookName(String bookName) или findAuthorByBookISDN(String ISDN)?
...
Рейтинг: 0 / 0
Форумы / Java [игнор отключен] [закрыт для гостей] / JPA EclipseLink cascade CRUD / 22 сообщений из 22, страница 1 из 1
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]