Java Payara Micro忽略persistence.xml中的连接url

Java Payara Micro忽略persistence.xml中的连接url,java,java-8,h2,payara-micro,Java,Java 8,H2,Payara Micro,我正在编写一个Payara Micro web应用程序,它应该连接到persistence.xml中定义的数据库。它应该连接到的数据库是本地计算机上的一个文件,在项目启动时,它不存在。据我所知,H2应该在第一次连接时为数据库创建一个文件 persistence.xml如下所示: <?xml version="1.0" encoding="UTF-8"?> <persistence version="2.1"

我正在编写一个Payara Micro web应用程序,它应该连接到
persistence.xml
中定义的数据库。它应该连接到的数据库是本地计算机上的一个文件,在项目启动时,它不存在。据我所知,H2应该在第一次连接时为数据库创建一个文件

persistence.xml
如下所示:

<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.1"
             xmlns="http://xmlns.jcp.org/xml/ns/persistence"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd">
    <persistence-unit name="com.danjbower_h2test_war_0.0.1PU"
                      transaction-type="JTA">
        <provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>

        <class>com.danjbower.h2test.Test</class>

        <properties>
            <property name="hibernate.connection.driver_class" value="org.h2.Driver" />
            <property name="hibernate.connection.url" value="jdbc:h2:file:C:/databases/testdb" />
            <property name="hibernate.connection.username" value="sa" />
            <property name="hibernate.connection.password" value="" />

            <property name="hibernate.show_sql" value="true" />
            <property name="hibernate.format_sql" value="true" />
            <property name="hibernate.hbm2ddl.auto" value="update" />
            <property name="hibernate.dialect" value="org.hibernate.dialect.H2Dialect" />
            <property name="hibernate.temp.use_jdbc_metadata_defaults" value="false" />
            <property name="hibernate.transaction.jta.platform" value="SunOne" />
        </properties>
    </persistence-unit>
</persistence>
Test.java

package com.danjbower.h2test;

import java.util.Objects;
import javax.persistence.Basic;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
import javax.validation.constraints.NotNull;
import javax.xml.bind.annotation.XmlRootElement;

@Entity
@Table(name = "Tests")
@XmlRootElement
public class Test
{
    @Id
    @Column(name = "Id", unique = true)
    @Basic(optional = false)
    @NotNull
    private Integer id = 0;

    public Integer getId()
    {
        return id;
    }

    public void setId(Integer id)
    {
        this.id = id;
    }

    @Override
    public int hashCode()
    {
        return id;
    }

    @Override
    public boolean equals(Object obj)
    {
        if (this == obj)
        {
            return true;
        }

        if (obj == null)
        {
            return false;
        }

        if (getClass() != obj.getClass())
        {
            return false;
        }

        final Test other = (Test) obj;

        return Objects.equals(id, other.id);
    }

    @Override
    public String toString()
    {
        return "Test (Id: " + id + ")";
    }
}
StartUp.java

package com.danjbower.h2test;

import javax.annotation.PostConstruct;
import javax.ejb.Singleton;
import javax.ejb.Startup;
import javax.ejb.TransactionAttribute;
import javax.ejb.TransactionAttributeType;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;

@Startup
@Singleton
public class StartUp
{
    @PersistenceContext(unitName = "com.danjbower_h2test_war_0.0.1PU")
    private EntityManager entityManager;

    @PostConstruct
    @TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
    public void init()
    {
        Test test = new Test();
        test.setId(4);
        entityManager.persist(test);
    }
}
显示它运行命令的日志

Hibernate: 
    
    create table Tests (
       Id integer not null,
        primary key (Id)
    )

Hibernate: 
    insert 
    into
        Tests
        (Id) 
    values
        (?)


[2021-03-07T03:37:03.511+0000] [] [INFO] [] [PayaraMicro] [tid: _ThreadID=1 _ThreadName=main] [timeMillis: 1615088223511] [levelValue: 800] 
{
    "Instance Configuration": {
        "Host": "192.168.1.12",
        "Http Port(s)": "8080",
        "Https Port(s)": "",
        "Instance Name": "Hilarious-Boxfish",
        "Instance Group": "MicroShoal",
        "Hazelcast Member UUID": "ae8dbc3a-b361-4dd6-bbba-762e620f96a8",
        "Deployed": [
            {
                "Name": "H2Test-0.0.1",
                "Type": "war",
                "Context Root": "/H2Test"
            }
        ]
    }
}

[2021-03-07T03:37:03.513+0000] [] [INFO] [] [PayaraMicro] [tid: _ThreadID=1 _ThreadName=main] [timeMillis: 1615088223513] [levelValue: 800] 
Payara Micro URLs:
http://192.168.1.12:8080/H2Test

问题是您使用的是
transaction type=“JTA”
,这意味着数据源是从Payara Micro检索的,而不是由Hibernate根据您指定的属性创建的

您应该将
transaction type=“JTA”
更改为
transaction type=“RESOURCE\u LOCAL”
。这应该会解决问题,并按照您的期望行事


现在的情况是Hibernate请求Payara Micro提供数据源,并忽略了
Hibernate.connection
属性。您没有指定任何数据源JNDI名称(例如使用
hibernate.connection.datasource
),因此它将检索默认数据源。Payara Micro中的默认数据源用于存储在临时目录中的H2数据库。

可以在此处找到该项目的工作示例


这个问题的一个解决方案是设置
jta数据源
,而不是使用
hibernate.connection.*
properties

这意味着将
persistence.xml
更改为

<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.1"
             xmlns="http://xmlns.jcp.org/xml/ns/persistence"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd">
    <persistence-unit name="com.danjbower_h2test_war_0.0.1PU"
                      transaction-type="JTA">
        <provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>

        <jta-data-source>java:app/TestDb</jta-data-source>
        <exclude-unlisted-classes>false</exclude-unlisted-classes>

        <properties>
            <property name="hibernate.show_sql" value="true" />
            <property name="hibernate.format_sql" value="true" />
            <property name="hibernate.hbm2ddl.auto" value="update" />
            <property name="hibernate.dialect" value="org.hibernate.dialect.H2Dialect" />
            <property name="hibernate.transaction.jta.platform" value="SunOne" />
        </properties>
    </persistence-unit>
</persistence>

最初我把它放在
web.xml
中作为

<data-source>
    <name>java:app/TestDb</name>
    <class-name>org.h2.Driver</class-name>
    <url>jdbc:h2:file:C:/databases/TestDb</url>
    <user>sa</user>
    <password></password>
</data-source>

java:app/TestDb
org.h2.Driver
jdbc:h2:file:C:/databases/TestDb
sa

然而,当我这样做时,我遇到了一个错误,它说没有设置密码。与此非常相似。

谢谢您的回答。我最初将其设置为RESOURCE_LOCAL,但问题是它引发了一个异常
java.lang.RuntimeException:module[h2test-0.0.1]中的持久性上下文引用名称[com.danjbower.h2test.StartUp/entityManager]解析为一个名为[com.danjbower_h2test_war_0.0.1PU]的持久性单元,其类型为RESOURCE_LOCAL。只有事务类型为JTA的持久化单元才能用作容器管理的实体管理器。请验证您的应用程序。
我没有注意到您注入了EntityManager。然后你需要使用JTA。但是在这种情况下,persistence.xml文件中指定的连接属性在我编写时被忽略,您需要创建一个托管数据源并在那里指定它们。您在回答中描述它的方式很好-您需要在web.xml(标准方式)或payara-resources.xml(仅适用于payara)中指定托管数据源。如果您在web.xml中使用空密码指定数据源,那么Payara和GlassFish中似乎存在一个bug,因此在这里使用Payara-resources.xml是有意义的。谢谢。我以前没有听说过JNDI。你提到这件事让我找到了正确的方向,如何把它往上推。悬赏结束了,决定把它授予这个人,因为这足以让我解决这个问题
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE resources PUBLIC "-//Payara.fish//DTD Payara Server 4 Resource Definitions//EN" "https://raw.githubusercontent.com/payara/Payara-Community-Documentation/master/docs/modules/ROOT/pages/schemas/payara-resources_1_6.dtd">
<resources>
    <jdbc-resource pool-name="TestDb"
                   jndi-name="java:app/TestDb"
                   enabled="true" />

    <jdbc-connection-pool datasource-classname="org.h2.jdbcx.JdbcDataSource"
                          name="TestDb"
                          res-type="javax.sql.DataSource">
        <property name="URL" value="jdbc:h2:file:C:/databases/TestDb" />
        <property name="User" value="sa" />
        <property name="Password" value="" />
    </jdbc-connection-pool>
</resources>
<data-source>
    <name>java:app/TestDb</name>
    <class-name>org.h2.Driver</class-name>
    <url>jdbc:h2:file:C:/databases/TestDb</url>
    <user>sa</user>
    <password></password>
</data-source>