1

我正在使用 eclipse JPA 项目在 Apache Derby 中创建实体。我正在使用 JPA 工具:

"generate tables from entities.." 

命令。当我使用这个命令时,表被放入数据库中。我可以看到这些表,并且它们具有来自 Eclipse“数据源资源管理器”的列。当我通过 ij 登录到 Derby 时。

我输入:

'show tables in schema x';

我得到与实体对应的表名列表。我输入:

'select * from <table in x>'

我得到:

ERROR 42X05: Table/View 'ADDRESS' does not exist.

为什么我的桌子不粘..?当我使用在使用“从实体生成表..”命令期间输入的 CREATE TABLE 命令时,它们会在那里生成表。当我输入“select * ..”时,我得到了一张桌子。

第二,可能相关的问题。我有一堂课。我使用以下命令来获取实体管理器:

EntityManagerFactory emf = Persistence.createEntityManagerFactory("DataModelAccess");

EntityManager em = emf.createEntityManager();

如果我对我的实体进行测试,例如:

public void runTest()
{
    EntityManagerFactory emf =
        Persistence.createEntityManagerFactory("DataModelAccess");

    EntityManager em = emf.createEntityManager();

    System.out.println(emf == null);

    Address address = new Address();
    address.setAddressID("1");
    address.setAddressNumber(1746);
    address.setStreetName("Howard");
    address.setStreetType("Court");
    address.setCity("Lennyville");
    address.setState("CT");
    address.setZipcode(73625);
    em.persist(address);
    em.close();
    emf.close();

    // reassign:
    emf = Persistence.createEntityManagerFactory("DataModelAccess");
    em = emf.createEntityManager();

    Address address2 = em.find(Address.class, "1");
    System.out.println(address2.getCity());

我在最后一行得到一个 NullPointerException。

如果我不重新分配给 emf 和 em,它会将城市打印到控制台。

所以,

1. 为什么SELECT * FROM <TABLE_NAME>没有出现表?
     但是会出现在 <SCHEMA> 中的 SHOW TABLES 中吗?

2. 为什么我的数据不能跨会话持久化?

我在 Eclipse 中从一个普通的旧 Java SE 对象运行它。没有 Java EE 容器。这是一个 Eclipse JPA 项目。有一个 persistence.xml 文件。有一个名为 'derby' 的连接由 eclipse 管理。也许我有一个 persistence.xml 文件问题?也许这是每个人的共同问题。由于某些不同的访问协议,JPA 和 eclipselink 可能会默认执行此操作?也许没有 Java EE 容器会变得很困难?

========

根据要求:地址类是完全无关的。我也尝试过基于字段和属性的访问。这对IJ没有任何影响。两种尝试都同样失败。这是一个总结:

@Entity 
@Table(name="ADDRESS") 
public class Address 
implements Serializable

...

@Id 
public String getAddressID()

其他一切都是字段、构造函数、getter 和 setter。没有注释。我刚刚通过右键单击我的包并选择添加了一个新的 JPA 实体

New --> JPA Entity 

我使用 Eclipse 向导将字段放入其中。我使它基于属性。我想也许基于字段的访问会改变一些事情,所以我尝试了基于字段的访问,但没有任何区别。

你在哪里看到这个:address.setStreetName("Howard"); 有字段:

private String streetName; 

和两个对应的方法

setStreetName(String x); 

String getStreetName(); 

类中的所有字段都存在相同的公式。每个字段都有一个 getter 和一个 setter。没有比 getter 和 setter 更多的方法了。每个 getter/setter 方法对 1 个字段。没有比我提到的更多的注释。

仅供参考:我没有设置 Address 类的所有属性。表中的字段都作为 NULLABLE 输入到数据库中。然而,IJ 没有找到任何 TABLE。– user1405870 11 小时前

=========

这是 Address 和 Address_ 类:

package dataAccess.customer;

import javax.annotation.Generated;
import javax.persistence.metamodel.SingularAttribute;
import javax.persistence.metamodel.StaticMetamodel;

@Generated(value="Dali", date="2012-05-18T21:44:02.229-0500")
@StaticMetamodel(Address.class)
public class Address_ 
{
    public static volatile SingularAttribute<Address, String> addressID;
    public static volatile SingularAttribute<Address, Integer> addressNumber;
    public static volatile SingularAttribute<Address, String> streetName;
    public static volatile SingularAttribute<Address, String> streetType;
    public static volatile SingularAttribute<Address, String> building;
    public static volatile SingularAttribute<Address, String> floor;
    public static volatile SingularAttribute<Address, String> unit;
    public static volatile SingularAttribute<Address, String> landmarkName;
    public static volatile SingularAttribute<Address, String> city;
    public static volatile SingularAttribute<Address, String> state;
    public static volatile SingularAttribute<Address, Integer> zipcode;
}

package dataAccess.customer;


import java.io.Serializable;
import java.lang.Integer;
import java.lang.String;
import javax.persistence.*;


/**
 * Entity implementation class for Entity: Address
 * 
 */
@Entity
@Table(name="ADDRESS")
public class Address
implements Serializable
{

    private String addressID;

    private Integer addressNumber;

    private String streetName;

    private String streetType;

    private String building;

    private String floor;

    private String unit;

    private String landmarkName;

    private String city;

    private String state;

    private Integer zipcode;

    private static final long serialVersionUID = 1L;


    public Address()
    {

    }

    @Id
    public String getAddressID()
    {
        return addressID;
    }

    public void setAddressID(String addressID)
    {
        this.addressID = addressID;
    }

    public Integer getAddressNumber()
    {
        return this.addressNumber;
    }

    public void setAddressNumber(Integer addressNumber)
    {
        this.addressNumber = addressNumber;
    }

    public String getStreetName()
    {
        return this.streetName;
    }

    public void setStreetName(String streetName)
    {
        this.streetName = streetName;
    }

    public String getStreetType()
    {
        return this.streetType;
    }

    public void setStreetType(String streetType)
    {
        this.streetType = streetType;
    }

    public String getBuilding()
    {
        return this.building;
    }

    public void setBuilding(String building)
    {
        this.building = building;
    }

    public String getFloor()
    {
        return this.floor;
    }

    public void setFloor(String floor)
    {
        this.floor = floor;
    }

    public String getUnit()
    {
        return this.unit;
    }

    public void setUnit(String unit)
    {
        this.unit = unit;
    }

    public String getLandmarkName()
    {
        return this.landmarkName;
    }

    public void setLandmarkName(String landmarkName)
    {
        this.landmarkName = landmarkName;
    }

    public String getCity()
    {
        return this.city;
    }

    public void setCity(String city)
    {
        this.city = city;
    }

    public String getState()
    {
        return this.state;
    }

    public void setState(String state)
    {
        this.state = state;
    }

    public Integer getZipcode()
    {
        return this.zipcode;
    }

    public void setZipcode(Integer zipcode)
    {
        this.zipcode = zipcode;
    }

}

这是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="DataModelAccess" transaction-type="RESOURCE_LOCAL">
        <class>dataAccess.customer.Person</class>
        <class>dataAccess.customer.Address</class>
        <class>dataAccess.customer.PhoneNumber</class>
        <class>dataAccess.customer.Customer</class>
        <class>dataAccess.customer.TwoFieldTest</class>
        <exclude-unlisted-classes>true</exclude-unlisted-classes>
        <properties>
            <property name="eclipselink.ddl-generation.output-mode" value="database"></property>
            <property name="eclipselink.target-database" value="derby"/>
            <property name="eclipselink.target-server" value="None"/>
            <property name="eclipselink.exclude-eclipselink-orm" value="true"/>
            <property name="eclipselink.jdbc.batch-writing" value="JDBC"/>
            <property name="eclipselink.jdbc.cache-statements" value="true"/>
            <property name="eclipselink.jdbc.native-sql" value="true"/>
            <property name="javax.persistence.jdbc.url" value="jdbc:derby://localhost:1527/sample;create=true"/>
            <property name="javax.persistence.jdbc.driver" value="org.apache.derby.jdbc.ClientDriver"/>
            <property name="eclipselink.jdbc.bind-parameters" value="false"/>
            <property name="eclipselink.jdbc.exclusive-connection.mode" value="Transactional"/>
            <property name="eclipselink.orm.validate.schema" value="true"/>
            <property name="eclipselink.orm.throw.exceptions" value="true"/>
            <property name="eclipselink.ddl-generation" value="drop-and-create-tables"/>
        </properties>
    </persistence-unit>
</persistence>

评语:
打电话

em.flush(); 

正是我所做的,以检查数据是否在会话中持续存在(它没有)。换句话说,当我运行方法“runTest()”时,我得到了正确的打印语句,在原始的 runTest() 方法下。我已经发布了修改后的“runTest()”方法(参见://reassign“comment”)。现在,当我有一个客户时,我构建了三个实体:地址、电话号码和个人,客户可以通过在实体管理器中“在数据库中”查找其他三个实体来实例化。但是,如果我注释掉所有内容,除了在数据库中查找三个实体并创建新客户的代码之外,我发现我无法从数据库中获取数据。

看起来像这样:

    Customer c = new Customer();
    c.setAddress(em.find(Address.class, "1"));
    c.setPhoneNumber(em.find(PhoneNumber.class, "1"));
    c.setName(em.find(Person.class, "1"));
    c.setCustomerID("123");
    em.persist(c);
    */
    Customer actual = em.find(Customer.class, "123");

当我在 em.persist(c) 之前注释掉所有内容时,我没有得到任何实际的客户。

通常,我得到这个:

Customer: 
Name: 
Mr. Howard T Stewart III

Address: 
1746 Howard Court
Lennyville, CT 73625

Phone: 
(215) 256-4563

但是当我注释掉一切直到

Customer actual = em.find(Customer.class, "123"); 

(现在..我在上一行中实例化了 em,但我现在没有创建人员、电话号码或地址。)

然后,..我明白了,

(actual == null) 

评估为真。

我是否滥用了“find()”命令?我是否应该做其他事情来加载与数据库的当前连接或其他事情(就通过 em (em.method()) 的命令而言)?

请记住,这里没有 Java EE 容器。我只是在eclipse中这样做,在j2se程序中运行主要方法,在eclipse中的JPA项目中,使用eclipselink 2.3。但这不是 EJB,也不是 ManagedBeans 等。

所以..

我找到了这个:

@Resource
UserTransaction utx;
...
try {
utx.begin();
bookDBAO.buyBooks(cart);
utx.commit();
} catch (Exception ex) {
try {
utx.rollback();
} catch (Exception exe) {
System.out.println("Rollback failed: "+exe.getMessage());
}
...

不幸的是,在我进入 java ee 教程的 Web 部分之前,我没有找到任何关于 UserTransaction 的信息,因此,在 em.persist( ) 就是一切。此外,@Resource 可能无法在 Java EE 容器之外工作。


丹尼尔:谢谢你的评论,它给了我需要的答案。

即使我找到了上述项目,虽然我正在这样做:

em.getTransaction().begin();

// .. set fields of address .. 
em.persist(address);    

em.getTransaction().commit();
em.close();

它仍然无法正常工作。当我将persistence.xml 文件更改为仅创建表时,测试方法运行正确,并且当我注释掉所有内容但从数据库中检索客户时,它也正确返回。

我也试过:

SELECT * FROM <SCHEMA>.ADDRESS;

这也很好。非常感谢,因为在教程中很难找到实体管理器由于“DROP AND CREATE TABLES”指令而实际在做什么。

4

2 回答 2

2

在你的 persistence.xml 你有,

<property name="eclipselink.ddl-generation" value="drop-and-create-tables"/>

这意味着每次您创建一个新的 EntityManagerFactory 时,您都将重新创建您的数据库,从而丢失所有数据。

要么删除它,要么将其更改为“create-tables”以仅创建。

对于您的第一个问题,请尝试 ., iexaddress

于 2012-05-22T15:41:56.173 回答
0

由于您使用的是 Eclipselink JPA,因此如果您使用标准的“createQuery”方法,它将不遵循 SQL 查询的标准语法您需要使用这个:

select t from table1 t

代替

select * from table1

它遵循 JPQL 的语法。有关更多信息,请参阅此链接

但是如果你想使用原生 sql 方法,请使用管理器实例中的“createNativeMethod”

于 2014-03-18T18:52:45.933 回答