使用JPA为应用添加持久层

使用JPA为应用添加持久层

第一步:创建基类
让我们首先为我们的域模型创建一个基类。这通重点内容常被认为是最佳实践,因为它为我们提供了一个中心位置,可以在以后添加要在所有域模型对象之间共享的通用功能。为此,从项目的上下文菜单项中选择New> Class,weatherapp并提供以下详细信息:
• 包名: com.sap.hana.cloud.samples.weatherapp.model
• 类名: BaseObject

这里写图片描述
第二步:替换代码
该代码就是BaseObject的内容

package com.sap.hana.cloud.samples.weatherapp.model;
import java.util.Date;
import java.util.UUID;
import javax.persistence.Column;
import javax.persistence.Id;
import javax.persistence.MappedSuperclass;
import javax.persistence.PrePersist;
import javax.persistence.PreUpdate;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
/**
 * Base class for all domain model objects.
 */
@MappedSuperclass
public abstract class BaseObject 
{
    /**
     * The (globally unique) ID of the object.
     */
    @Id
    @Column(name="GUID", length = 36)
    private String guid = UUID.randomUUID().toString();
/**
     * The {@link Date} the object was created at.
     */
    @Temporal(TemporalType.TIMESTAMP)
    @Column(name="CREATION_DATE", updatable = false)
    private Date createdAt = null;

    /**
     * The {@link Date} the object was last modified at.
     */
    @Temporal(TemporalType.TIMESTAMP)
    @Column(name="MODIFICATION_DATE")
    private Date lastModifiedAt = null;
/**
     * ID of the user who created the object.
     */
    @Column(name="CREATED_BY", updatable = false, length = 20)
    private String createdBy = null;

    /**
     * ID of the user who was the last to modify the object.
     */
    @Column(name="MODIFIED_BY", length = 20)
    private String lastModifiedBy = null;

    /**
     * Life-cycle event callback, which automatically sets the last modification date.  
     */
    @PreUpdate
    protected void updateAuditInformation() 
    {
        lastModifiedAt = new Date();

        // TODO - obtain currently logged-on user
    }
/**
     * Life-cycle event callback, which automatically creates a unique ID for the object
     * and populates its audit information.  
     */
    @PrePersist
    protected void generateAuditInformation() 
    {   
        final Date now = new Date();

        createdAt = now;
        lastModifiedAt = now;

        // TODO - obtain currently logged-on user
    }
public String getGuid()
    {
        return this.guid;
    }
public void setGuid(String guid)
    {
        this.guid = guid;
    }

    public Date getCreatedAt()
    {
        return this.createdAt;
    }
public void setCreatedAt(Date createdAt)
    {
        this.createdAt = createdAt;
    }
public Date getLastModifiedAt()
    {
        return this.lastModifiedAt;
    }
public void setLastModifiedAt(Date lastModifiedAt)
    {
        this.lastModifiedAt = lastModifiedAt;
    }
public String getCreatedBy()
    {
        return this.createdBy;
    }
public void setCreatedBy(String createdBy)
    {
        this.createdBy = createdBy;
    }
public String getLastModifiedBy()
    {
        return this.lastModifiedBy;
    }
public void setLastModifiedBy(String lastModifiedBy)
    {
        this.lastModifiedBy = lastModifiedBy;
    }
}

第三步:创建另一个Java类
接下来,FavoriteCity.java使用相同的过程创建另一个Java类():
• 包名: com.sap.hana.cloud.samples.weatherapp.model
类名: FavoriteCity
这里写图片描述
替换该类的代码

package com.sap.hana.cloud.samples.weatherapp.model;
import java.io.Serializable;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.Table;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlRootElement;
/**
 * Model object representing a single {@link FavoriteCity} instance.
 * 
 * @author Matthias Steiner
 * @version 0.1
 */
@Entity
@Table(name = "WEATHERAPP_CITY")
@NamedQueries({@NamedQuery(name = "FavoriteCities", query = "SELECT c FROM FavoriteCity c"), 
               @NamedQuery(name = "FavoriteCityById", query = "SELECT c FROM FavoriteCity c WHERE c.id = :id")})
@XmlRootElement(name = "city")
@XmlAccessorType(XmlAccessType.FIELD)
public class FavoriteCity extends BaseObject implements Serializable
{
    /**
     * The <code>serialVersionUID</code> of the {@link FavoriteCity} class.
     */
    private static final long serialVersionUID = 1L;
@Column(name="ID", length = 36, nullable=true)
    String id = null;

    @Column(name="NAME", length = 128, nullable=true)
    String name = null;

    @Column(name="COUNTRY", length = 2, nullable=true)
    String countryCode = null;
public String getId()
    {
        return id;
    }

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

    public String getName() 
    {
        return name;
    }
public void setName(String name) 
    {
        this.name = name;
    }
public String getCountryCode() 
    {
        return countryCode;
    }
public void setCountryCode(String countryCode) 
    {
        this.countryCode = countryCode;
    }
}

第四步:创建配置文件
接下来,我们需要为持久层创建配置文件。根据Maven约定,这些非源代码工件应位于名为的单独源代码文件夹中:src/main/resources。因此,让我们通过Project Explorer中Java Resources节点上相应的上下文菜单条目创建该源文件夹:New> Source Folder。提供以下信息:
• 项目名: weatherapp
• 文件夹名称: src/main/resources
这里写图片描述
第五步:创建文件夹
打开此新创建的源文件夹的上下文菜单,然后选择“ 新建”>“其他”选项,然后选择“ 文件夹”选项。命名新文件夹META-INF(所有大写!),然后单击“ 完成”。
第六步:创建持久性xml文件
打开新创建的META-INF文件夹的上下文菜单,然后选择“ 新建”>“文件”。命名新文件persistence.xml,然后单击“ 完成”。
这里写图片描述
将以下XML内容复制并粘贴到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="application" transaction-type="RESOURCE_LOCAL">
<provider>
    org.eclipse.persistence.jpa.PersistenceProvider
</provider>
<class>
    com.sap.hana.cloud.samples.weatherapp.model.BaseObject
</class>
<class>
    com.sap.hana.cloud.samples.weatherapp.model.FavoriteCity
</class>
    <exclude-unlisted-classes>true</exclude-unlisted-classes>
    <properties>
      <property name="eclipselink.ddl-generation" value="create-tables"/>
  </properties>
</persistence-unit>
</persistence>

第七步:添加依赖项
接下来,我们需要为我们的pom.xml文件添加更多依赖项。在这种情况下,最重要的依赖是EclipseLink(我们选择的JPA实现)。但是,我们还需要声明Derby DB和Jackson的依赖关系(将数据转换为JSON所需的序列化框架,反之亦然。)
复制代码

<!-- EclipseLink (and JPA) -->
<dependency>
  <groupId>org.eclipse.persistence</groupId>
  <artifactId>eclipselink</artifactId>
  <version>2.5.0</version>
  </dependency>
<dependency>
   <groupId>org.eclipse.persistence</groupId>
   <artifactId>javax.persistence</artifactId>
   <version>2.1.0</version>
 </dependency>
 <!-- Derby -->
<dependency>
<groupId>org.apache.derby</groupId>
  <artifactId>derbyclient</artifactId>
  <version>10.9.1.0</version>
</dependency>
<dependency>
<groupId>org.apache.derby</groupId>
<artifactId>derby</artifactId>
<version>10.9.1.0</version>
</dependency>

<dependency>
<groupId>javax.ws.rs</groupId>
<artifactId>javax.ws.rs-api</artifactId>
<version>2.0</version>
</dependency>

<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-jaxrs</artifactId>
<version>${org.codehaus.jackson-version}</version>
</dependency>

我们还需要将Jackson版本作为属性添加到pom.xml文件的属性部分(正如我们在上一节中所做的那样)并保存您的更改

<org.codehaus.jackson-version>1.9.9</org.codehaus.jackson-version>

这里写图片描述
第八步:创建CRUD服务
下一步是创建相应的CRUD服务。为此,请创建一个包含以下详细信息的新类:
• 包名: com.sap.hana.cloud.samples.weatherapp.api
• 类名: FavoriteCityService
该类的代码内容

package com.sap.hana.cloud.samples.weatherapp.api;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import javax.persistence.Query;
import javax.sql.DataSource;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.SecurityContext;
import org.eclipse.persistence.config.PersistenceUnitProperties;
import com.sap.hana.cloud.samples.weatherapp.model.FavoriteCity;
/**
 * {@link FavoriteCityService}
 * 
 * @author Matthias Steiner
 * @version 0.1
 */
@Path("/cities")
@Produces({ MediaType.APPLICATION_JSON })
public class FavoriteCityService 
{
    @SuppressWarnings("unchecked")
    @GET
    @Path("/")
    public List<FavoriteCity> getFavoriteCities()
    {
        List<FavoriteCity> retVal = null;

        EntityManager em = this.getEntityManagerFactory().createEntityManager();
retVal = em.createNamedQuery("FavoriteCities").getResultList();

        return retVal;
    }

    @GET
    @Path("/{id}")
    public FavoriteCity getFavoriteCity(@PathParam(value = "id") String id)
    {
        FavoriteCity retVal = null;

        EntityManager em = this.getEntityManagerFactory().createEntityManager();

        try
        {
            Query query = em.createNamedQuery("FavoriteCityById");
            query.setParameter("id", id);
            retVal = (FavoriteCity) query.getSingleResult();
        }
        catch(Exception ex)
        {
            ex.printStackTrace();
        }
        finally
        {
            em.close();
        }

        return retVal;
    }

    @SuppressWarnings("unchecked")
    @POST
    @Path("/")
    public List<FavoriteCity> addFavoriteCity(FavoriteCity city)
    {
        List<FavoriteCity> retVal = null;

        EntityManager em = this.getEntityManagerFactory().createEntityManager();

        try
        {
            em.getTransaction().begin();
            em.persist(city);
            em.getTransaction().commit();

            retVal = em.createNamedQuery("FavoriteCities").getResultList();
        }
        catch(Exception ex)
        {
            ex.printStackTrace();
        }
        finally
        {
            em.close();
        }

        return retVal;
    }

    @SuppressWarnings("unchecked")
    @DELETE
    @Path("/{id}")
    public List<FavoriteCity> removeFavoriteCity(@PathParam(value = "id") String id)
    {
        List<FavoriteCity> retVal = null;

        EntityManager em = this.getEntityManagerFactory().createEntityManager();

        try
        {
            Query query = em.createNamedQuery("FavoriteCityById");
            query.setParameter("id", id);
            FavoriteCity city = (FavoriteCity) query.getSingleResult();

            if (city != null)
            {
                em.getTransaction().begin();
                em.remove(city);
                em.getTransaction().commit();
            }

            retVal = em.createNamedQuery("FavoriteCities").getResultList();
        }
        catch(Exception ex)
        {
            ex.printStackTrace();
        }
        finally
        {
            em.close();
        }

        return retVal;
    }


    /**
     * Returns the <code>DefaultDB</code> {@link DataSource} via JNDI.
     * 
     * @return <code>DefaultDB</code> {@link DataSource}
     */
    protected DataSource getDataSource()
    {
        DataSource retVal = null;

        try 
        {
            InitialContext ctx = new InitialContext();
            retVal = (DataSource) ctx.lookup("java:comp/env/jdbc/DefaultDB");
        }
        catch (NamingException ex)
        {
            ex.printStackTrace();
        }

        return retVal;
    }

    /**
     * Returns the {@link EntityManagerFactory}.
     * 
     * @return The {@link EntityManagerFactory}
     */
    @SuppressWarnings({ "rawtypes", "unchecked" })
    protected EntityManagerFactory getEntityManagerFactory()
    {
        EntityManagerFactory retVal = null;

        try
        {
            Map properties = new HashMap();

            DataSource ds = this.getDataSource();

            properties.put(PersistenceUnitProperties.NON_JTA_DATASOURCE, ds);

            retVal = Persistence.createEntityManagerFactory("application", properties);
        }
        catch (Exception ex)
        {
            ex.printStackTrace();
        }

        return retVal;
    }

}

第九步:创建REST服务
要在web.xml配置文件中注册我们的RESTful服务实现,请将我们FavoriteCityService类的完全限定类名添加到逗号分隔列表中jaxrs.serviceClasses。请参阅下面的代码段,了解在元素中输入完全限定类名的位置(不要忘记AuthenticationService行尾的逗号)。

<init-param>
    <param-name>jaxrs.serviceClasses</param-name>
    <param-value>
    com.sap.hana.cloud.samples.weatherapp.api.AuthenticationService,
    com.sap.hana.cloud.samples.weatherapp.api.FavoriteCityService
    </param-value>
</init-param>

这里写图片描述

第十步:为json反序列化添加初始化参数。
在上述标记的下方,我们需要为JSON反序列化添加另一个标记,如下所示:

<init-param>
    <param-name>jaxrs.providers</param-name>
    <param-value>org.codehaus.jackson.jaxrs.JacksonJsonProvider</param-value>
</init-param>

这里写图片描述
第十一步:定义数据源
要做的最后一个更改是在其中定义一个DataSource web.xml以便连接到底层数据库。为此,请在结束标记之后复制并粘贴以下XML代码段:

<resource-ref>
<res-ref-name>jdbc/DefaultDB</res-ref-name>
<res-type>javax.sql.DataSource</res-type>
</resource-ref>

这里写图片描述
第十二步:REST工具
为了正确测试我们的RESTful服务,我们需要一个REST工具(例如Postman),它允许您以方便的方式执行HTTP调用。
在邮递员中,输入http://localhost:8080/weatherapp/api/v1/citiesURL输入字段,并确保Basic Auth在“ 授权”选项卡中提供您的用户名/密码作为参数。
然后,确保按相应的更新请求按钮更新请求。然后,将“Authorization”参数作为HTTP标头参数添加到您的请求中。
这里写图片描述
执行调用后,您将在成功验证后看到两个空括号“[]”(表示空数组)。别担心,我们还没有将任何城市保存为最爱,所以这正是我们所期望的

这里写图片描述
至此,我们对于SAP Cloud PlatForm中的使用JPA为应用添加持久层部分已经完成了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值