EJB Project doesn't connect to the right Derby

2019-09-18 05:55发布

问题:

having a problem yesterday that i couldn't connect to the derby database (most likely due to persistence.xml issues) I have been guided to modify my persistence.xml so that it contains two additional poperties;

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

Having added them I don't get faced with bunch of errors such as SCHEMA "xx" doesn't exist or Unknown entity bean class: class model.Userbay, please verify that this class has been marked with the @Entity annotation.

Having though everything will be fine now, I realized that isn't the case.. At first i was attempting to obtain one of the rows from the database through the Entity Manager's .find() method. After a while of testing to retrieve the records from the database I though that it might be better to try to insert something into the database and see what happens. Having executed the following line of code;

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

I noticed that nothing was inserted into the database... However having tried to execute the .find() to find a primary key i just inserted (testts123s) it has found the record (although in the Data Source Explorer the database's table didn't get populated with this record). Therefore my questions is what could have happened that I was linked to an empty table ?

The following is the code;

Persistence.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;
    }

}

Userbay 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;
    }

}

回答1:

I noticed that nothing was inserted into the database... However having tried to execute the .find() to find a primary key i just inserted (testts123s) it has found the record.

How exactly did you notice that nothing was inserted into the database? Reading your next sentence it looks like it was.

Regardless

You should avoid inserting records with native SQL. First of all doing this you bypass cache and it may bring you real headache and finally it breaks entire idea of ORM. So instead you've better do it with persist method of entity manager.

Userbay user = new Userbay();
user.setFirstName("Firstname");
user.setLastName("Lastname");
user.setPassword("password");
user.setEmail("someemail@email.zzz");

emgr.persist(user);

As far as you chosen to generate userName it will be generated for you.

Just in case: Keep in mind even if you did not open any transaction, the container opened one for you when you called registerUser method. It means your are working in the same transaction until the method ends with all that it implies. Below is an extraction from Oracle tutorial

The Required attribute is the implicit transaction attribute for all enterprise bean methods running with container-managed transaction demarcation. You typically do not set the Required attribute unless you need to override another transaction attribute. Because transaction attributes are declarative, you can easily change them later.

You may want to read at least these sections for better understanding.

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

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



回答2:

After days of messing around with the persistence.xml I fortunately have found an oracle tutorial which guides to create a new JDBC connection pool and resource for glassfish server, to link the derby database. Having done it, all I needed to put inside the persistence.xml was the JTA data source.

Here's a video where I have done it from the scratch, this time choosing a ClientDriver - http://www.youtube.com/watch?v=xBNB8L49ZQ4