今天,我们用一个最简单的例子上手Spring Data JPA的开发。
1、新建工程
首先,我们使用STS建一个工程:
这里我们示例使用H2数据库,主要是因为简单,使用其他数据库也是一样的,如果你用Web作为用户界面的话把Web选上,我们这里使用JUnit测试,所以不选也行。
2、配置数据库
Spring Boot的配置内容参考官方文档:Appendix A. Common application properties
其中,我们关心的是:
# JPA (JpaBaseConfiguration, HibernateJpaAutoConfiguration)
# DATASOURCE (DataSourceAutoConfiguration & DataSourceProperties)
spring.datasource.continue-on-error=false # Do not stop if an error occurs while initializing the database.
spring.datasource.data= # Data (DML) script resource references.
spring.datasource.data-username= # User of the database to execute DML scripts (if different).
spring.datasource.data-password= # Password of the database to execute DML scripts (if different).
spring.datasource.dbcp2.*= # Commons DBCP2 specific settings
spring.datasource.driver-class-name= # Fully qualified name of the JDBC driver. Auto-detected based on the URL by default.
spring.datasource.generate-unique-name=false # Generate a random datasource name.
spring.datasource.hikari.*= # Hikari specific settings
spring.datasource.initialize=true # Populate the database using 'data.sql'.
spring.datasource.jmx-enabled=false # Enable JMX support (if provided by the underlying pool).
spring.datasource.jndi-name= # JNDI location of the datasource. Class, url, username & password are ignored when set.
spring.datasource.name=testdb # Name of the datasource.
spring.datasource.password= # Login password of the database.
spring.datasource.platform=all # Platform to use in the schema resource (schema-${platform}.sql).
spring.datasource.schema= # Schema (DDL) script resource references.
spring.datasource.schema-username= # User of the database to execute DDL scripts (if different).
spring.datasource.schema-password= # Password of the database to execute DDL scripts (if different).
spring.datasource.separator=; # Statement separator in SQL initialization scripts.
spring.datasource.sql-script-encoding= # SQL scripts encoding.
spring.datasource.tomcat.*= # Tomcat datasource specific settings
spring.datasource.type= # Fully qualified name of the connection pool implementation to use. By default, it is auto-detected from the classpath.
spring.datasource.url= # JDBC url of the database.
spring.datasource.username= # Login user of the database.
spring.datasource.xa.data-source-class-name= # XA datasource fully qualified name.
spring.datasource.xa.properties= # Properties to pass to the XA data source.
# H2 Web Console (H2ConsoleProperties)
spring.h2.console.enabled=false # Enable the console.
spring.h2.console.path=/h2-console # Path at which the console will be available.
spring.h2.console.settings.trace=false # Enable trace output.
spring.h2.console.settings.web-allow-others=false # Enable remote access.
# JOOQ (JooqAutoConfiguration)
spring.jooq.sql-dialect= # SQLDialect JOOQ used when communicating with the configured datasource. For instance `POSTGRES`
# JPA (JpaBaseConfiguration, HibernateJpaAutoConfiguration)
spring.data.jpa.repositories.enabled=true # Enable JPA repositories.
spring.jpa.database= # Target database to operate on, auto-detected by default. Can be alternatively set using the "databasePlatform" property.
spring.jpa.database-platform= # Name of the target database to operate on, auto-detected by default. Can be alternatively set using the "Database" enum.
spring.jpa.generate-ddl=false # Initialize the schema on startup.
spring.jpa.hibernate.ddl-auto= # DDL mode. This is actually a shortcut for the "hibernate.hbm2ddl.auto" property. Default to "create-drop" when using an embedded database, "none" otherwise.
spring.jpa.hibernate.naming.implicit-strategy= # Hibernate 5 implicit naming strategy fully qualified name.
spring.jpa.hibernate.naming.physical-strategy= # Hibernate 5 physical naming strategy fully qualified name.
spring.jpa.hibernate.naming.strategy= # Hibernate 4 naming strategy fully qualified name. Not supported with Hibernate 5.
spring.jpa.hibernate.use-new-id-generator-mappings= # Use Hibernate's newer IdentifierGenerator for AUTO, TABLE and SEQUENCE.
spring.jpa.open-in-view=true # Register OpenEntityManagerInViewInterceptor. Binds a JPA EntityManager to the thread for the entire processing of the request.
spring.jpa.properties.*= # Additional native properties to set on the JPA provider.
spring.jpa.show-sql=false # Enable logging of SQL statements.
其实不止这些,但我们不会完全学完所有知识才能应用,以下的配置就可以让我们访问数据库了:
spring.datasource.url=jdbc:h2:file:d:/h2/data.db;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE
spring.datasource.driverClassName=org.h2.Driver
spring.datasource.username=sa
spring.datasource.password=
spring.jpa.database-platform= org.hibernate.dialect.H2Dialect
spring.jpa.generate-ddl=true
spring.jpa.hibernate.ddl-auto=create-drop
spring.jpa.open-in-view=true
spring.jpa.show-sql=false
spring.h2.console.enabled=false
3、代码结构
理论上我们可以任意的组织代码,Spring Boot给出了一个建议:
com
+- example
+- myproject
+- Application.java
|
+- domain
| +- Customer.java
| +- CustomerRepository.java
|
+- service
| +- CustomerService.java
|
+- web
+- CustomerController.java
从上图可以看出:domain放置实体和Repository,service放置业务逻辑,web放置Controller。我更习惯于另为一种组织,将domain拆分为entity和repo,将实体和Repository分别安放。Repository可以看作是DAO/DAL数据访问层或者数据访问对象。
4、从数据到逻辑
用上面的代码结构我们可以看出,一个Spring业务流程包括:数据结构(entity)、数据访问(repo/dal)、业务逻辑(service)和用户交互界面(web)。我们接下来按此顺序一一讲解
4.1、实体对象Entity
实体对象很简单,是和数据库表的映射,但框架已经把数据库操作封装了,且Java强调的面向对象,我认为实体直接看作是可以持久化的数据对象就好了,和数据库的关系只要心里明白就行。我们先实现一个记录数据的描述,这个记录没有什么实际意义,仅为演示Spring Data JPA的使用。代码如下:
@Entity
public class Records {
@Id
@GeneratedValue
private Long id;
@Column
private String title;
@Column
private String description;
@Column
private Date updateDate;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public Date getUpdateDate() {
return updateDate;
}
public void setUpdateDate(Date updateDate) {
this.updateDate = updateDate;
}
}
在实体类上使用@Entity注解说明这是一个实体类,@Id注解说明这是主键,@Column说明是普通字段,@GenerateValue主键生成策略默认native,H2是自增的。
这就是整个数据结构,包含了主键、标题、描述和更新时间。
4.2、Repository的实现
数据结构有了,接下来我们我操作这些数据,说白了就是增删查改、分页等等。要感谢Spring,这些功能大部分都为我们实现了,我们只需要扩展一个接口就行,不信看下面的代码:
@Repository
public interface RecordsRepo extends JpaRepository<Records, Long> {
}
看见没,不超过三行代码。@Repository说明这个接口是一个repository,也就是DAO/DAL。接口JpaRepository是一个很全的功能接口,我们不用实现它,Spring会自动为我们适配实现。
4.3、业务逻辑的实现
当我们可以操作数据时,就可以通过处理数据来实现业务逻辑了,代码如下:
@Service
public class RecordsService {
@Autowired
RecordsRepo recRepo;
public Records save(Records rec) {
return recRepo.save(rec);
}
public List<Records> list() {
return recRepo.findAll();
}
public void delete(Records rec) {
recRepo.delete(rec);
}
public Records get(Long id) {
return recRepo.findOne(id);
}
}
同样,这里也有一个@Service注解说明这是一个服务Bean,通过@Autowired注解将RecordsRepo注入到服务中,这样就能操作Records数据了。这时候我们就可以根据我们的需求和业务来编写我买的业务方法,因为这里只是一个demo,所以我们就简单的调用了repository方法。
4.4、检验成果
测试通常是通过对比输出值和期望值来进行检验的。简单的,我们只是通过用户界面来进行判断,例如:
4.4.1、Web页面操作测试
我们,通过Controller实现几个用户功能,代码如下:
@SpringBootApplication
@RestController
public class SpringBootJpaApplication {
@Autowired
RecordsService recSevc;
public static void main(String[] args) {
SpringApplication.run(SpringBootJpaApplication.class, args);
}
@RequestMapping("new")
public Records newRecords() {
Records rec = new Records();
rec.setTitle("title" + Math.random());
rec.setDescription("desc" + Math.random());
rec.setUpdateDate(Calendar.getInstance().getTime());
rec = recSevc.save(rec);
return rec;
}
@RequestMapping("update")
public Records updateRecords() {
Records rec = recSevc.get(1l);
rec.setTitle("modified");
recSevc.save(rec);
return rec;
}
@RequestMapping("delete")
public String deleteRecords() {
Records rec = recSevc.get(1l);
recSevc.delete(rec);
return "deleted";
}
}
这里,注入了RecordsService,并通过用户请求实现了增改删功能。我们可以浏览器返回值查看返回值。另外,我们可以在H2控制台中查看数据库的变化,什么是H2控制台,如果你用过phpMyAdmin或其他数据库管理工具就明白了,这里不深入讨论。我们先配置一下application.properties:
spring.h2.console.enabled=true
spring.h2.console.path=/h2 #默认是/h2_console
我们先启动服务:
在项目名称上,右键,Run As,Java Application 或者 Spring Boot App。
然后,我们在浏览器中输入http://host:port/[new|update|delete] 试试看。
同时,我们可以在浏览器中输入http://host:port/h2 看看数据库中数据的变化是否与预期一致:
4.4.2、JUnit单元测试
另外一种更专业的测试方法是我们可以写单元测试,这样我买的测试就可以不断迭代,而且有相应的工具帮我们进行测试分析,代码如下:
@RunWith(SpringRunner.class)
@SpringBootTest
public class SpringBootJpaApplicationTests {
@Autowired
RecordsService recSevc;
@Test
public void contextLoads() {
}
@Test
public void testJpaRecords() {
Records rec = new Records();
rec.setTitle("title" + Math.random());
rec.setDescription("desc" + Math.random());
rec.setUpdateDate(Calendar.getInstance().getTime());
rec = recSevc.save(rec);
Long id = rec.getId();
assertThat(rec.getId()).isNotNull();
rec.setTitle("modified");
rec = recSevc.save(rec);
assertThat(rec.getTitle()).isEqualTo("modified");
assertThat(rec.getId()).isEqualTo(id);
List<Records> recs = recSevc.list();
int size = recs.size();
assertThat(size).isGreaterThan(0);
rec = recSevc.get(id);
assertThat(rec.getId()).isEqualTo(id);
recSevc.delete(rec);
rec = recSevc.get(id);
assertThat(rec).isNull();
}
}
同样是注解,这个@Test说明我们的执行的测试方法是testJpaRecords,不过这次我们运行的是JUnit Test,如下图所示:
运行结果一闪而过,结果如何呢?请看:
IDE里面的JUnit 视图窗口,运行了两个测试方法,全部通过。这里仅是示例,实际测试应更复杂,需分析测试覆盖率等。
总结
回过头来再复习一遍,很简单,设计好你要操作的数据结构,编写操作数据的接口,在业务逻辑中操作数据,将数据处理结果返回给用户。
转载请注明:
http://www.techcave.cn
http://tedeum.iteye.com
http://www.jianshu.com/u/befd4004b0a4
==============================================================
Ionic 2 实例开发
序
Ionic 2 安装
环境安装
创建Ionic项目
测试运行项目
Ionic 2 项目结构
./src/index.html
./src/
./src/app/app.html
Ionic 2 应用剖析
0 开始之前
1 创建一个新的Ionic 2 应用
2 目录结构
Root Components 模版
App Module
总结
Ionic 2 添加页面
创建页面
创建附加页面
使用 Ionic 2 开发Todo应用
0 开始之前
1 创建新的Ionic 2工程
2. 设置主页(Home page)
3 持久化数据保存
4 总结
Ionic 2 实现列表滑动删除按钮
1.创建Ionic2应用
2.准备列表数据
3.修改主页(HOME)的模版
4.创建方法删除数据
5.添加一个编辑按钮
总结
Angular 2 新概念和语法
Angular 2 & Ionic 2 概念
Angular 2 语法
Ionic 2 导航简明指南
入栈出栈(Pushing and Popping)
什么时候使用导航栈?什么时候使用rootPage?
Ionic 2 基本导航功能
总结
Ionic 2 中使用管道处理数据
1.生成一个新应用
2.创建一个管道
3.使用管道
总结
Ionic 2 中使用HTTP与远程服务器交互数据
开始之前
我们需要一个列表
3.获取远程数据
4.推送数据到服务器
总结
Ionic 2 中的样式与主题
Ionic 2主题简介
创建Ionic 2应用主题的方式
没有苹果电脑打包iOS平台的 Ionic 2程序
开始之前
1 创建一个Ionic 2的应用
2 建立Ionic Cloud
3 生成证书和创建一个安全概要
4 使用Ionic Package 命令
总结
Ionic 2中使用百度地图和Geolocation
新建项目
加入百度地图SDK库
加载地图
获取定位
坐标转换
地图定位
激活百度地图导航
总结
在Ionic 2 Native中使用Cordova插件
Ionic 和 Cordova 的误解
使用Ionic Native
使用没有包含在Ionic Native中的插件
Ionic 2 中添加图表
1. 照例新建一个项目
2. 安装Chart.js
3. 在模版中使用
总结
Ionic 2 中的创建一个闪视卡片组件
1. 创建一个新的应用作为例子
2. 什么是组件?
3. 创建组件模版
4. 创建组件类
5. 创建 CSS 动画
6. 添加组件到模版
总结
Ionic 2 中创建一个照片倾斜浏览组件
1. 创建一个新的应用
2. 实现照片倾斜浏览组件
3. 使用照片倾斜浏览组件
总结
Ionic 2 中实现一个简单的进度条
理解 自定义组件中的 Input 和 output
1.创建一个新的应用
2.创建组件
修改src/components/progress-bar/progress-bar.ts如下:
3.使用这个组件
总结
使用VS Code在Chrome中调试Ionic 2
优化你的Ionic2应用
打开Angular产品模式
修改(click) 为 (tap)
使用 --prod 参数编译
总结
Ionic 2 开发遇到的问题及处理集
Console.log 不输出
编译Android报错:compileArmv7DebugJavaWithJavac
一些更新命令
错误:Error: listen EADDRINUSE 0.0.0.0:53703