SpringBoot 学习记录(三): jpa

上篇学习了mybaits的使用,既可以通过注解方式实现,也可以使用常见的xml配置方式实现

这篇我们继续学习数据库访问层jpa,集各家所长,各取所需吧

一,第一步当然还是引入相关依赖包,在pom.xml中继续添加:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
二,jpa底层是由Hibernate来实现的,需要在application.properties中添加相关配置
#jpa
spring.jpa.properties.hibernate.hbm2ddl.auto=update
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL5InnoDBDialect
spring.jpa.show-sql= true
spring.jackson.serialization.indent_output=true
这里说明一下:
hibernate.hbm2ddl.auto参数的作用主要用于:自动创建|更新|验证数据库表结构,有四个值:

create: 每次加载hibernate时都会删除上一次的生成的表,然后根据你的model类再重新来生成新表,
哪怕两次没有任何改变也要这样执行,这就是导致数据库表数据丢失的一个重要原因。
create-drop :每次加载hibernate时根据model类生成表,但是sessionFactory一关闭,表就自动删除。
update:最常用的属性,第一次加载hibernate时根据model类会自动建立起表的结构(前提是先建立好数据库),
以后加载hibernate时根据 model类自动更新表结构,即使表结构改变了但表中的行仍然存在不会删除以前的行。
要注意的是当部署到服务器后,表结构是不会被马上建立起来的,是要等 应用第一次运行起来后才会。
validate :每次加载hibernate时,验证创建数据库表结构,只会和数据库中的表进行比较,不会创建新表,但是会插入新值

另外新建sql脚本,命名schema.sql,并放在classpath下面,那么在应用启动的时候会在结束前读取脚本,执行命令
三,测试,我们新建实体类UserInfo,启动查看是否自动创建了table
package com.example.entity;

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

@Entity
@Table(name="user_info")
public class UserInfo {

	@Id
	@GeneratedValue
	private long id;
	
	private String name;
	
	private String gender;
	
	/** 不映射成数据表 */
	@Transient
	private String status;

	public long getId() {
		return id;
	}

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

	public String getName() {
		return name;
	}

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

	public String getGender() {
		return gender;
	}

	public void setGender(String gender) {
		this.gender = gender;
	}

	public String getStatus() {
		return status;
	}

	public void setStatus(String status) {
		this.status = status;
	}
		
}

四,启动查看,数据库创建了空的table,user_info

五,加入schema.sql脚本,重新启动

insert into user_info (name,gender) values('initname','M');

再查看数据库,此时已成功插入一条初始化数据,这里需要注意两点:

1,开始我引入的spring-boot-starter-parent版本是1.3.8的,前面都没问题,

引入jpa后项目就报错了,查看本地仓库,依赖包也下载下来了,不知道什么原因,

于是更改parent版本为1.3.6,成功启动

2,执行schema.sql脚本,前提是已经创建好了table,自动创建table是应用第一次启动结束后才会创建

而读取脚本文件是在应用启动结束前,如果没有创建table就加入脚本文件,会找不到table报错,另外每次重启都会执行一次。

六,创建UserInfoRepository 继承Repository接口,基本方法已经有实现,继承后能直接使用

这也是使用jpa的便利之处:

package com.example.repository;

import org.springframework.data.jpa.repository.JpaRepository;

import com.example.entity.UserInfo;

public interface UserInfoRepository extends JpaRepository<UserInfo, Long>{

}

七,创建UserController,这里简化了代码,没有使用service层,仅供测试用

package com.example.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import com.example.entity.UserInfo;
import com.example.repository.UserInfoRepository;

@RestController
public class UserController {
	
	@Autowired
	private UserInfoRepository userRepository;
	
	@RequestMapping(value="/user/save",method=RequestMethod.GET)
	public void save(){
		UserInfo user = new UserInfo();
		user.setGender("F");
		user.setName("wendy");
		userRepository.save(user);
	}
	
}
八,查看控制台打印sql语句:
2017-04-07 17:09:01.728  INFO 516 --- [nio-8088-exec-1] o.a.c.c.C.[.[localhost].[/spring-boot]   : Initializing Spring FrameworkServlet 'dispatcherServlet'
2017-04-07 17:09:01.729  INFO 516 --- [nio-8088-exec-1] o.s.web.servlet.DispatcherServlet        : FrameworkServlet 'dispatcherServlet': initialization started
2017-04-07 17:09:01.761  INFO 516 --- [nio-8088-exec-1] o.s.web.servlet.DispatcherServlet        : FrameworkServlet 'dispatcherServlet': initialization completed in 32 ms
Hibernate: insert into user_info (gender, name) values (?, ?)
九,除了封装好的方法,我们也可以自定义查询,jpa会根据方法名自动创建sql语句

如,在UserInfoRepository中添加方法:

package com.example.repository;

import org.springframework.data.jpa.repository.JpaRepository;

import com.example.entity.UserInfo;

public interface UserInfoRepository extends JpaRepository<UserInfo, Long>{

	UserInfo findById(long id);
	
	UserInfo findByName(String name);
}
在UserController中新增测试方法:
	@RequestMapping(value="/user/id",method=RequestMethod.GET)
	public UserInfo findById(long id){
		return userRepository.findById(id);
	}
	
	@RequestMapping(value="/user/name",method=RequestMethod.GET)
	public UserInfo findByName(String name){
		return userRepository.findByName(name);
	}

测试返回结果如下:


再查看控制台打印的sql语句:

Hibernate: select userinfo0_.id as id1_0_, userinfo0_.gender as gender2_0_, userinfo0_.name as name3_0_ from user_info userinfo0_ where userinfo0_.id=?
Hibernate: select userinfo0_.id as id1_0_, userinfo0_.gender as gender2_0_, userinfo0_.name as name3_0_ from user_info userinfo0_ where userinfo0_.name=?

十,很多时候我们需要根据业务需求写sql语句,下面我们来看如何使用注解写sql语句

如,在UserInfoRepository中添加方法:

/**
	 * 自定义查询语句
	 * @param id
	 * @return
	 */
	@Query("select gender from UserInfo where id=?1")
	String userGender(long id);
	
	/**
	 * 自定义更新语句
	 * @param firstname
	 * @param lastname
	 * @return
	 */
	@Transactional
	@Modifying 
	@Query("update UserInfo set name =:name where id =:id")
	int updateName(@Param("name")String name,@Param("id")Long id);
这里需要注意:

1,查询表名UserInfo对应的是实体类名,不是数据库表名

2,更新数据库操作,需要添加事务注解@Transactional,否则会报错:

javax.persistence.TransactionRequiredException
3,其他用法可以参见博客:http://jishiweili.iteye.com/blog/2088265

在UserController中新增测试方法:

	/**
	 * 使用注解写查询语句
	 * @param id
	 * @return
	 */
	@RequestMapping(value="/gender",method=RequestMethod.GET)
	public String getGender(long id){
		return userRepository.userGender(id);
	}
	
	/**
	 * 使用注解生成自定义方法
	 * @param id
	 * @return
	 */
	@RequestMapping(value="/update",method=RequestMethod.POST)
	public String update(@RequestBody UserInfo userInfo){
		String name = userInfo.getName();
		Long id = userInfo.getId();
		int count = userRepository.updateName(name,id);
		return "成功更新"+count+"条数据";
	}
	

启动测试:

http://localhost:8088/spring-boot/gender?id=1 ========== 返回结果:M

http://localhost:8088/spring-boot/update === params:{"name":"acc","id":"2"} ======= 返回结果:成功更新1条数据


===============================================================================================

jpa的使用就初步演示到这里,下篇我们继续学习日志框架,SpringBoot 学习记录(四): slf4j+logback



















评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值