1.创建springboot项目
2.在pom文件加入mybatis等坐标
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.1.1</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>6.0.5</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.12</version>
</dependency>
3.配置
server.port=8089
#druid���ݿ�����
spring.datasource.url=jdbc:mysql://localhost:3306/user?serverTimezone=UTC
spring.datasource.username=root
spring.datasource.password=123456
spring.datasource.driverClassName=com.mysql.cj.jdbc.Driver
#ʹ��Druid����Դ
spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
mybatis.mapper-locations=classpath:/mapper/*.xml
4.单个用户插入数据:
代码:userMapper
@Mapper
public interface UserMapper {
public void save(User user);
public User selectById(Long id);
}
user:
@Data
@Accessors
@ToString
public class User {
private Long id;
private String password;
private String name;
private Long roleId;
private Date createTime;
private Date updateTime;
private Role role;
}
userMapper.xml
<?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="com.example.demo.mapper.UserMapper">
<resultMap id="user" type="com.example.demo.po.User">
<id column="id" property="id" jdbcType="BIGINT"></id>
<result column="name" property="name" jdbcType="VARCHAR"></result>
<result column="role_id" property="roleId" jdbcType="BIGINT"></result>
<result column="password" property="password" jdbcType="VARCHAR"></result>
<result column="create_time" property="createTime" jdbcType="TIMESTAMP"></result>
<result column="update_time" property="updateTime" jdbcType="TIMESTAMP"></result>
测试代码:
@Test
public void testSave() {
User user = new User();
user.setPassword("111");
user.setRoleId(1l);
user.setName("aaa");
userMapper.save(user);
}
接下来做user和role一对一查询:即一个用户对应一个角色
代码:userMapper
public User selectById(Long id);
userMapper.xml
<resultMap id="user" type="com.example.demo.po.User">
<id column="id" property="id" jdbcType="BIGINT"></id>
<result column="name" property="name" jdbcType="VARCHAR"></result>
<result column="role_id" property="roleId" jdbcType="BIGINT"></result>
<result column="password" property="password" jdbcType="VARCHAR"></result>
<result column="create_time" property="createTime" jdbcType="TIMESTAMP"></result>
<result column="update_time" property="updateTime" jdbcType="TIMESTAMP"></result>
<!--association 用来关联对象的, property对应user表里的role变量,column对应数据库表user里的role_id字段-->
<association property="role" column="role_id" javaType="com.example.demo.po.Role" select="com.example.demo.mapper.RoleMapper.selectById"></association>
</resultMap>
<sql id="user_columns">
id, name,password
</sql>
<select id="selectById" resultMap="user">
select * from user where id = #{id}
</select>
roleMapper
@Mapper
public interface RoleMapper {
public Role selectById(Long id);
}
roleMapper.xml
<select id="selectById" resultMap="role">
select * from role where id = #{id}
</select>
测试:
@Test
public void testUserSe() {
User user = userMapper.selectById(1L);
System.out.println(user);
}
结果:
Mon Dec 09 21:29:46 CST 2019 WARN: Establishing SSL connection without server's identity verification is not recommended. According to MySQL 5.5.45+, 5.6.26+ and 5.7.6+ requirements SSL connection must be established by default if explicit option isn't set. For compliance with existing applications not using SSL the verifyServerCertificate property is set to 'false'. You need either to explicitly disable SSL by setting useSSL=false, or set useSSL=true and provide truststore for server certificate verification.
2019-12-09 21:29:46.099 DEBUG 78268 --- [ main] c.e.demo.mapper.UserMapper.selectById : ==> Preparing: select * from user where id = ?
2019-12-09 21:29:46.124 DEBUG 78268 --- [ main] c.e.demo.mapper.UserMapper.selectById : ==> Parameters: 1(Long)
2019-12-09 21:29:46.143 DEBUG 78268 --- [ main] c.e.demo.mapper.RoleMapper.selectById : ====> Preparing: select * from role where id = ?
2019-12-09 21:29:46.143 DEBUG 78268 --- [ main] c.e.demo.mapper.RoleMapper.selectById : ====> Parameters: 1(Long)
2019-12-09 21:29:46.211 DEBUG 78268 --- [ main] c.e.demo.mapper.RoleMapper.selectById : <==== Total: 1
2019-12-09 21:29:46.212 DEBUG 78268 --- [ main] c.e.demo.mapper.UserMapper.selectById : <== Total: 1
2019-12-09 21:29:46.214 DEBUG 78268 --- [ main] c.e.d.m.ResourceMapper.selectByRoleId : ==> Preparing: select * from resource where role_id = ?
2019-12-09 21:29:46.214 DEBUG 78268 --- [ main] c.e.d.m.ResourceMapper.selectByRoleId : ==> Parameters: 1(Long)
2019-12-09 21:29:46.217 DEBUG 78268 --- [ main] c.e.d.m.ResourceMapper.selectByRoleId : <== Total: 2
User(id=1, password=111, name=aaa, roleId=1, createTime=Tue Dec 10 04:51:22 CST 2019, updateTime=Tue Dec 10 04:51:22 CST 2019, role=Role(id=1, name=老师, createTime=Tue Dec 10 04:59:03 CST 2019, updateTime=Tue Dec 10 04:59:03 CST 2019, resources=[Resource(id=1, name=查看, createTime=Tue Dec 10 04:59:26 CST 2019, updateTime=Tue Dec 10 04:59:26 CST 2019, roleId=1), Resource(id=2, name=增加, createTime=Tue Dec 10 04:59:26 CST 2019, updateTime=Tue Dec 10 04:59:26 CST 2019, roleId=1)]))
2019-12-09 21:29:46.247 INFO 78268 --- [extShutdownHook] com.alibaba.druid.pool.DruidDataSource : {dataSource-1} closed
2019-12-09 21:29:46.248 INFO 78268 --- [extShutdownHook] o.s.s.concurrent.ThreadPoolTaskExecutor : Shutting down ExecutorService 'applicationTaskEx
接下来做一对多嵌套查询。一个角色对应多个资源 :
roleMapper
@Mapper
public interface ResourceMapper {
public List<Resource> selectByRoleId(Long roleId);
}
roleMapper.xml
<?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="com.example.demo.mapper.ResourceMapper">
<resultMap id="resource" type="com.example.demo.po.Resource">
<id column="id" property="id" jdbcType="BIGINT"></id>
<result column="role_id" property="roleId" jdbcType="BIGINT"></result>
<result column="name" property="name" jdbcType="VARCHAR"></result>
<result column="create_time" property="createTime" jdbcType="TIMESTAMP"></result>
<result column="update_time" property="updateTime" jdbcType="TIMESTAMP"></result>
</resultMap>
<sql id="user_columns">
</sql>
<select id="selectByRoleId" resultMap="resource">
select * from resource where role_id = #{roleId}
</select>
</mapper>
roleMapper.xml
<?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="com.example.demo.mapper.RoleMapper">
<resultMap id="role" type="com.example.demo.po.Role">
<id column="id" property="id" jdbcType="BIGINT"></id>
<result column="name" property="name" jdbcType="VARCHAR"></result>
<result column="create_time" property="createTime" jdbcType="TIMESTAMP"></result>
<result column="update_time" property="updateTime" jdbcType="TIMESTAMP"></result>
<collection property="resources" column="id" javaType="java.util.List" select="com.example.demo.mapper.ResourceMapper.selectByRoleId"></collection>
</resultMap>
<select id="selectById" resultMap="role">
select * from role where id = #{id}
</select>
</mapper>
测试代码:
@Test
public void testRoleSe() {
Role role = roleMapper.selectById(new Long(1));
System.out.println(role.toString());
}
结果:
2019-12-09 21:08:36.376 INFO 97936 --- [ main] com.alibaba.druid.pool.DruidDataSource : {dataSource-1} inited
Mon Dec 09 21:08:36 CST 2019 WARN: Establishing SSL connection without server's identity verification is not recommended. According to MySQL 5.5.45+, 5.6.26+ and 5.7.6+ requirements SSL connection must be established by default if explicit option isn't set. For compliance with existing applications not using SSL the verifyServerCertificate property is set to 'false'. You need either to explicitly disable SSL by setting useSSL=false, or set useSSL=true and provide truststore for server certificate verification.
2019-12-09 21:08:36.697 DEBUG 97936 --- [ main] c.e.demo.mapper.RoleMapper.selectById : ==> Preparing: select * from role where id = ?
2019-12-09 21:08:36.719 DEBUG 97936 --- [ main] c.e.demo.mapper.RoleMapper.selectById : ==> Parameters: 1(Long)
2019-12-09 21:08:36.737 DEBUG 97936 --- [ main] c.e.d.m.ResourceMapper.selectByRoleId : ====> Preparing: select * from resource where role_id = ?
2019-12-09 21:08:36.738 DEBUG 97936 --- [ main] c.e.d.m.ResourceMapper.selectByRoleId : ====> Parameters: 1(Long)
2019-12-09 21:08:36.740 DEBUG 97936 --- [ main] c.e.d.m.ResourceMapper.selectByRoleId : <==== Total: 2
2019-12-09 21:08:36.741 DEBUG 97936 --- [ main] c.e.demo.mapper.RoleMapper.selectById : <== Total: 1
Role(id=1, name=老师, createTime=Tue Dec 10 04:59:03 CST 2019, updateTime=Tue Dec 10 04:59:03 CST 2019, resources=[Resource(id=1, name=查看, createTime=Tue Dec 10 04:59:26 CST 2019, updateTime=Tue Dec 10 04:59:26 CST 2019, roleId=1), Resource(id=2, name=增加, createTime=Tue Dec 10 04:59:26 CST 2019, updateTime=Tue Dec 10 04:59:26 CST 2019, roleId=1)])
2019-12-09 21:08:36.769 INFO 97936 --- [extShutdownHook] com.alibaba.druid.pool.DruidDataSource : {dataSource-1} closed
2019-12-09 21:08:36.770 INFO 97936 --- [extShutdownHook] o.s.s.concurrent.ThreadPoolTaskExecutor : Shutting down ExecutorService 'applicationTaskExecutor'
Process finished with exit code 0
通过上面可以看到一个老师对象对应了两个资源。而且从上面可以看到日志里查询了两次数据库。其实这也反映了嵌套查询有个问题,激素N+1问题。
N+1问题,简单说,在这例子就是查询了1(1)个老师数据和2(N)个资源数据。
有时候我们查询仅仅只需要查询老师的属性,并不需要马上拿到对应的资源。这时候可以在collection标签里加个属性fetchType="lazy",即加上懒加载(只有在需要的时候才进行加载)
测试:
@Test
public void testRoleSe() {
Role role = roleMapper.selectById(new Long(1));
System.out.println(role.getName());
}
结果:
2019-12-09 21:16:04.076 INFO 102712 --- [ main] com.example.demo.mapper.UserMapperTest : Started UserMapperTest in 7.995 seconds (JVM running for 9.684)
2019-12-09 21:16:04.649 INFO 102712 --- [ main] com.alibaba.druid.pool.DruidDataSource : {dataSource-1} inited
Mon Dec 09 21:16:04 CST 2019 WARN: Establishing SSL connection without server's identity verification is not recommended. According to MySQL 5.5.45+, 5.6.26+ and 5.7.6+ requirements SSL connection must be established by default if explicit option isn't set. For compliance with existing applications not using SSL the verifyServerCertificate property is set to 'false'. You need either to explicitly disable SSL by setting useSSL=false, or set useSSL=true and provide truststore for server certificate verification.
2019-12-09 21:16:04.849 DEBUG 102712 --- [ main] c.e.demo.mapper.RoleMapper.selectById : ==> Preparing: select * from role where id = ?
2019-12-09 21:16:04.872 DEBUG 102712 --- [ main] c.e.demo.mapper.RoleMapper.selectById : ==> Parameters: 1(Long)
2019-12-09 21:16:04.963 DEBUG 102712 --- [ main] c.e.demo.mapper.RoleMapper.selectById : <== Total: 1
老师
2019-12-09 21:16:04.993 INFO 102712 --- [extShutdownHook] com.alibaba.druid.pool.DruidDataSource : {dataSource-1} closed
2019-12-09 21:16:04.994 INFO 102712 --- [extShutdownHook] o.s.s.concurrent.ThreadPoolTaskExecutor : Shutting down ExecutorService 'applicationTaskExecutor'
Process finished with exit code 0
从上面可以看到跟上一个例子,并没有把资源数据查出来。这样就可以解决N+1问题
有兴趣的可以关注公众号:码上行走
来源:CSDN
作者:ldlly0505
链接:https://blog.csdn.net/ldlly0505/article/details/103465872