如何仅在数据库,模式和表尚不存在时自动创建它们

Zzi*_*ium 6 hibernate jpa web-applications h2

我想创建一个简单的webapp

  • 允许远程客户端跟踪发布请求中的某些内容
  • 将所有跟踪保留在轻量级数据库中
  • 在get请求中返回所有跟踪

关于数据库,我想

  1. 将其位置放在我的webapp的属性文件中(并将此位置用于persistence.xml中设置的hibernate.location.url)
  2. 如果数据库尚不存在,则使用模式和表创建数据库
  3. 使用现有的数据库和模式以及表和数据(如果存在)

所以我创建了一个maven项目:

的pom.xml

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>org.my.tracker</groupId>
    <artifactId>tracker-webapp</artifactId>
    <version>0.1-SNAPSHOT</version>
    <packaging>war</packaging>
    <properties>
        <hibernate.version>4.3.8.Final</hibernate.version>
        <h2.version>1.4.185</h2.version>
    </properties>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-eclipse-plugin</artifactId>
                <version>2.9</version>
                <configuration>
                    <downloadSources>true</downloadSources>
                    <downloadJavadocs>false</downloadJavadocs>
                </configuration>
            </plugin>
            <!-- Set a compiler level -->
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-war-plugin</artifactId>
                <version>2.6</version>
            </plugin>
        </plugins>
    </build>

    <dependencies>
        <!-- Servlet API -->
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>3.1.0</version>
            <scope>provided</scope>
        </dependency>
        <!-- JPA Provider (Hibernate) -->
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-entitymanager</artifactId>
            <version>${hibernate.version}</version>
        </dependency>
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-core</artifactId>
            <version>${hibernate.version}</version>
        </dependency>
        <!-- Database (H2) -->
        <dependency>
            <groupId>com.h2database</groupId>
            <artifactId>h2</artifactId>
            <version>${h2.version}</version>
        </dependency>

    </dependencies>

</project>
Run Code Online (Sandbox Code Playgroud)

SRC /主/资源/ META-INF/persistence.xml中

<?xml version="1.0" encoding="UTF-8" ?>
<persistence 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_1_0.xsd" version="1.0">

  <persistence-unit name="thePersistenceUnit" transaction-type="RESOURCE_LOCAL">
     <provider>org.hibernate.ejb.HibernatePersistence</provider>

    <class>org.my.tracker.Event</class>

    <properties>
        <property name="connection.driver_class" value="org.h2.Driver"/>
        <property name="hibernate.connection.url" value="jdbc:h2:./db/repository"/>
        <property name="hibernate.dialect" value="org.hibernate.dialect.H2Dialect"/>
        <property name="hibernate.hbm2ddl.auto" value="create"/>
        <property name="hibernate.show_sql" value="true" />
    </properties>
</persistence-unit>
</persistence>
Run Code Online (Sandbox Code Playgroud)

的src /主/ web应用/ WEB-INF/web.xml中

<?xml version="1.0" encoding="ISO-8859-1"?>
<web-app 
   xmlns="http://java.sun.com/xml/ns/javaee" 
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" 
   version="2.5">
  <servlet>
    <servlet-name>orc-event</servlet-name>
    <servlet-class>org.my.tracker.EventServlet</servlet-class>
  </servlet>
  <servlet-mapping>
    <servlet-name>orc-event</servlet-name>
    <url-pattern>/event/*</url-pattern>
  </servlet-mapping>
</web-app>
Run Code Online (Sandbox Code Playgroud)

的src/main/JAVA /组织/我/跟踪器/ EventServlet.java

package org.my.tracker;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.List;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.gson.Gson;

public class EventServlet extends HttpServlet {
    private static final Logger LOGGER = LoggerFactory.getLogger(EventServlet.class);

    private static final long serialVersionUID = 1L;
    public static final String HTML_START="<html><body>";
    public static final String HTML_END="</body></html>";
    private static EntityManager manager;

    static {
        EntityManagerFactory factory = Persistence.createEntityManagerFactory("thePersistenceUnit");
        manager = factory.createEntityManager();
    }
    /**
     * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
     */
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        PrintWriter out = response.getWriter();
        try {
            manager.getTransaction().begin();
            @SuppressWarnings("unchecked")
            List<Event> events = manager.createQuery("from Event").getResultList();
            Gson gson = new Gson();
            out.print(gson.toJson(events));
            manager.getTransaction().commit();
        } catch (Exception e) {
            manager.getTransaction().rollback();
        }
    }

    /**
     * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
     */
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String body = (String)request.getParameter("body");
        if (null != body) {
            try {
                manager.getTransaction().begin();
                Event event = new Event();
                event.setBody(body);
                manager.persist(event);
                manager.getTransaction().commit();
            } catch (Exception e) {
                manager.getTransaction().rollback();
            }
        } else {
            LOGGER.error("null body, cannot track");
        }
    }

}
Run Code Online (Sandbox Code Playgroud)

的src/main/JAVA /组织/我/跟踪器/ Event.java

package org.my.tracker;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;

@Entity
public class Event {
    @Id
    @GeneratedValue
    private Integer id;
    private String body;

    public Integer getId() {
        return id;
    }

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

    public String getBody() {
        return body;
    }

    public void setBody(String body) {
        this.body = body;
    }

}
Run Code Online (Sandbox Code Playgroud)

好吧,多亏了所有这些强大的工具,这很简单,工作得很好,除了我不能

  1. 看看如何通过属性设置我的数据库位置(只能通过tomcat server.xml调整(我不能为它做的不属于我)或spring(这是在我的项目中放一些弹簧的一个很弱的理由)只有1个属性注入...),

  2. (和3.)每次启动我的webapp时,我的数据库都是空的.当然,你会告诉我,因为我在persistence.xml中加上了"create"值

        <property name="hibernate.hbm2ddl.auto" value="create"/>
    
    Run Code Online (Sandbox Code Playgroud)

好吧,我可以

  • create-drop:在我的情况下与"create"结果相同(这是预期的,因为"drop"意味着很像"将所有东西都关闭"的反面:D)
  • none:但是在第一次未部署webapp时不会创建数据库
  • 验证:我可以在webapp重启时恢复我的内容,但是没有,首先如果它不存在,则不会创建数据库模式和表,我的webapp无法使用它:)

所以我希望尽可能保持事情的简单,是否可能?

如果没有其他方法除了编写一个sql脚本来初始化我的数据库,只有它不存在,我将不胜感激,你提供代码或一些提示,因为我在这个领域是一个完全愚蠢的.

编辑

因此,当我提出一个评论时,实际上,"更新"是我正在寻找的价值.像魅力一样工作.

除了spring之外,我没有找到任何其他方式来传递变量而不是常量值.但是,嘿,这在这样的领域是相当普遍的:)(并弹簧它的orm层也)

Nei*_*ton 4

JPA 2.1 提供了用于创建模式的标准属性。寻找

javax.persistence.schema-generation.database.action
Run Code Online (Sandbox Code Playgroud)

并设置为createdrop-and-create。同样,还有用于在 EMF 启动时执行脚本的属性。任何兼容的 JPA 实现的文档都应该记录它们

  • 如果我用 &lt;property name="javax.persistence.schema- Generation.database.action" value="create"/&gt; 替换 &lt;property name="hibernate.hbm2ddl.auto" value="create"/&gt; ,它会失败第二次启动是因为它尝试创建事件表,尽管它已经存在。如果我设置 drop-and-create ,它会清除现有的表,并且我会丢失已经存在的持久事件。 (2认同)