EJB Project не подключается к правильной базе данных/таблице Derby

вчера у меня возникла проблема, из-за которой я не смог подключиться к базе данных derby (скорее всего, из-за проблем с persistence.xml). Мне было предложено изменить файл persistence.xml, чтобы он содержал два дополнительных свойства;

<property name="eclipselink.ddl-generation" value="create-tables" />
<property name="eclipselink.ddl-generation.output-mode" value="database" />

Добавив их, я не сталкиваюсь с кучей ошибок, таких как SCHEMA "xx" doesn't exist или Unknown entity bean class: class model.Userbay, please verify that this class has been marked with the @Entity annotation.

Хотя теперь все будет хорошо, я понял, что это не так. Сначала я пытался получить одну из строк из базы данных с помощью метода .find() Entity Manager. После некоторого тестирования для извлечения записей из базы данных я подумал, что было бы лучше попытаться вставить что-нибудь в базу данных и посмотреть, что произойдет. Выполнив следующую строку кода;

emgr.createNativeQuery("insert into ADRIAN.USERBAY (USER_NAME, PASSWORD, EMAIL, FIRST_NAME, LAST_NAME) values('testts123s', '1', '1', '1', '1')").executeUpdate();

Я заметил, что ничего не было вставлено в базу данных... Однако, попытавшись выполнить .find(), чтобы найти первичный ключ, который я только что вставил (testts123s), он нашел запись (хотя в проводнике источников данных таблица базы данных не t заполняется этой записью). Поэтому мои вопросы: что могло случиться, что я был связан с пустой таблицей?

Ниже приведен код;

Постоянство.xml

<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.0" xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">
    <persistence-unit name="EJBAuctionv2">
    <!-- <jta-data-source>JDBC/MyDB</jta-data-source> -->
        <class>model.Userbay</class>
        <class>model.Item</class>
        <class>model.Category</class>

        <properties>
     <property name="javax.persistence.jdbc.password" value="123" />
     <property name="javax.persistence.jdbc.user" value="adrian" />
     <property name="javax.persistence.jdbc.driver" value="org.apache.derby.jdbc.EmbeededDriver" />
     <property name="javax.persistence.jdbc.url" value="jdbc:derby:C:\Users\Adrian\MyDB;create=true" />
<!-- <property name="eclipselink.ddl-generation" value="create-tables" />
<property name="eclipselink.ddl-generation.output-mode" value="database" />  -->
    </properties>
    </persistence-unit>
</persistence>

UserRegistration SessionBean

package auction;

import javax.ejb.EJB;
import javax.ejb.LocalBean;
import javax.ejb.Remote;
import javax.ejb.Singleton;
import javax.ejb.Stateful;
import javax.ejb.Stateless;
import javax.management.Query;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;

import model.Userbay;

/**
 * Session Bean implementation class userRegistrationSB
 */
@Remote @Stateless
public class userRegistrationSB implements userRegistrationSBRemote {

    //@EJB private Userbay user;
    @PersistenceContext(name = "EJBAuctionv2") private EntityManager emgr;
    /**
     * Default constructor. 
     */
    public userRegistrationSB() {}

    @Override
    public boolean registerUser(String username, String password, String email,
            String firstname, String lastname) {
        boolean registered = false;

        //emgr.createNativeQuery("insert into ADRIAN.USERBAY (USER_NAME, PASSWORD, EMAIL, FIRST_NAME, LAST_NAME) values('testts123s', '1', '1', '1', '1')").executeUpdate();

        System.out.println("Registering an user with username: " + username);
        Userbay user = emgr.find(model.Userbay.class, username);
        if (user == null) {
            System.out.println("Username doesn't exist.");
            registered = true;
        } else {
            registered = false;
            System.out.println("Username already exists.");
        }

        return registered;
    }

    @Override
    public boolean userExists(String username) {
        return false;
    }

    @Override
    public boolean userMatchesPassword(String username, String password) {
        return false;
    }

}

Пользовательский компонент Entity Bean

package model;

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




@Entity @Table (name = "Userbay")
@NamedQuery(name="Userbay.findAll", query="SELECT u FROM Userbay u")
public class Userbay implements Serializable {
    private static final long serialVersionUID = 1L;

    @Id @GeneratedValue (strategy = GenerationType.TABLE)
    @Column(name="USER_NAME")
    private String userName;

    private String email;

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

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

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

    //bi-directional many-to-one association to Item
    @OneToMany(mappedBy="userbay")
    private List<Item> items;

    public Userbay() {
    }

    public String getUserName() {
        return this.userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }

    public String getEmail() {
        return this.email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public String getFirstName() {
        return this.firstName;
    }

    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }

    public String getLastName() {
        return this.lastName;
    }

    public void setLastName(String lastName) {
        this.lastName = lastName;
    }

    public String getPassword() {
        return this.password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public List<Item> getItems() {
        return this.items;
    }

    public void setItems(List<Item> items) {
        this.items = items;
    }

    public Item addItem(Item item) {
        getItems().add(item);
        item.setUserbay(this);

        return item;
    }

    public Item removeItem(Item item) {
        getItems().remove(item);
        item.setUserbay(null);

        return item;
    }

}

person Adrian    schedule 25.02.2014    source источник
comment
Есть ли у вас какие-либо исключения после этой вставки? Если вы используете JPA, постарайтесь не использовать нативные запросы, если они вам действительно не нужны.   -  person Jakub H    schedule 25.02.2014
comment
При первой вставке не было никаких проблем, но при второй попытке возникло следующее исключение (поэтому оно сейчас закомментировано) — org.apache.derby.client.am.SqlException: оператор был прерван, потому что он вызвал дублировать значение ключа в уникальном или первичном ключевом ограничении или уникальном индексе, идентифицированном «SQL140225111513480», определенном в «USERBAY». P.S. он использовался только в целях тестирования и заставил меня понять, что я определенно не имею дело с таблицей, которую ожидал.   -  person Adrian    schedule 25.02.2014
comment
Так что, вероятно, генерация идентификатора не работает. Попробуйте удалить эту строку из базы данных и выполнить ее еще раз. Если все в порядке и у вас проблема только при второй вставке, значит у вас что-то не так с генерацией ID. Попробуйте изменить стратегию generateValue, например, тогда.   -  person Jakub H    schedule 25.02.2014
comment
Я не уверен, что вы поняли мою проблему. Проблема, которая меня беспокоит, не вставляется. Проблема в том, что у меня есть база данных с таблицей Userbay, которая уже содержит записи, и когда я пытаюсь найти строку с существующим первичным ключом, она просто возвращает пустой объект. Вставка материала была просто проверкой, чтобы увидеть, будет ли он вставлен в таблицу Userbay (чего, к сожалению, не было). Я даже не знаю, в какую таблицу были вставлены данные, потому что я не могу визуально увидеть их в Eclipse - Data Source Explorer ни при какой СХЕМЕ.   -  person Adrian    schedule 25.02.2014
comment
Таким образом, вы не можете получить какие-либо результаты в начале (в таблице есть несколько строк), но если вы вставите некоторые данные, вы можете получить результаты. Это правильно? Я бы посоветовал проверить, работаете ли вы с той же схемой базы данных, что и. Кстати, у вас есть ADRIAN.USERBAY в операторе вставки и USERBAY в запросе поиска.   -  person Jakub H    schedule 25.02.2014


Ответы (2)


Я заметил, что ничего не было вставлено в базу данных... Однако, попытавшись выполнить .find(), чтобы найти первичный ключ, который я только что вставил (testts123s), он нашел запись.

Как именно вы заметили, что в базу данных ничего не вставляется? Читая ваше следующее предложение, кажется, что так оно и было.

Несмотря ни на что

Вам следует избегать вставки записей с собственным SQL. Прежде всего, делая это, вы обходите кеш, и это может принести вам настоящую головную боль, и, наконец, это ломает всю идею ORM. Поэтому вместо этого вам лучше сделать это с помощью метода persist менеджера сущностей.

Userbay user = new Userbay();
user.setFirstName("Firstname");
user.setLastName("Lastname");
user.setPassword("password");
user.setEmail("[email protected]");

emgr.persist(user);

Поскольку вы решили сгенерировать имя пользователя, оно будет сгенерировано для вас.

На всякий случай: имейте в виду, даже если вы не открыли ни одной транзакции, контейнер открыл ее для вас, когда вы вызвали метод registerUser. Это означает, что вы работаете в одной и той же транзакции, пока метод не завершится со всеми вытекающими последствиями. Ниже приведена выдержка из учебника Oracle.

Атрибут Required — это неявный атрибут транзакции для всех методов корпоративного компонента, работающих с разграничением транзакций, управляемых контейнером. Обычно вы не устанавливаете обязательный атрибут, если вам не нужно переопределить другой атрибут транзакции. Поскольку атрибуты транзакций являются декларативными, их можно легко изменить позже.

Вы можете прочитать хотя бы эти разделы для лучшего понимания.

http://docs.oracle.com/javaee/6/tutorial/doc/bnbpy.html

http://docs.oracle.com/javaee/6/tutorial/doc/bncih.html

person jjd    schedule 26.02.2014
comment
Извините за мое плохое объяснение, я имел в виду, что ничего не было вставлено в базу данных, это то, что ничего не было вставлено в мою схему ADRIAN - таблицу Userbay. Он также не был вставлен ни в какую другую схему, существующую в базе данных. Сказать, что я могу получить вставленное значение testts123s, было правдой, потому что я имел дело с таблицей, которая была пустой до того, как я вставил testts123s. Поэтому я предполагаю, что была создана новая таблица, которая не была связана с базой данных, которую я хотел, и вывод состоит в том, что я не знаю, с какой схемой/базой данных я имею дело. - person Adrian; 26.02.2014

После нескольких дней возни с файлом persistence.xml я, к счастью, нашел учебник по оракулу, который поможет создать новый пул соединений JDBC и ресурс для сервера Glassfish, чтобы связать базу данных derby. Сделав это, все, что мне нужно было поместить в файл persistence.xml, — это источник данных JTA.

Вот видео, где я сделал это с нуля, на этот раз выбрав ClientDriver - http://www.youtube.com/watch?v=xBNB8L49ZQ4

person Adrian    schedule 28.02.2014