JPA入门

JPA入门

1. 准备

纯java项目: 

  项目名: spring-data-demo

  项目结构:

    spring-data-demo

            src

     com.jpa.demo

                 entity

            repository

            service

            util

      applicationContext.xml

        db.properties

             lib

  源码:

 db.properties

spring.datasource.url=jdbc:mysql://localhost:3306/jpa?useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC
spring.datasource.username=root
spring.datasource.password=123456
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
View Code

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.jpa.demo"/>

    <!-- 1. 配置数据源 -->
    <context:property-placeholder location="db.properties"/>
    <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
        <property name="user" value="${spring.datasource.username}"></property>
        <property name="password" value="${spring.datasource.password}"></property>
        <property name="driverClass" value="${spring.datasource.driver-class-name}"></property>
        <property name="jdbcUrl" value="${spring.datasource.url}"></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.jpa.demo"></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.jpa.demo" entity-manager-factory-ref="entityManagerFactory"></jpa:repositories>

</beans>
View Code
PersonRepository.java
package com.jpa.demo.repository;

import com.jpa.demo.entity.Person;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.CrudRepository;
import org.springframework.data.repository.query.Param;

import java.util.Date;
import java.util.List;

/**
 * 两种写法:
 * 1.
 * @RepositoryDefinition(domainClass = Person.class, idClass = Integer.class)
 * public interface PersonRepository {
 * }
 *
 * 2.
 * public interface PersonRepository extends Repository<Person, Integer> {
 * }
 *
 */
//@RepositoryDefinition(domainClass = Person.class, idClass = Integer.class)
public interface PersonRepository extends CrudRepository<Person, Integer> {

    //where lastName = ?
    Person findByLastName(String lastName);

    //where lastName like ?% and id < ?
    List<Person> findByLastNameStartingWithAndIdLessThan(String lastName, Integer id);

    //where lastName like %? and id < ?
    List<Person> findByLastNameEndingWithAndIdLessThan(String lastName, Integer id);

    //where email in (?,?,?) and birth < ?
    List<Person> findByEmailInAndBirthLessThan(List<String> emails, Date birth);

    //where a.id > ? 非/级联 (取决于是否Person中有字段addressId, 有 则查询时单表查询, 无 则查询时级联查询)
    List<Person> findByAddressIdGreaterThan(Integer addressId);

    //where a.id > ? 级联
    List<Person> findByAddress_IdGreaterThan(Integer addressId);

    //@Query 复杂查询:子查询
    @Query("select p from Person p where p.id=(select max(p2.id) from Person p2)")
    Person selectMaxPerson();

    //@Query 注解传参方式一:占位符, 如1,2
    @Query("select p from Person p where lastName=?1 and email=?2")
    List<Person> selectByLastNameAndEmail(String lastName, String email);

    //@Query 注解传参方式二:冒号加名称的命名方式
    @Query("select p from Person p where lastName= :lastName and email= :email")
    List<Person> selectByLastNameAndEmail2(@Param("lastName") String lastName, @Param("email")String email);

    //@Query 注解LIKE查询允许写"%%"在占位符或命名上
    @Query("select p from Person p where lastName like %?1%")
    List<Person> selectByLastNameLike(String lastName);

    @Query("select p from Person p where lastName like %:lastName%")
    List<Person> selectByLastNameLike2(@Param("lastName") String lastName);

    //@Query 注解 支持原生sql语句 需设置nativeQuery = true
    @Query(value = "select * from jpa_person where last_name=?1", nativeQuery = true)
    List<Person> selectNativeByLastName(String lastName);


    //@Modifying和@Query结合完成修改,删除操作(JPQL语句不支持insert), service调用层必须加事务, spring-data默认在每个语句中都加了只读事务, 但是修改,删除操作必须加非只读事务,故调用方法必须加事务注解
    @Modifying
    @Query("update Person p set p.email = ?1 where id = ?2")
    int updatePersonEmailById(String email, Integer id);
}
View Code
Person.java
package com.jpa.demo.entity;

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

@Table(name = "jpa_person")
@Entity
public class Person {

    private Integer id;
    private String lastName;
    private String email;
    private Date birth;
    private Address address;

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    public Integer getId() {
        return id;
    }

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

    public String getLastName() {
        return lastName;
    }

    public void setLastName(String lastName) {
        this.lastName = lastName;
    }

    public String getEmail() {
        return email;
    }

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

    public Date getBirth() {
        return birth;
    }

    public void setBirth(Date birth) {
        this.birth = birth;
    }

    @JoinColumn(name = "address_id")
    @ManyToOne
    public Address getAddress() {
        return address;
    }

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


    @Override
    public String toString() {
        return "Person{" +
                "id=" + id +
                ", lastName='" + lastName + '\'' +
                ", email='" + email + '\'' +
                ", birth=" + birth +
                ", address=" + address +
                '}';
    }
}
View Code
Address.java
package com.jpa.demo.entity;

import javax.persistence.*;

@Table(name = "jpa_address")
@Entity
public class Address {

    private Integer id;
    private String province;
    private String city;

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    public Integer getId() {
        return id;
    }

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

    public String getProvince() {
        return province;
    }

    public void setProvince(String province) {
        this.province = province;
    }

    public String getCity() {
        return city;
    }

    public void setCity(String city) {
        this.city = city;
    }

    @Override
    public String toString() {
        return "Address{" +
                "id=" + id +
                ", province='" + province + '\'' +
                ", city='" + city + '\'' +
                '}';
    }
}
View Code
PersonServiceImpl.java
package com.jpa.demo.service.impl;

import com.jpa.demo.repository.PersonRepository;
import com.jpa.demo.service.PersonService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;

@Service
public class PersonServiceImpl implements PersonService {

    @Resource
    private PersonRepository personRepository;

    @Transactional
    @Override
    public int updatePersonEmailById(String email, Integer id){
        return personRepository.updatePersonEmailById(email, id);
    }


}
View Code
PersonService.java
package com.jpa.demo.service;

public interface PersonService {

    int updatePersonEmailById(String email, Integer id);
}
View Code
DateUtil.java
package com.jpa.demo.util;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

public class DateUtil {

    public static String pattern1 = "yyyy-MM-dd";
    public static String pattern2 = "yyyy-MM-dd HH:mm:ss";

    /**
     * 日期转字符串(格式化)
     * @param pattern
     */
    public static String dateToStr(String pattern){
        Date date = new Date();
        SimpleDateFormat sdf = new SimpleDateFormat(pattern);
        String str = sdf.format(date);
        return str;
    }


    /**
     * 字符串转日期(解析)
     * @param dateStr
     * @param pattern
     */
    public static Date strToDate(String dateStr, String pattern) throws ParseException {
        SimpleDateFormat sdf = new SimpleDateFormat(pattern);
        Date date = sdf.parse(dateStr);
        return date;
    }
}
View Code

测试类: 

SpringDataTest.java
package com.jpa.demo;

import com.jpa.demo.repository.PersonRepository;
import com.jpa.demo.service.PersonService;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import javax.sql.DataSource;
import java.sql.SQLException;
import java.text.ParseException;

public class SpringDataTest {

    private ApplicationContext ctx = null;

    {
        ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
    }

    @Test
    public void testDataSource() throws SQLException {
        DataSource dataSource = ctx.getBean(DataSource.class);
        System.out.println(dataSource.getConnection());
    }

    @Test
    public void testJpa() {

    }

    @Test
    public void testPerson() throws ParseException {
        PersonRepository personRepository = ctx.getBean(PersonRepository.class);
        System.out.println(personRepository.getClass().getName());

        /*Person person = personRepository.findByLastName("tq");
        System.out.println(person);

        List<Person> list = personRepository.findByLastNameStartingWithAndIdLessThan("t", 2);
        System.out.println("list: " + list);

        List<Person> list2 = personRepository.findByLastNameEndingWithAndIdLessThan("q", 2);
        System.out.println("list2: " + list2);

        List<String> emails = new ArrayList<>();
        emails.add("123333qq.com");
        List<Person> list3 = personRepository.findByEmailInAndBirthLessThan(emails, DateUtil.strToDate("2019-10-16 13:48:49", DateUtil.pattern2));
        System.out.println("list3: " + list3);

        List<Person> list4 = personRepository.findByAddressIdGreaterThan(0);
        System.out.println("list4: " + list4);
        List<Person> list44 = personRepository.findByAddress_IdGreaterThan(0);
        System.out.println("list44: " + list44);

        Person person2 = personRepository.selectMaxPerson();
        System.out.println(person2);

        List<Person> list5 = personRepository.selectByLastNameAndEmail("tq", "123333qq.com");
        System.out.println("list5:" + list5);

        List<Person> list6 = personRepository.selectByLastNameAndEmail2("tq", "123333qq.com");
        System.out.println("list6:" + list6);

        List<Person> list7 = personRepository.selectNativeByLastName("tq");
        System.out.println("list7:" + lit7);*/

        PersonService personService = ctx.getBean(PersonService.class);
        int i = personService.updatePersonEmailById("5555@qq.com", 1);
        System.out.println(i);

    }





}
View Code

lib

antlr-2.7.7.jar
c3p0-0.9.2.1.jar
com.springsource.net.sf.cglib-2.2.0.jar
com.springsource.org.aopalliance-1.0.0.jar
com.springsource.org.aspectj.weaver-1.6.8.RELEASE.jar
commons-logging-1.1.3.jar
dom4j-1.6.1.jar
hibernate-c3p0-4.2.4.Final.jar
hibernate-commons-annotations-4.0.2.Final.jar
hibernate-core-4.2.4.Final.jar
hibernate-entitymanager-4.2.4.Final.jar
hibernate-jpa-2.0-api-1.0.1.Final.jar
javassist-3.15.0-GA.jar
jboss-logging-3.1.0.GA.jar
jboss-transaction-api_1.1_spec-1.0.1.Final.jar
mchange-commons-java-0.2.3.4.jar
mysql-connector-java-5.1.7-bin.jar
slf4j-api-1.6.1.jar
spring-aop-4.0.0.RELEASE.jar
spring-aspects-4.0.0.RELEASE.jar
spring-beans-4.0.0.RELEASE.jar
spring-context-4.0.0.RELEASE.jar
spring-core-4.0.0.RELEASE.jar
spring-data-commons-1.6.2.RELEASE.jar
spring-data-jpa-1.4.2.RELEASE.jar
spring-expression-4.0.0.RELEASE.jar
spring-jdbc-4.0.0.RELEASE.jar
spring-orm-4.0.0.RELEASE.jar
spring-tx-4.0.0.RELEASE.jar
spring-web-4.0.0.RELEASE.jar
spring-webmvc-4.0.0.RELEASE.jar
View Code

源码: 百度网盘 地址: https://pan.baidu.com/s/1iz-FKWxgefv2fJmbeRy22Q