上周跳槽到了一家新公司,数据持久化层用的不是mybatis,而是用的JPA,由于以前都没有用过,所以周末学习了一下,并且做一下记录,方便以后查看。
先说说jpa是什么?
我们来看看官方回答:
其实说白了,你可以把它当做hibernate、mybatis的同类。
学习了之后,我更觉得这是mybatis-plus的前身,提供了很多写好的crud的接口,后面总结的时候我再做一下对比。
先看看主要代码,文末会附上完整项目链接,欢迎大家下载。
1.pom.xml文件
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.1.10</version>
</dependency>
</dependencies>
当然,resource标签一些读取.yml文件之类的必须,这里就不贴了
2.application.yml文件
spring:
datasource:
druid:
url: jdbc:mysql://localhost:3306/jpa_test?allowMultiQueries=true&useUnicode=true&characterEncoding=UTF-8&zeroDateTimeBehavior=convertToNull&useSSL=false&allowPublicKeyRetrieval=true
username: root
password: root12345
driver-class-name: com.mysql.cj.jdbc.Driver
jpa:
hibernate:
ddl-auto: update #自动更新
naming:
physical-strategy: org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl
show-sql: true #日志中显示sql语句
application:
name: spring-data-jpa-demo
server:
port: 2333 #端口号
3.实体映射类
package com.jpa.example.entity;
import lombok.Data;
import javax.persistence.*;
@Data
@Entity
@Table(name = "jpa_user_test")
public class UserEntity {
/**
*这里的属性name,我在这里编译是警告红线,这不影响我们代码的正常运行
*至于这些注解,一看应该都能懂,想要研究的去百度一大堆
*/
@Id
@Column(name = "id")
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
@Column(name = "user_name")
private String userName;
@Column(name = "student")
private String student;
}
3.TestJpaRepository.java类
这个类其实就类似于mybaits的mapper文件,里面是连接数据库的最后一层。
有些注意点,我后面会打总结。
package com.jpa.example.dao;
import com.jpa.example.entity.UserEntity;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
public interface TestJpaRepository extends JpaRepository<UserEntity,Long> {
Object findByStudentAndUserName(String userName,String student);
@Modifying
@Query(value = "delete from #{#entityName} a where a.userName = ?1")
void testDelete(String name);
}
4.Service层,controller我就不贴代码了。每个测试方法我都有注释
package com.jpa.example.service;
import com.jpa.example.dao.TestJpaRepository;
import com.jpa.example.entity.UserEntity;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.Optional;
@Service
public class JpaTestServiceImpl implements JpaTestService {
@Autowired
TestJpaRepository testJpaRepository;
//查找表中所有数据
@Override
public Object findAll() {
return testJpaRepository.findAll();
}
//根据主键id查找
@Override
public Object findById() {
long id = 1l;
return testJpaRepository.findById(id);
}
//插入一条新数据,这里没有设置id,因为在实体类我们有个
//@GeneratedValue(strategy = GenerationType.AUTO)注解,帮助我们自动生成
@Override
public Object save() {
UserEntity userEntity = new UserEntity();
userEntity.setUserName("xiaoyu");
userEntity.setStudent("川大");
testJpaRepository.save(userEntity);
return null;
}
//修改数据,修改和插入用的都是save,区别就是有无主键id。
@Override
public Object update() {
long id = 1l;
Optional<UserEntity> byId = testJpaRepository.findById(id);
if (byId.isPresent()) {
UserEntity userEntity = byId.get();
userEntity.setUserName("update 小鱼");
testJpaRepository.save(userEntity);
return userEntity;
}
return null;
}
//根据id删除
@Override
public Object delete() {
long id = 1l;
testJpaRepository.deleteById(id);
return null;
}
//特殊的查找方法,这里接下来解释
@Override
public Object special() {
String username = "四川";
String student = "成都";
return testJpaRepository.findByStudentAndUserName(username,student);
}
//根据条件去删除,这里点进去可以看到我们写的是sql语句,所以要加 @Transactional注解
//而且在delete之类操作的时候要在TestJpaRepository加上@Modifying注解
@Override
@Transactional
public Object deleteSpecial() {
String name = "测试特殊删除";
testJpaRepository.testDelete(name);
return "OK";
}
}
以上就是主要的代码,完整项目请访问我的GitHub,开箱即用,都是调试好了的代码。
做个总结吧
1.先说优点,提供了一系列封装好的方法,帮助我们少些了SQL语句,方便开发。
2.一些缺点,官方封装好的直接方法很有限,基本都是根据id操作,或者所有数据。
(1)我们上面有个特殊的查找方法,根据用户名和student来查找,用的是testJpaRepository.findByStudentAndUserName
,注意findByStudentAndUserName是jpa提供的规范,只能这么写,用select、query之类的都不行,只能用find开头,然后后面的Student和UserName必须是实体类中的字段,多个条件用and连接,驼峰。很麻烦。
(2)在上面特殊的删除方法,deleteSpecial
在dao层是要写SQL语句的,注解必须加,不加项目都启动不起来,除了写SQL,当然我们也可以根据JPA的规范,把方法名命名为:deleteByUserName,这样也能实现根据名字删除。
3.说说和mybatis-plus的对比,虽然都是封装了一些crud的方法,但是mybatis-plus提供了更加灵活的条件构造器,而且还有代码生成器,这方便的不是一点半点,我只想说mybatis-plus yyds,其他的自己体会。我想现在除了那种老项目,或者公司传承下来很庞大的框架,应该没有人会喜欢用JPA这东西,
但是迫于现实,我还是得用,害,卑微打工人。