JPA应用

1、JPA介绍以及初衷:JPA属于Hibernate的前身ORM框架,是一个更高层次的抽象,Hibernate是JPA的一个具体实现,对JPA进行了扩展和延伸,结合Spring,JPA在应用上面具有很好的实用性,因此,学好JPA对学习ORM框架具有很重要的意义。自己在学习JPA过程中遇到的问题,百思不得其解,最后发现都是一些小问题导致的,记录这些问题的解决方案以及总结问题,避免以后犯同样的错误其实就是我写这边博客的初衷。
2、项目的结构如图:
在这里插入图片描述
3、web.xml

<!DOCTYPE web-app PUBLIC
 "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
 "http://java.sun.com/dtd/web-app_2_3.dtd" >

<web-app>
  <display-name>Archetype Created Web Application</display-name>

  <context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>/WEB-INF/applicationContext.xml</param-value>
  </context-param>
  <listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
  </listener>
</web-app>

4、applicationContext.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xmlns:jpa="http://www.springframework.org/schema/data/jpa"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
		http://www.springframework.org/schema/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa-1.3.xsd
		http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd
		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd">


    <context:component-scan base-package="com.edward.springdata" />
    <!--配置数据源-->
    <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
        <property name="user" value="sa"/>
        <property name="password" value="123"></property>
        <property name="driverClass" value="com.microsoft.sqlserver.jdbc.SQLServerDriver"></property>
        <property name="jdbcUrl" value="jdbc:sqlserver://localhost;databaseName=Sample"></property>
    </bean>

    <!-- 2. 配置 JPA 的 EntityManagerFactory -->
    <bean id="entityManagerFactory"
          class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
        <property name="dataSource" ref="dataSource"></property>
        <property name="jpaVendorAdapter">
            <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"></bean>
        </property>
        <property name="packagesToScan" value="com.edward.springdata"></property>
        <property name="jpaProperties">
            <props>
                <!-- 二级缓存相关 -->
                <!--<prop key="hibernate.cache.region.factory_class">org.hibernate.cache.ehcache.EhCacheRegionFactory</prop>-->
                <!--
               <prop key="net.sf.ehcache.configurationResourceName">ehcache-hibernate.xml</prop>
               -->
                <!-- 生成的数据表的列的映射策略 -->
                <prop key="hibernate.ejb.naming_strategy">org.hibernate.cfg.ImprovedNamingStrategy</prop>
                <!-- hibernate 基本属性 -->
                <prop key="hibernate.dialect">org.hibernate.dialect.MySQL5InnoDBDialect</prop>
                <prop key="hibernate.show_sql">true</prop>
                <prop key="hibernate.format_sql">true</prop>
                <prop key="hibernate.hbm2ddl.auto">update</prop>
            </props>
        </property>
    </bean>

    <!-- 3. 配置事务管理器 -->
    <bean id="transactionManager"
          class="org.springframework.orm.jpa.JpaTransactionManager">
        <property name="entityManagerFactory" ref="entityManagerFactory"></property>
    </bean>

    <!-- 4. 配置支持注解的事务 -->
    <tx:annotation-driven transaction-manager="transactionManager"/>

    <!-- 5. 配置 SpringData -->
    <!-- 加入  jpa 的命名空间 -->
    <!-- base-package: 扫描 Repository Bean 所在的 package -->
    <jpa:repositories base-package="com.edward.springdata"
                      entity-manager-factory-ref="entityManagerFactory"></jpa:repositories>

</beans>

5、一对一双向映射:Category中有Customer属性,Customer中有Category属性
Category类:@OneToOne(mappedBy=“category”) :不作为一对一关系处理的一方,category为Customer中定义的Category属性:category

package com.edward.springdata.bean;

import javax.persistence.*;

@Entity
@Table(name="Category")
public class Category {
    private String cid;
    private String cname;
    private Customer customer;

    @OneToOne(mappedBy = "category")
    public Customer getCustomer() {
        return customer;
    }
    public void setCustomer(Customer customer) {
        this.customer = customer;
    }
    @Id
    public String getCid() {
        return cid;
    }

    public void setCid(String cid) {
        this.cid = cid;
    }
    @Column
    public String getCname() {
        return cname;
    }

    public void setCname(String cname) {
        this.cname = cname;
    }

    @Override
    public String toString() {
        return "Category{" +
                "cid='" + cid + '\'' +
                ", cname='" + cname + '\'' +
                '}';
    }
}

Customer类:@OneToOne标注一对一映射,@JoinColumn(name=“cid”,unique=true),必须加上unique=true,cid是对应关联表Category表的主键

package com.edward.springdata.bean;

import org.hibernate.annotations.GenericGenerator;

import javax.persistence.*;
import java.util.Date;
import java.util.Set;

//单向一对多 Customer中有Set<Orders>属性 而Orders中没有Customer属性
@Entity
@Table(name = "Customer")
public class Customer {
    private String uid;
    private  String username;
    private String password;
    private String name;
    private String email;
    private String telephone;
    private Date birthday;
    private String sex;
    private Integer state;
    private String code;
    private Set<Orders>  orders;
    private Category category;

    @JoinColumn(name="cid",unique = true)
    @OneToOne
    public Category getCategory() {
        return category;
    }

    public void setCategory(Category category) {
        this.category = category;
    }

    @Id
    @GenericGenerator(name = "user-uuid", strategy = "uuid2")
    @GeneratedValue(generator = "user-uuid")
    public String getUid() {
        return uid;
    }

    public void setUid(String uid) {
        this.uid = uid;
    }

    @Column(name="username")
    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public String getTelephone() {
        return telephone;
    }

    public void setTelephone(String telephone) {
        this.telephone = telephone;
    }

    public Date getBirthday() {
        return birthday;
    }

    public void setBirthday(Date birthday) {
        this.birthday = birthday;
    }

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }

    public Integer getState() {
        return state;
    }

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

    public String getCode() {
        return code;
    }

    public void setCode(String code) {
        this.code = code;
    }

    @JoinColumn(name="uid")
    @OneToMany(fetch = FetchType.EAGER,cascade = CascadeType.REMOVE)
    //@OneToMany
    public Set<Orders> getOrders() {
        return orders;
    }

    public void setOrders(Set<Orders> orders) {
        this.orders = orders;
    }
}

6、多对一单向映射:Orders类中有Customer属性,Customer类中没有Set属性
Orders类:@ManyToOne标注多对一的映射,fetch=FetchType.EAGER属于主动加载,相对应是FetchType.LAZY属于懒加载,@JoinColumn(name=“uid”),uid属性对应关联表的主键,在当前表默认为对应的外键

package com.edward.springdata.bean;
import org.hibernate.FetchMode;
import org.hibernate.annotations.GenericGenerator;
import org.springframework.data.web.JsonPath;
import javax.persistence.*;
import javax.persistence.criteria.CriteriaBuilder;
import java.util.Date;

//单向多对一 Orders中有Customer属性 而Customer中没有Orders属性
@Entity
@Table(name = "Orders")
public class Orders {
    private String oid;
    private String code;
    private Date ordertime;
    private Double total;
    private Integer state;
    private String address;
    private String name;
    private String telephone;
    private Customer customer;

    @Id
    @GenericGenerator(name="order-uuid",strategy = "uuid2")
    @GeneratedValue(generator = "order-uuid")
    public String getOid() {
        return oid;
    }

    public void setOid(String oid) {
        this.oid = oid;
    }

    public String getCode() {
        return code;
    }

    public void setCode(String code) {
        this.code = code;
    }

    @Temporal(TemporalType.DATE)
    public Date getOrdertime() {
        return ordertime;
    }

    public void setOrdertime(Date ordertime) {
        this.ordertime = ordertime;
    }

    public Double getTotal() {
        return total;
    }

    public void setTotal(Double total) {
        this.total = total;
    }

    public Integer getState() {
        return state;
    }

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

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Column(name="telephone")
    public String getTelephone() {
        return telephone;
    }

    public void setTelephone(String telephone) {
        this.telephone = telephone;
    }

    @JoinColumn(name="uid")  //这个name对应关联表的主键 不要写错
    @ManyToOne(fetch = FetchType.EAGER)
    public Customer getCustomer() {
        return customer;
    }

    public void setCustomer(Customer customer) {
        this.customer = customer;
    }
}

7、一对多关联映射:Customer中有Set属性,Orders中没有Customer属性
Customer类中@OneToMany标注一对多映射,cascade表示级联策略,CascadeType.REMOVE表示级联删除,@JoinColumn(name=“uid”),其中uid是当前表Customer的主键,并且在Orders表中将作为外键存在
8、测试类:
JpaTest类:通过ClassPathXmlApplicationContext加载ApplicationContext对象,注意由于我们的ApplicationContext.xml不是在类路径下面构建的,所以这里使用该文件的绝对路径进行加载;然后通过getBean方法获取CustomerService对象;

package com.edward.springdata;

import com.edward.springdata.bean.Customer;
import com.edward.springdata.service.CustomerService;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class JpaTest {
    private ApplicationContext ctx=null;
    private CustomerService  cs=null;
    {
        ctx = new ClassPathXmlApplicationContext("file:E:\\JAVA\\ideacase\\springdatajpa\\src\\main\\webapp\\WEB-INF\\applicationContext.xml");
        cs=ctx.getBean(CustomerService.class);
    }

    @Test
    public void testSave(){
//        Customer p1=new Customer();
//        p1.setEmail("a@123.com");
//        p1.setName("aa");
//
//        Customer p2=new Customer();
//        p2.setEmail("b@123.com");
//        p2.setName("bb");
//        System.out.println(cs.getClass().getName());
//        cs.save(p1,p2);
    }

    @Test
    public void test1(){
        cs.findByname("DA4FD78A-272C-4E0D-AF78-67E378111382");
    }
}

9、依赖注入:首先在ApplicationContext.xml配置文件中通过<context:component-scan base-package=“com.edward.springdata” />将对应包下面的类进行了扫描。
CustomerService类:通过注解@Service进行组件的注册,@Autowired标注进行注入CustomerDao。

package com.edward.springdata.service;

import com.edward.springdata.bean.Customer;
import com.edward.springdata.dao.CustomerDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service
public class CustomerService {
    @Autowired
    private CustomerDao dao;

    @Transactional
    public void save(Customer p1,Customer p2){
        dao.save(p1);
        //int i=10/0;
        dao.save(p2);
    }

    public void findByname(String name){
        dao.findByname(name);
    }


}

CustomerDao类:@Repository标注仓储

package com.edward.springdata.dao;

import com.edward.springdata.bean.Customer;
import org.springframework.stereotype.Repository;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import java.util.HashMap;
import java.util.Map;

@Repository
public class CustomerDao {
    @PersistenceContext
    private EntityManager entityManager;

    public  void save(Customer p){
        entityManager.persist(p);
    }

    public void findByname(String id){
        Customer customer=new Customer();
        customer=entityManager.find(Customer.class,id);
        System.out.println(customer);
    }
}

总结:
1)、注解最好是都打在getter方法上面,不要有的地方打在变量上面,有些地方打在getter方法上面;
2)、不要尝试在方法里面重载toString()的方法,这样会影响延迟加载的策略(报错),影响使用;
3)、其实不管是那种映射,本质上和数据库表的设计是一样的,我们可以基于数据表的设计来构建我们的映射关系,从而实现数据表的自动生成;
4)、JPA能做的,最终就是要实现我们对数据库的操作。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值