0%

java之spring整合orm之Jdbc,Mybatis

说明

  • 本次教程主要来自这里
  • 环境信息:win10 、java1.8、IDEA 社区版本

整合JDBC

  • 用IDEA 社区版本新建个maven项目
  • pom.xml的依赖文件如下
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

<groupId>org.example</groupId>
<artifactId>spring-quickstart1</artifactId>
<version>1.0-SNAPSHOT</version>

<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.2.16.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.2.16.RELEASE</version>
</dependency>
<!--数据库连接池 -->
<dependency>
<groupId>com.zaxxer</groupId>
<artifactId>HikariCP</artifactId>
<version>3.4.2</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.13</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.20</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
</dependencies>
</project>
  • 实体类
1
2
3
4
5
6
7
8
9
package xyz.shi.entity;

import lombok.Data;
@Data
public class User {
private int id;
private String name;
private String password;
}
  • springconfig配置类,主要用于扫描路径
1
2
3
4
5
6
7
8
9
10
package xyz.shi.config;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

@Configuration
@ComponentScan("xyz.shi")
public class SpringConfig {
}

  • jdbc的配置文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
package xyz.shi.config;

import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.core.JdbcTemplate;

import javax.sql.DataSource;

//表明当前类是spring的一个配置类,作用是替代spring的applicationContext.xml。
// 但其本质就是@Component注解,被此注解修饰的类,也会被存入spring的ioc容器
@Configuration
public class JDBCConfig {
//@Bean通常出现在Spring的配置类当中,注解在方法上,表示把当前方法的返回值存入spring的ioc容器
@Bean
public DataSource dataSource() {
HikariConfig hikariConfig = new HikariConfig();
hikariConfig.setPassword("123456");
hikariConfig.setUsername("root");
hikariConfig.setJdbcUrl("jdbc:mysql://localhost:3306/test?serverTimezone=UTC");
hikariConfig.setDriverClassName("com.mysql.cj.jdbc.Driver");
hikariConfig.addDataSourceProperty("autoCommit", "true");
hikariConfig.addDataSourceProperty("connectionTimeout", "5");
hikariConfig.addDataSourceProperty("idleTimeout", "60");
return new HikariDataSource(hikariConfig);
}
@Bean
public JdbcTemplate jdbcTemplate(@Autowired DataSource dataSource) {
return new JdbcTemplate(dataSource);
}
}
  • service代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
package xyz.shi.service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.support.GeneratedKeyHolder;
import org.springframework.jdbc.support.KeyHolder;
import org.springframework.stereotype.Service;
import xyz.shi.entity.User;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;

@Service
public class UserService1 {
@Autowired
private JdbcTemplate jdbcTemplate;

public int save(String name, String pwd) {
//该类返回新增记录时的自增长主键值。
KeyHolder keyHolder = new GeneratedKeyHolder();
int update = jdbcTemplate.update((connection) -> {
PreparedStatement ps = connection.prepareStatement("insert into users(name,password) values(?,?)", Statement.RETURN_GENERATED_KEYS);

ps.setObject(1, name);
ps.setObject(2, pwd);
return ps;
}, keyHolder);
if (update > 0){
System.out.println("保存成功...user id:"+keyHolder.getKey());
}
return keyHolder.getKey().intValue();
}

/**
* 根据用户id 查询
* @param id
* @return
*/
public User getUser(int id){
User user = jdbcTemplate.queryForObject("select * from users where id = ?", new Object[]{id},new BeanPropertyRowMapper<>(User.class));
return user;
}

/**
* 分页查询
* @param page
* @param pageSize
* @return
*/
public List<User> queryUserList(int page, int pageSize){
int index = (page-1)*pageSize;
int size = pageSize;
List<User> list = jdbcTemplate.query("select * from users limit ?,?", new Object[]{index, size}, new BeanPropertyRowMapper<>(User.class));
return list;
}

/**
* 更新
* @param id
* @param name
* @return
*/
public boolean update(int id,String name){
int update = jdbcTemplate.update("update users set name=? where id=?", name, id);
if (update > 0){
return true;
}
throw new RuntimeException("update error");
}

public boolean delete(int id){
int deleteCount = jdbcTemplate.update("delete from users where id=?", id);
return deleteCount > 0;
}
// execute的用法
public List<User> execute1(int page,int pageSize) {
return jdbcTemplate.execute((Connection conn) -> {
PreparedStatement ps = conn.prepareStatement("select * from users limit ?,?");
ps.setObject(1, (page - 1) * pageSize);
ps.setObject(2, pageSize);
ResultSet resultSet = ps.executeQuery();
List<User> userList = new ArrayList<>();
while (resultSet.next()) {
User user = new User();
user.setId(resultSet.getInt("id"));
user.setName(resultSet.getString("name"));
user.setPassword(resultSet.getString("password"));
userList.add(user);
}
return userList;
});
}
}

注意execute的用法

  • 测试
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import xyz.shi.config.SpringConfig;
import xyz.shi.entity.User;
import xyz.shi.service.UserService1;

import java.util.List;

public class jdbcTest {
ApplicationContext context = new AnnotationConfigApplicationContext(SpringConfig.class);

UserService1 userService = context.getBean(UserService1.class);
@Test
public void save() {
int id = userService.save("test1234","22222");
System.out.println(id);
}
@Test
public void find() {
User user = userService.getUser(46);
System.out.println(user);
}
@Test
public void queryUserList() {
List<User> users = userService.queryUserList(1, 2);
System.out.println(users);
}
@Test
public void update() {
userService.update(46, "哈哈");
}
@Test
public void delete() {
boolean flag = userService.delete(46);
System.out.println(flag);

}
@Test
public void execute1() {
List<User> users1 = userService.execute1(1,3);
System.out.println(users1);
}
}

整合Mybatis

SqlSessionFactory是mybatis的核心,当与spring进行整合时,我们使用mybatis-spring提供的SqlSessionFactoryBean 来创建其实例,SqlSessionFactoryBean实现了FactoryBean 接口

  • 依赖包
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
	<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

<groupId>org.example</groupId>
<artifactId>spring-mybatis</artifactId>
<version>1.0-SNAPSHOT</version>

<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.2.16.RELEASE</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.20</version>
</dependency>
<dependency>
<groupId>com.zaxxer</groupId>
<artifactId>HikariCP</artifactId>
<version>3.4.2</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.2.16.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>5.2.16.RELEASE</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.13</version>
</dependency>
<!--spring整合mybatis-->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>2.0.3</version>
</dependency>

<!--mybatis环境-->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.3</version>
</dependency>
<!--分页插件坐标-->
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper</artifactId>
<version>5.2.1</version>
</dependency>
</dependencies>
<build>

<!--目的是把src/main/java目录中的xml文件包含到输出结果中,也就是输出到classes目录中-->
<resources>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>false</filtering>
</resource>
<resource>
<directory>src/main/resources</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>false</filtering>
</resource>
</resources>

</build>
</project>
  • 下面是xml的配置方式,resources/application.xml,主要配置了连接数据库、SqlSessionFactory等信息
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">


<bean id="hikariConfig" class="com.zaxxer.hikari.HikariConfig">
<property name="jdbcUrl" value="jdbc:mysql://localhost:3306/test?characterEncoding=utf8&amp;serverTimezone=UTC"/>
<property name="username" value="root"/>
<property name="password" value="123456"/>
<property name="driverClassName" value="com.mysql.cj.jdbc.Driver"/>
<property name="autoCommit" value="true"/>
<property name="connectionTimeout" value="5000" />
<property name="idleTimeout" value="60" />
</bean>
<!--jdbc的xml配置-->
<bean id="myDataSource" class="com.zaxxer.hikari.HikariDataSource">
<constructor-arg name="configuration" ref="hikariConfig"/>
</bean>
<!--mybatis-->
<!--SqlSessionFactory-->
<!--声明的是mybatis中提供的SqlSessionFactoryBean类,这个类内部创建SqlSessionFactory-->
<bean id="SqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<!--set注入,把数据库连接池付给dataSource属性-->
<property name="dataSource" ref="myDataSource"/>
<!--mybatis主配置文件的位置
configLocation属性是Resource类型,读取配置文件
它的赋值使用的是value , 指定文件的路径,使用的是classpath:表示文件的位置
-->
<property name="configLocation" value="classpath:mybatis.xml"/>
<property name="plugins">
<array>
<bean class="com.github.pagehelper.PageInterceptor">
<property name="properties">
<props>
<prop key="helperDialect">mysql</prop>
</props>
</property>
</bean>
</array>
</property>
</bean>
<!--创建 dao对象
使用SqlSession的getMapper(userDao.class)
MapperScannerConfigurer在内部调用getMapper()生成每个dao接口的代理对象
-->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<!--指定的是SqlSessionFactory对象的id-->
<property name="sqlSessionFactoryBeanName" value="SqlSessionFactory"/>
<!--指定包名,包名是dao接口所在的包名
MapperScannerConfigurer会扫描这个包中的所有接口,把每个接口都执行
一次getMapper()方法,得到每个接口的dao对象
创建好的dao对象放入到spring的容器中

dao默认对象的名称:是接口名字的首字母小写
-->

<property name="basePackage" value="xyz.shi.dao"/>
<!--多个包-->
<!--<property name="basePackage" value="com.md.dao,com.md.dao2"/>-->

</bean>
<!--下面的就是自己定义的service-->
<!--声明service-->
<bean id="userService" class="xyz.shi.service.Impl.UserServiceImpl">
<!--就是上面通过创建的dao对象-->
<property name="userDao" ref="userDao"/>
</bean>
</beans>
  • resources/mybatis.xml,基本配置
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">

<configuration>


<!--settings:控制mybatis全局行为-->
<settings>

<!--设置mybatis输出日志-->
<setting name="logImpl" value="STDOUT_LOGGING"/>
</settings>


<!--设置别名-->
<typeAliases>
<!--
package:把包下面的所有类名作为别名
name:实体类所在的包名-->
<package name="xyz.shi.entity"/>

</typeAliases>



<!-- sql映射文件的位置 -->
<mappers>
<!-- 注册userMapper.xml文件 -->
<mapper resource="mapper/UserMapper.xml"/>
</mappers>

</configuration>

  • resources/mapper/userMapper.xml,写入sql信息
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="xyz.shi.dao.UserDao">

<insert id="save" parameterType="xyz.shi.entity.User" keyProperty="id" useGeneratedKeys="true">
insert into users(name,password)
value(#{name},#{password})
</insert>
<update id="update" parameterType="xyz.shi.entity.User">
update users set name=#{name},password=#{password} where id=#{id}
</update>
<delete id="delete" parameterType="int">
delete from users where id=#{id}
</delete>
<select id="findById" parameterType="int" resultType="xyz.shi.entity.User">
select * from users where id = #{id};
</select>
<select id="findAll" resultType="xyz.shi.entity.User">
select * from users
</select>
</mapper>

记得一定要把resources目录设置为Resources Root,不然读取application.xml报错不存在此文件

  • 写mapper的接口,其实就是dao层,我用的dao
1
2
3
4
5
6
7
8
9
10
11
12
13
14
package xyz.shi.dao;

import com.github.pagehelper.Page;
import xyz.shi.entity.User;

// 注意这里的方法名称,一定要和mapper.xml中的id名称一致,不然无法映射到就会报错
public interface UserDao {
int save(User user);
int update(User user);
User findById(int id);
Page<User> findAll();
int delete(int id);
}

  • Service的Mybatis实现,增删改查
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
package xyz.shi.service;

import com.github.pagehelper.Page;
import org.springframework.stereotype.Service;
import xyz.shi.entity.User;

@Service
public interface UserService {
int save(User user);
Page<User> findAll();
int update1(User user);
int delete(int id);
}


  • userdao的实现接口
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
package xyz.shi.service.Impl;

import com.github.pagehelper.Page;
import xyz.shi.dao.UserDao;
import xyz.shi.entity.User;
import xyz.shi.service.UserService;

public class UserServiceImpl implements UserService {
// 引用类型
private UserDao userDao;
// 为了使用set注入来赋值,一定要加这个
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
@Override
public int save(User user) {
return this.userDao.save(user);
}

@Override
public Page<User> findAll() {
return userDao.findAll();
}

@Override
public int update1(User user) {
return userDao.update(user);
}

@Override
public int delete(int id) {
return userDao.delete(id);
}
}

  • 测试
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
iimport com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import xyz.shi.entity.User;
import xyz.shi.service.UserService;

import java.util.Arrays;
import java.util.List;

public class MybatisTest {
ApplicationContext context = new ClassPathXmlApplicationContext("application.xml");
// 其实就是调用的app..xml中的<bean id="userService" class="xyz.shi.service.Impl.UserServiceImpl">
UserService userMybatisService = (UserService) context.getBean("userService");

@Test
public void save() {
User user = new User();
user.setName("test009");
user.setPassword("1234566");
int num = userMybatisService.save(user);
System.out.println(num);
}
@Test
public void findAll() {
//在查询之前,设置分页条件 显示第一页,展示3条数据
Page<Object> page = PageHelper.startPage(1, 3);
List<User> userList = userMybatisService.findAll();
// 设置分页导航数量5
PageInfo<User> pageInfo = new PageInfo<>(userList, 5);
for (User user:userList) {
System.out.println("------每个用户的信息-------");
System.out.println(user.getName());
System.out.println(user.getPassword());
}
System.out.println();
///xxx
System.out.println("---------全面配置信息:--------");
System.out.println("总数据量 :"+pageInfo.getTotal());
System.out.println("每页的数量:"+pageInfo.getPageSize());
System.out.println("当前页码:"+pageInfo.getPageNum());
System.out.println("是否有上一页:"+pageInfo.isHasPreviousPage());
System.out.println("上一页是:"+pageInfo.getPrePage());
System.out.println("是否有下一页:"+pageInfo.isHasNextPage());
System.out.println("下一页是:"+pageInfo.getNextPage());
System.out.println("是否是第一页:"+pageInfo.isIsFirstPage());
System.out.println("是否是最后一页:"+pageInfo.isIsLastPage());
System.out.println("导航页的第一个页码是:"+pageInfo.getNavigateFirstPage());
System.out.println("导航页的最后一个页码是:"+pageInfo.getNavigateLastPage());
System.out.println("每页显示的页码个数:"+pageInfo.getNavigatePages());
System.out.println("页码数:"+ Arrays.toString(pageInfo.getNavigatepageNums()));
}

@Test
public void update() {
User user = new User();
user.setId(41);
user.setName("test41");
user.setPassword("111111");
userMybatisService.update1(user);
}
@Test
public void delete() {
userMybatisService.delete(48);
}
}


总结

  • 注意resources目录的设置要为Resources Root
  • UserDao中的方法一定要和mapper.xml中的id一致
  • 源代码