JPA объекты не сохранены в базе данных - PullRequest
2 голосов
/ 23 июня 2019

У меня есть приложение JEE, работающее на WildFly 10.1.0 с использованием JPA и MySQL.

У меня есть служба без сохранения состояния, которая представляет веб-сканер, который извлекает контент с данного веб-сайта, создает структурированные объекты POJO и сохраняет эти объекты в базе данных. Моя проблема заключается в том, что, хотя исключения не создаются, сущности JPA не сохраняются в базе данных. Мой веб-сканер без сохранения состояния:

@Stateless
public class ImmoweltBot {

    public static final String URL = "https://www.immowelt.at/";
    public static final String queryURL = URL + "/liste/wien/wohnungen/mieten?sort=relevanz";


    @Inject
    private HomeToDealDBService homeToDealDBService;


    @PostConstruct
    public void initialize() {
        System.setProperty("webdriver.chrome.driver", "C:\\Temp\\chromedriver.exe");
    }


    public void crawl () throws Exception {

        String URLPage = StringUtils.EMPTY;
        int page = 1;
        int totalNumberOfEntities = 6000;
        int numberOfEntitiesFound = 0;

        List<WebElement> elemnts = new ArrayList<>();

        WebDriver webDriver = new ChromeDriver();

        outer:
        while (numberOfEntitiesFound < totalNumberOfEntities){

        webDriver.get(queryURL + URLPage);      


        final int totalNumberOfKeyDowns = 190;
        int keyDownTries = 0;
        while ((++keyDownTries < totalNumberOfKeyDowns)) {
            webDriver.findElement(By.tagName("body")).sendKeys(Keys.DOWN);

        }
        elemnts = webDriver.findElements(By.xpath("//*[contains(@class, 'clear relative js-listitem')]"));

        WebElement elem = webDriver.findElement(By.xpath("//*[contains(@class, 'ellipsis margin_none')]"));
        totalNumberOfEntities = Utils.parseNumber(elem.getText()).intValue();

        for (int i = 0; i < elemnts.size(); i++) {
            WebElement divListItemClear = elemnts.get(i);
            HomeToDeal homeToRent = new HomeToDeal();
            String exposeURL = divListItemClear.findElement(By.tagName("a")).getAttribute("href");
            homeToRent.setURL(exposeURL);

            try {
                homeToDealDBService.saveEntity(homeToRent);
                Logger.getLogger(ImmoweltBot.class).info("Entity " +  homeToRent + " saved");
            }
            catch (EntityExistsException eex){
                Logger.getLogger(ImmoweltBot.class).warn("Entity already saved " + homeToRent.getURL());
                break outer;
            }
        }
        URLPage = "&cp="+ (++page);
        numberOfEntitiesFound+=elemnts.size();
     }
    }
}

Мой класс HomeToDealDBService:

@Stateless
public class HomeToDealDBService {

    @PersistenceContext
    private EntityManager em;


    @TransactionAttribute(TransactionAttributeType.REQUIRED) 
    public void saveEntity(HomeToDeal homeToDeal) throws EntityExistsException{
        this.em.persist(homeToDeal);
    }

}

Мой класс POJO:

@Entity
@Table(name = "home")
@Access(AccessType.FIELD)
public class HomeToDeal implements Comparable<HomeToDeal>, Serializable {

    private static final long serialVersionUID = 1L;

    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE)
    @Column(name = "id", updatable=false, nullable=false)
    private int id;
    private String URL;
    private String mainImage;
    private String imageFolderPath;
    private String description;
    private byte noRooms;
    private BigDecimal nutzflaeche; // area in sqm
    private BigDecimal wohnflaeche;

Мой сервлет, который запускает сканер:

@WebServlet("/test")
public class TestServlet extends HttpServlet {

    private static final long serialVersionUID = 1L;

    @Inject
    private ImmoweltBot immoweltBot;

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException {
        try {
            immoweltBot.crawl();
        } catch (Exception e) {
            throw new ServletException(e);
        }
    }

}

My 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="IamOK" transaction-type="JTA">
         <description>Home to Deal</description>
         <provider>org.hibernate.ejb.HibernatePersistence</provider>

         <jta-data-source>java:/MySqlDS_HomeToDeal</jta-data-source> 
         <properties>
                <property name="hibernate.dialect" value = "org.hibernate.dialect.MySQLDialect" />
                <property name="hibernate.cache.provider_class" value="org.hibernate.cache.NoCacheProvider"/>  
                <property name="hibernate.show_sql" value="true"></property>  
                <property name="hibernate.max_fetch_depth" value="3" />
                <property name="hibernate.hbm2ddl.auto" value="create"/> 
                <property name="hibernate.show_sql" value="true" />
            </properties>
       </persistence-unit>

    </persistence>

мой источник данных в автономном.FML WildFly:

    <datasource jta="true" jndi-name="java:/MySqlDS_HomeToDeal" pool-name="MySqlDS_HomeToDeal" enabled="true" use-java-context="true" use-ccm="true">
                <connection-url>jdbc:mysql://localhost:3306/homeToDeal?autoReconnect=true</connection-url>
                <driver>mysql</driver>
                <transaction-isolation>TRANSACTION_READ_COMMITTED</transaction-isolation>
                <pool>
                    <min-pool-size>10</min-pool-size>
                    <max-pool-size>100</max-pool-size>
                    <prefill>true</prefill>
                </pool>
                <security>
                    <user-name>homeToDealuser</user-name>
                    <password>homeToDeal123</password>
                </security>
                <validation>
                    <check-valid-connection-sql>SELECT 1</check-valid-connection-sql>
                </validation>
                <timeout>
                    <idle-timeout-minutes>0</idle-timeout-minutes>
                    <query-timeout>600</query-timeout>
                </timeout>
                <statement>
                    <prepared-statement-cache-size>100</prepared-statement-cache-size>
                    <share-prepared-statements>true</share-prepared-statements>
                </statement>
            </datasource>

Результат в базе данных:

select * from home;

enter image description here

Мой 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/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>seller</groupId>
    <artifactId>home.digest</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>war</packaging>

    <name>home.digest Maven Webapp</name>
    <!-- FIXME change it to the project's website -->
    <url>http://maven.apache.org</url>
    <repositories>
        <repository>
            <id>prime-repo</id>
            <name>Prime Repo</name>
            <url>http://repository.primefaces.org</url>
        </repository>
    </repositories>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
    </properties>

    <dependencies>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.11</version>
            <scope>test</scope>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.seleniumhq.selenium/selenium-java -->
        <dependency>
            <groupId>org.seleniumhq.selenium</groupId>
            <artifactId>selenium-java</artifactId>
            <version>3.141.59</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.apache.httpcomponents/httpcore -->
        <dependency>
            <groupId>org.apache.httpcomponents</groupId>
            <artifactId>httpcore</artifactId>
            <version>4.4.10</version>
        </dependency>
        <dependency>
            <groupId>org.apache.httpcomponents</groupId>
            <artifactId>httpclient</artifactId>
            <version>4.5.6</version>
        </dependency>
        <dependency>
            <groupId>org.primefaces</groupId>
            <artifactId>primefaces</artifactId>
            <version>6.2</version>
        </dependency>
        <dependency>
            <groupId>org.jboss.logging</groupId>
            <artifactId>jboss-logging</artifactId>
            <version>3.0.1.GA</version>
            <scope>compile</scope>
            <optional>true</optional>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.hibernate.javax.persistence/hibernate-jpa-2.1-api -->
        <dependency>
            <groupId>org.hibernate.javax.persistence</groupId>
            <artifactId>hibernate-jpa-2.1-api</artifactId>
            <version>1.0.2.Final</version>
            <scope>provided</scope>
        </dependency>
        <!-- https://mvnrepository.com/artifact/javax.enterprise/cdi-api -->
        <dependency>
            <groupId>javax.enterprise</groupId>
            <artifactId>cdi-api</artifactId>
            <version>2.0.SP1</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>org.jboss.as</groupId>
            <artifactId>jboss-as-web</artifactId>
            <version>7.1.1.Final</version>
            <scope>compile</scope>
            <optional>true</optional>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.jboss.spec.javax.ejb/jboss-ejb-api_3.2_spec -->
        <dependency>
            <groupId>org.jboss.spec.javax.ejb</groupId>
            <artifactId>jboss-ejb-api_3.2_spec</artifactId>
            <version>1.0.2.Final</version>
            <scope>provided</scope>
        </dependency>

        <!-- https://mvnrepository.com/artifact/com.google.cloud/google-cloud-translate -->
        <dependency>
            <groupId>com.google.cloud</groupId>
            <artifactId>google-cloud-translate</artifactId>
            <version>1.61.0</version>
        </dependency>
        <dependency>
            <!-- jsoup HTML parser library @ https://jsoup.org/ -->
            <groupId>org.jsoup</groupId>
            <artifactId>jsoup</artifactId>
            <version>1.11.3</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.apache.commons/commons-lang3 -->
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-lang3</artifactId>
            <version>3.8.1</version>
        </dependency>
    </dependencies>

    <build>
        <finalName>home.digest</finalName>
        <pluginManagement><!-- lock down plugins versions to avoid using Maven 
                defaults (may be moved to parent pom) -->
            <plugins>
                <plugin>
                    <artifactId>maven-clean-plugin</artifactId>
                    <version>3.1.0</version>
                </plugin>
                <!-- see http://maven.apache.org/ref/current/maven-core/default-bindings.html#Plugin_bindings_for_war_packaging -->
                <plugin>
                    <artifactId>maven-resources-plugin</artifactId>
                    <version>3.0.2</version>
                </plugin>
                <plugin>
                    <artifactId>maven-compiler-plugin</artifactId>
                    <version>3.8.0</version>
                </plugin>
                <plugin>
                    <artifactId>maven-surefire-plugin</artifactId>
                    <version>2.22.1</version>
                </plugin>
                <plugin>
                    <artifactId>maven-war-plugin</artifactId>
                    <version>3.2.2</version>
                </plugin>
                <plugin>
                    <artifactId>maven-install-plugin</artifactId>
                    <version>2.5.2</version>
                </plugin>
                <plugin>
                    <artifactId>maven-deploy-plugin</artifactId>
                    <version>2.8.2</version>
                </plugin>
            </plugins>
        </pluginManagement>
    </build>
</project>

Если я только поменяю свой TestServlet следующим образом:

@WebServlet("/test")
public class TestServlet extends HttpServlet {

    @Inject
    private HomeToDealDBService homeToDealDBService;

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException {
        try {
            HomeToDeal home = new HomeToDeal();
            home.setURL("alabale");
            homeToDealDBService.saveEntity(home);
        } catch (Exception e) {
            throw new ServletException(e);
        }
    }
}

Это работает, хотя. В чем может быть проблема?

Ответы [ 2 ]

1 голос
/ 24 июня 2019

Проблемой в этом случае была аннотация

@TransactionAttribute(TransactionAttributeType.REQUIRED)

выше метода

public void saveEntity(HomeToDeal homeToDeal) throws EntityExistsException{
    this.em.persist(homeToDeal);
}

В этом случае при вызове из метода ImmoweltBot.crawl () saveEntity () фактически вызывается из той же транзакции, пока метод ImmoweltBot.crawl () не завершится. Вот почему сущности не сохраняются в базе данных до конца транзакции - значит, до завершения метода ImmoweltBot.crawl (). Делать каждую сущность сохраняемой отдельно означает сохранить каждую сущность в отдельной транзакции. Это может произойти, если я изменю аннотацию метода saveEntity () следующим образом:

@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW) 
public void saveEntity(HomeToDeal homeToDeal) throws EntityExistsException{
    this.em.persist(homeToDeal);
}

это на самом деле именно то, что я хотел - что если сохранение определенной сущности не удастся, это не повлияет на сохранение остальных сущностей.

0 голосов
/ 23 июня 2019

<property name="hibernate.hbm2ddl.auto" value="update"/> может решить проблему.

Если вы введете value="create", это означает, что каждый раз, когда вы запускаете приложение, вы снова и снова создаете таблицу.

...