使用Maven构建一Java项目,起名springdata

一 基本工作


1,1 配置pom文件

1.1.1 导入6项依赖


1.1.2 在pom.xml文件中配置jdk版本为1.8

<build>  
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.8</source>
<target>1.8</target>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
</plugins>
</build>

1.2 配置spring全局配置文件


1.2.1 在src/main/resources 下创建 db.properties文件

jdbc.driverClass=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql:///jpa
jdbc.username=root
jdbc.password=root

1.2.2 在src/main/resouces 下创建spring全局配置文件 applicationContext.xml

创建文件时,命名空间选择如下


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:jpa="http://www.springframework.org/schema/data/jpa"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.3.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd
http://www.springframework.org/schema/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa-1.8.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.3.xsd">


<!-- 导入数据库的配置信息,注意这个标签只能出现一次, 导入一个匹配文件
若想导入多个配置文件可以将 db.properties写成 *.properties
-->
<context:property-placeholder location="classpath:db.properties"/>

<!-- 扫包(让spring扫描含有注解类:service注解),扫描包的目的是为了创建对象 -->
<context:component-scan base-package="com.qx.springdata"></context:component-scan>

<!-- 配置JPA要用到的dataSource -->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="${jdbc.driverClass}"></property>
<property name="jdbcUrl" value="${jdbc.url}"></property>
<property name="user" value="${jdbc.username}"></property>
<property name="password" value="${jdbc.password}"></property>
</bean>

<!-- 配置 entityManagerFactory-->
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSource"></property>
<!-- 配置jpa的具体实现 -->
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"></bean>
</property>
<!-- 配置扫描包,扫描所有带有jpa注解的类(就是entity注解) -->
<property name="packagesToScan" value="com.qx.springdata"></property>


<!-- 配置具体实现的相关配置(因为指定了具体实现是hibernate,因此也需要为hibernate进行相关的配置) -->
<!-- JPA和JDBC一样是规范,你需要给它指定一个具体的实现 -->
<property name="jpaProperties">
<props>
<prop key="hibernate.show_sql">true</prop>
<prop key="hibernate.format_sql">true</prop>
<prop key="hibernate.hbm2ddl.auto">update</prop>
</props>

</property>
</bean>

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

<!-- 注解驱动:扫描带有@Transaction注解的类或方法 -->
<tx:annotation-driven transaction-manager="transactionManager"/>

<!-- 配置扫描springdata 扫描的是继承自Repository接口的接口 (接口可以多继承) 目的:扫描jpa注解 -->
<jpa:repositories base-package="com.qx.springdata" entity-manager-factory-ref="entityManagerFactory"></jpa:repositories>
</beans>

2.1 创建持久化类和 SpringData的核心接口Repository的子接口


SpringData_Repository接口概述

  • Repository 接口是 Spring Data 的一个核心接口,它是一个空接口,不提供任何方法(和Serializable一样,Serializable也是一个空接口),开发者需要在自己定义的接口中声明需要的方法 public interface Repository<T, ID extends Serializable> {}

  • Spring Data可以让我们只定义接口,只要遵循 Spring Data的规范,就无需写实现类。
  • 与继承 Repository 等价的一种方式,就是在持久层接口上使用 @RepositoryDefinition 注解,并为其指定 domainClass 和 idClass 属性。

  • Repository 的子接口

    • 基础的 Repository 提供了最基本的数据访问功能,其几个子接口则扩展了一些功能。它们的继承关系如下:

    1.Repository: 仅仅是一个标识,表明任何继承它的均为仓库接口类

    2.CrudRepository: 继承 Repository,实现了一组 CRUD 相关的方法

    3.PagingAndSortingRepository: 继承 CrudRepository,实现了一组分页排序相关的方法

    4.JpaRepository: 继承 PagingAndSortingRepository,实现一组 JPA 规范相关的方法

    5.自定义的 XxxxRepository 需要继承 JpaRepository,这样的 XxxxRepository 接口就具备了通用的数据访问控制层的能力。

    6.JpaSpecificationExecutor: 不属于Repository体系,实现一组 JPA Criteria 查询相关的方法

命名规范:

LessThan,GreaterThan 指的是数字 After,Before指的是日期 Date 写错会提示


2.1.1 创建持久化类Person

package com.qx.springdata;

import java.util.Date;

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

@Entity
@Table(name="jpa_persons")
public class Person {
private Integer id;
private String lastName;
private String email;
private Date birth;


@GeneratedValue // 按照数据库默认的方式进行自增
@Id
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;
}
}

2.1.2 创建Repository的子接口PersonRepository(继承关系)

package com.qx.springdata;

import org.springframework.data.repository.Repository;

/**
* 操作person类的接口
* 需要继承自Repository
* 参1: 代表当前操作的实体类
* 参2: 代表实体类的主键类型
* @author dell
*
*Repository是springdata的核心接口,这个接口的实现规定了spring data操作数据库的规范--命名规范
*查询是以get或者是find或者是read开头
*/
public interface PersonRepository extends Repository<Person, Integer> {
Person getByLastName(String lastName);
}

3.1 创建测试类, 自动生成数据库表

3.1.1 创建一测试类TestSpringData

package com.qx.springdata.test;

import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.qx.springdata.PersonRepository;

public class TestSpringData {

private ApplicationContext context;
private PersonRepository personRepository;

@org.junit.Before //该注解含义在执行@Test注解之前先执行这个代码
public void Before(){
context=new ClassPathXmlApplicationContext("applicationContext.xml");
personRepository=context.getBean(PersonRepository.class);
System.out.println("测试前");
}

@Test
public void testHellord(){
//Person person = personRepository.getByLastName("bb");
//System.out.println(person);

}
}

3.1.2 运行testHellord方法,生成数据库表

运行前:数据库jpa是空的

运行后: 自动生成了 表 jpa_persons (生成了两种表,且jpa_persons这种表主键并不是自增的)



注意:

生成了两张表,且jpa_persons这种表主键并不是自增的, 跟持久化类id的注解@GeneratedValue 有关


当注解是

@GeneratedValue  // 按照数据库默认的方式进行自增
@Id
public Integer getId() {
return id;
}
或是

@GeneratedValue(strategy=GenerationType.AUTO)  // 按照数据库默认的方式进行自增
@Id
public Integer getId() {
return id;
}
时,都将会生成两张表,其中一个是hibernate_sequence,且表jpa_persons的主键并非自增

只有为下面这种注解方式时,才会只生成一张表,且jpa_persons表的主键id是自增的

@GeneratedValue(strategy=GenerationType.IDENTITY)  // 按照指定的方式进行自增
@Id
public Integer getId() {
return id;
}

验证:

package com.qx.springdata;

import java.util.Date;

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

@Entity
@Table(name="jpa_persons")
public class Person {
private Integer id;
private String lastName;
private String email;
private Date birth;


@GeneratedValue(strategy=GenerationType.IDENTITY) // 按照指定的方式进行自增
@Id
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;
}

@Override
public String toString() {
return "Person [id=" + id + ", lastName=" + lastName + ", email=" + email + ", birth=" + birth + "]";
}

}



自动生成的表:



二 正式操作 ,CRUD

2.1 单表单对象

往jpa_persons表中插入几条数据,以便测试:




在PersonRepository接口中按命名规范,定义方法:

/**
* 操作person类的接口
* 需要继承自Repository
* 参1: 代表当前操作的实体类
* 参2: 代表实体类的主键类型
* @author dell
*
*Repository是springdata的核心接口,这个接口的实现规定了spring data操作数据库的规范--命名规范
*查询是以get或者是find或者是read开头
*/
public interface PersonRepository extends Repository<Person, Integer> {

//根据名字查找
Person getByLastName(String lastName);

//查询名字以xxx开头同时id小于xxx的值
List<Person> getByLastNameStartingWithAndIdLessThan(String lastName,Integer id);

List<Person> getByLastNameEndingWithAndIdLessThan(String lastName,Integer id);

//查询对应邮件的人
List<Person> getByEmailIn(List<String> emails);
//查询邮件在对应里面里面且id小于某个值的人
List<Person> getByEmailInAndIdLessThan(List<String> emails,Integer id);

}

测试类中进行测试

public class TestSpringData {

private ApplicationContext context;
private PersonRepository personRepository;

@org.junit.Before //该注解含义在执行@Test注解之前先执行这个代码
public void Before(){
context=new ClassPathXmlApplicationContext("applicationContext.xml");
personRepository=context.getBean(PersonRepository.class);
System.out.println("测试前");
}

@Test
public void testHellord(){
Person person = personRepository.getByLastName("张三");
System.out.println(person);

}

@Test
public void testKeyWords(){
//List<Person> list = personRepository.getByLastNameStartingWithAndIdLessThan("张", 8);
//System.out.println(list);

//List<Person> list = personRepository.getByLastNameEndingWithAndIdLessThan("c", 8);
//System.out.println(list);

//使用 Arrays.asList(T... a)可以把传进来的一个可变参数数组快速转变成集合
List<Person> list = personRepository.getByEmailIn(Arrays.asList("bb@163.com","cc@163.com","zs@163.com"));
System.out.println(list);

List<Person> list2=personRepository.getByEmailInAndIdLessThan(Arrays.asList("bb@163.com","cc@163.com","zs@163.com"), 6);
System.out.println(list2);
}
}


测试testKeyWords结果:底层执行的sql语句和查询结果:

INFO: HHH000228: Running hbm2ddl schema update
测试前
七月 30, 2017 11:17:24 下午 org.hibernate.hql.internal.QueryTranslatorFactoryInitiator initiateService
INFO: HHH000397: Using ASTQueryTranslatorFactory
Hibernate:
select
person0_.id as id1_0_,
person0_.birth as birth2_0_,
person0_.email as email3_0_,
person0_.lastName as lastName4_0_
from
jpa_persons person0_
where
person0_.email in (
? , ? , ?
)
[Person [id=2, lastName=bb, email=bb@163.com, birth=2017-07-01 19:31:44.0]
, Person [id=3, lastName=cc, email=cc@163.com, birth=2017-07-09 22:24:17.0]
, Person [id=6, lastName=张三, email=zs@163.com, birth=2017-07-29 22:25:45.0]
]
Hibernate:
select
person0_.id as id1_0_,
person0_.birth as birth2_0_,
person0_.email as email3_0_,
person0_.lastName as lastName4_0_
from
jpa_persons person0_
where
(
person0_.email in (
? , ? , ?
)
)
and person0_.id<?
[Person [id=2, lastName=bb, email=bb@163.com, birth=2017-07-01 19:31:44.0]
, Person [id=3, lastName=cc, email=cc@163.com, birth=2017-07-09 22:24:17.0]
]


2.2 关联表,查询关联数据

2.2.1新建一实体类 Address

package com.qx.springdata;

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

/**
* 给类同时加@Entity 和 @Table的原因:
* 当你从数据库读取数据时,由于你要读取的表映射有实体类(@Entity注解的),那么后台会自动帮你
* 实例化一个对象:
* 创建一个Entity Bean对象相当于新建一条记录,删除一个Entity Bean对象会同时从数据库中删除
* 对应记录,修改一个Entity Bean时,容器会自动将Entity Bean的状态和数据库同步.
* @author dell
*
*/
@Entity //该注解用于指明这是一个实体bean
@Table(name="jpa_addresses") //该注解用于指明Entity所要映射到的数据库表
public class Address {

private Integer id;
private String provience;
private String city;

@GeneratedValue(strategy=GenerationType.IDENTITY)
@Id
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getProvience() {
return provience;
}
public void setProvience(String provience) {
this.provience = provience;
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
@Override
public String toString() {
return "Address [id=" + id + ", provience=" + provience + ", city=" + city + "]";
}

}


2.2.2 在Person类中增加一属性 Address并设置getter setter方法

private Address address;

@JoinColumn(name="address_id") //该注解用来修饰代表关联实体的属性,用于映射底层的外键列
@ManyToOne //一个地址对应着多个人,人和地址之间多对一的关系
public Address getAddress() {
return address;
}
public void setAddress(Address address) {
this.address = address;
}

2.2.3 在PersonRepository接口中按照命名规范,新定义一方法

List<Person> getByAddressIdGreaterThan(Integer addressId);

2.2.4 在测试类中,添加测试方法testKeyWords2

//查询关联数据
@Test
public void testKeyWords2(){
List<Person> list = personRepository.getByAddressIdGreaterThan(110);
System.out.println(list);
}

运行该测试方法.会发现自动生成了表jpa_addresses, 且jpa_persons自动多了一外键列address_id


使用关联数据进行查询时,底层自动走的左外连接



注意:定义方法时要注意:

List<Person> getByAddressIdGreaterThan(Integer addressId);

在定义方法时,如果对象中存在这个属性addressId,会优先使用自带的属性而不是关联数据


在Person类中增加一属性addressId, 设置getter setter方法

而Person类中有一关联属性Address,那么这次去调用方法

List<Person> getByAddressIdGreaterThan(Integer addressId);时,

会优先使用自带的属性AddressId

如果想用关联数据的,而里面刚好有一个属性是同名的,那么你需要加一个下划线分割一下.

List<Person> getByAddress_IdGreaterThan(Integer addressId); 使用_后,代表Address的id


接口中同时定义两个方法

List<Person> getByAddressIdGreaterThan(Integer addressid);//注意,如果对象中存在这个属性,会优先使用自带的属性而不是关联数据
List<Person> getByAddress_IdGreaterThan(Integer addressid);

测试类的测试方法:

//查询关联数据
@Test
public void testKeyWords2(){
List<Person> list = personRepository.getByAddressIdGreaterThan(110);
System.out.println(list);

List<Person> list2=personRepository.getByAddress_IdGreaterThan(110);
System.out.println(list2);
}

运行测试方法,底层走的查询语句:





更多相关文章

  1. 第三部分:Android 应用程序接口指南---第二节:UI---第六章 对话框
  2. 实现基于注解(Annotation)的数据库框架(一)反射的基本了解
  3. sc7731 Android 5.1 Camera 学习之二 framework 到 HAL接口整理
  4. [Unity3D]调用Android接口
  5. Android添加一个回调监听接口
  6. Android下usb host接口插入usb设备时,如何屏蔽usb权限的提示框? 如
  7. android 编译时注解
  8. Android开发一些实用的类、方法及接口(新手向)
  9. 通过数据库接口获取到的中文数据是问号怎么办?

随机推荐

  1. 请不要随随便便就离职
  2. SpaceX成功海上回收火箭(附视频):从星辰到
  3. Python与苹果哲学的相似之处
  4. Tomcat就是这么简单(修订版)
  5. 聊聊Docker镜像
  6. FBI是如何攻破iPhone的?
  7. 快速尝试Python模块:try
  8. 微软Edge浏览器准备内置屏蔽广告功能
  9. 嗯,我来杭州了。
  10. 数据库两个神器索引和锁(修订版)