环境搭建
创建maven项目导入坐标
<!-- junit单元测试 -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<!--spring data jpa-->
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-jpa</artifactId>
<version>2.4.2</version>
</dependency>
<!--jpa的实现hibernate核心包-->
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>5.4.27.Final</version>
</dependency>
<!-- c3p0数据库连接池 -->
<dependency>
<groupId>c3p0</groupId>
<artifactId>c3p0</artifactId>
<version>0.9.1.2</version>
</dependency>
<!-- log日志 -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.6.6</version>
</dependency>
<!--spring 测试-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>5.3.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.22</version>
</dependency>
编写Spring配置类(纯java方式整合)
@Configuration
@EnableJpaRepositories(basePackages="cn.itcast.dao") // jpa要扫描的dao接口包
@EnableTransactionManagement //开启事务管理
@ComponentScan("cn.itcast") //spring 扫描的包
public class SpringConfig {
/*
* 配置数据源
* */
@Bean
public DataSource dataSource() {
ComboPooledDataSource comboPooledDataSource = new ComboPooledDataSource();
try {
comboPooledDataSource.setDriverClass("com.mysql.cj.jdbc.Driver");
} catch (PropertyVetoException e) {
e.printStackTrace();
}
comboPooledDataSource.setJdbcUrl("jdbc:mysql://localhost:3306/jpa?useSSL=false&allowPublicKeyRetrieval=true&serverTimezone=UTC");
comboPooledDataSource.setUser("root");
comboPooledDataSource.setPassword("123456");
return comboPooledDataSource;
}
/*
* 整合spring data jpa
* */
@Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory(DataSource dataSource) {
LocalContainerEntityManagerFactoryBean factory = new LocalContainerEntityManagerFactoryBean();
//jpa的供应商适配器
HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
// 自动创建数据库表
vendorAdapter.setGenerateDdl(true);
// 显示sql语句
vendorAdapter.setShowSql(true);
// 指定数据库类型
vendorAdapter.setDatabase(Database.MYSQL);
// 指定数据库方言,mysql默认方言MySQL57InnoDBDialect,即MySQL5.7版本以上才行
// vendorAdapter.setDatabasePlatform("org.hibernate.dialect.MySQL57InnoDBDialect");
factory.setJpaVendorAdapter(vendorAdapter);
factory.setJpaDialect(new HibernateJpaDialect());
// jpa要扫描的实体类
factory.setPackagesToScan("cn.itcast.domain");
factory.setDataSource(dataSource);
}
/*
* 事务管理器
* */
@Bean
public PlatformTransactionManager transactionManager(EntityManagerFactory entityManagerFactory) {
JpaTransactionManager txManager = new JpaTransactionManager();
txManager.setEntityManagerFactory(entityManagerFactory);
return txManager;
}
}
编写实体类
@Data
@Entity
@Table(name="sys_user")
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id; // 尽量使用包装类
@Column(name = "sys_username",length = 50)
private String username;
@Column(name = "sys_password",length = 50)
private String password;
@Column(name = "sys_money")
private Integer money;
}
数值类型尽量使用包装类,如Integer的默认为null,而int默认是0,在后续的更新操作中会有影响
编写Dao层接口
public interface UserDao extends JpaRepository<User, Integer>, JpaSpecificationExecutor<User> {
}
你没有看错,就是继承JpaRepository
和JpaSpecificationExecutor
这两个接口好了。其中:
JpaRepository<<User, Integer>
: 用于简单的CRUD操作,User
表示要操作的实体类,Integer
表示该实体类主键的类型JpaSpecificationExecutor<User>
: 用于复杂查询(动态条件查询、分页等等)
编写测试类
本案例将使用spring整合junit作为测试
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = SpringConfig.class)
public class UserTest {
@Autowired
private UserDao userDao;
// 即将要写的测试用例
}
到此环境搭建已经完成,接下来开始增删改查操作
实现CURD操作
以下代码都是UserTest.java
单元测试类中编写
保存用户
@Test
public void test2() {
// 本次没有给id赋值为保存用户操作
User user = new User();
user.setUsername("张三");
user.setPassword("123456");
user.setMoney(1000);
userDao.save(user);
}
即保存用户和更新用户信息都是用的save()
方法。
- 如果执行此方法是对象中存在id属性,即为更新操作会先根据id查询,再更新
- 如果执行此方法中对象中不存在id属性,即为保存操作
根据id
查询用户
使用立即加载
@Test
public void testFindById1() {
Optional<User> optionalUser = userDao.findById(2);
// 如果找到返回,找不到则为null
User user = optionalUser.orElse(null);
// 如果直接调用get方法找不到就会抛异常
// User user = optionalUser.get();
System.out.println(user);
}
使用延迟加载
必须在事务中操作,否则会报错
@Test
@Transactional // 在事务中操作
public void testFindById2() {
User user = userDao.getOne(2);
System.out.println(user);
}
更新用户
@Test
public void testUpdate() {
// 先查询到该用户
Optional<User> optionalUser = userDao.findById(4);
User user = optionalUser.get();
// 修改用户信息
user.setMoney(0);
// 更新操作
userDao.save(user);
}
如果在事务中的话也可以这样操作
@Test
@Transactional
@Rollback(false) // 在单元测试中,关闭事务的自动回滚,否则数据不改变
public void testUpdate() {
// 先查询到该用户
Optional<User> optionalUser = userDao.findById(4);
User user = optionalUser.get();
// 修改用户信息
user.setMoney(0);
}
就是在事务中修改实体类信息可以自动更新到数据库中,而不用手动调用save()
方法
查询用户个数
@Test
public void testCount() {
long count = userDao.count();
System.out.println("用户个数:"+count);
}
这没什么好说的,so seay
根据id
删除用户
@Test
public void testDelete() {
userDao.deleteById(3);
}
查询所有用户信息
@Test
public void test1() {
List<User> users = userDao.findAll();
for (User user : users) {
System.out.println(user);
}
}
判断用户是否存在
@Test
public void testExists() {
// 根据id判断用户是否存在
// boolean b = userDao.existsById(1);
// 根据用户名判断用户是否存在
User user = new User();
user.setUsername("张三三");
// 构造查询条件
Example<User> example = Example.of(user);
boolean b = userDao.exists(example);
System.out.println("该用户是否存在:"+b);
}