mabatis learning notes (only record your learning process)

Keywords: Mybatis SQL SSM IDEA

set up a database

create database 'mybatis'
use 'mybatis';
create table 'user'(
	'id' int(20) not null primary key,
	'name' varchar(30) default null,
	'pwd' varchar(30) default null
)engine = innodb default charset= utf-8;

insert into 'user'('id','name','pwd') values
(1,'Mad God','123456'),
(2,'Mad God','123456'),
(3,'Mad God','123456');

//Mybatis-config.xml is the core configuration file of mabatis, which is written under the resources file

<configuration>
	<environments default="development">
	<environment>
		<transactionManager type="JDBC"/>
		<dataSource>
			<property name="driver" value=""/>
			<property name="url" value=""/>
			<property name="username" value=""/>
			<property name="password" value=""/>
			
		</dataSource>
	</environment>
</environments>

be careful::::::::::::::every last Mapper.xml All need to be in mabatis Register in core profile
<mappers>
	<mapper resource = "com/kuang/dao/UserMapper.xml">
</mappers>

</configuration>

//Tool class sqlsessionfactory -- > sqlsession

public class MybatisUtils{
	private static SqlSessionFactory sqlSessionFactory;
	static{
		String resource="mybatis-config.xml"
		InputStream inputStream = Resources.getResourceAsStream(resource);
		sqlSessionFactory = new  SqlSessionFactoryBuilder().build(inputStream)
	}
	//With SqlSession, you can obtain an instance of SqlSession from the summary
	//SqlSession completely contains all the methods required to execute Sql commands for the database
	public static SqlSession getSqlSession(){
		return sqlSessionFactory.openSession();	
	}
		
}

//Entity class

public class User{
	private int id;
	private String name;
	private String pwd;
	
	public User(){}
	public User(){
		this.id = id;
		this.name = name;
		this.pwd = pwd;
	}
	
	
	get   set method  toString
}

//dao

public  interface UserDao{
	//Extensions: fuzzy queries
	List<User> getUserLike(String value);
	//Query all users
	List<User> getUserList();
	//Query user by id
	User getUserById(int id);
	//insert a user
	int addUser(User user);
	//By map
	int addUser(Map <String,Object>map)
	//Modify user
	int updateUser(User user);
	//Delete a user
	boolean deleteUser(int id);	
}
public class UserDaoImpl implements UserDao{
	public List<User> getUserList(){
		//Execute sql
		String sql = "select * from mybatis.user"
		//Result set 
		resultSet
	   	return null;
	}
}

//The interface implementation class is transformed from the original UserDaoImpl to a Mapper configuration file

//UserMapper.xml

<?xml version=1.0 encoding ="utf-8"?>
<!DOCTYPE=mapper PUBLIC "">
//namespace = bind a corresponding Dao/Mapper interface
<mapper namespace="com.kuang.dao.UserDao" >

	<select id ="getUserLike" resultType="com.kuang.pojo.User">
		select * from  mybatis.user where  name like "%"#{value}"%"
	</select>
	
	//The select query statement id is equivalent to the method name in the original impl implementation class	
	<select id = "getUserList" resultType="com.kuang.pojo.User">
		select * from mabatis.user
	</select>
	
	//Query user by ID
	<select id ="getUserById" parameterType="int" resultType="com.kuang.pojo.User" >
		select * from mybatis.user where id = #{id}
	</select>
	
	//insert a user
	<insert id ="addUser" parameterType="com.kuang.pojo.User">
		insert into  mybatis.user(id,name,pwd) values(#{id},#{name},#{pwd});
	</insert>
		
	//The universal map does not need to pass all parameters. It can only pass some parameters, not as many parameters as the object
	<insert id ="addUser" parameterType="map">
		insert into imybatis.user (id,pwd) values (#{userid},#{password})
	</insert>
	
	//Modify user
	<update  id = "upadateUser" parameterType="com.kuang.pojo.User">
		update mybatis.user set name= #{name},pwd=#{pwd} where id =#{id};
	</update>
	
	//Delete a user
	<delete id = "deleteUser" parameterType="int">
		delete from mybatis.user where id = #{id};
	</delete>
	
</mapper>
public class UserDaoTest{
	@Test
	public void getUserLike(){
		SqlSession sqlSession = MybatisUtils.getSqlSession();
		UserMapper mapper = sqlSession.getMapper(UserMapper.class);
		
		List<User> userlist = mapper.getUserLike("%Lee%");
		for(User user:userList){
			
		}
		
		sqlSession.commit();
		sqlSession.close();
	}

	@Test 
	public void test(){
		//Step 1: get SqlSession object
		SqlSesson sqlSession = MybatisUtils.getSqlSession();
		
		
		//Method 1: getMapper recommendation
		UserDao userDao = sqlSession.getMapper(UserDao.class);
		List<User> userList = userDao.getUserList();
		
		//Mode 2:
		List<User> userList = sqlSession.selectList("com.kuang.dao.UserDao.getUserList");
		
		for(User user :userList){
			System.out.println(userList);
		}
		sqlSession.close();		
	}
	
	@Test
	public void getUserById(){
		SqlSesson sqlSession = MybatisUtils.getSqlSession();
		UserMapper mapper = sqlSession.getMapper(UserMapper.class);
		User user = mapper.getUserById(1);
		System.out.println(user);
		
		sqlSession.close();
	}
	//Add, delete and modify transactions that need to be committed
	@Test 
	public void addUser(){
		SqlSession sqlSession = MybatisUtils.getSqlSession();
		UserMapper mapper  = sqlSession.getMapper(UserMapper.class) //Change the name of UserDao.class to UserMapper in the video
	
		
		int res = mapper.addUser(new User(4,"ha-ha","123132"));
		//Commit transaction (must be,,, otherwise the database will not change)
		sqlSession.commit();
		
		sqlSession.close();
	}
	
	@Test
	public void updateUser(){
		SqlSession sqlSession = MybatisUtils.getSqlSession();
		UserMapper mapper = sqlSession.getMapper(UserMapper.class);
		int num = mapper.upadateUser(new User(4,"seven seven","15646"));
		sqlSession.commit();
		sqlSession.close();
	}
	@Test
	public void deleteUser(){
		SqlSession sqlSession = MybatisUtils.getSqlSession();
		UserMapper mapper = SqlSession.getMapper(UserMapper.class);
		boolean result = mapper.deleteUser(4);
		sqlSession.commit();
		sqlSession.close();
		
	}
	
	//Universal map, with a map, you don't need to pass all the parameters
	@Test
	public void addUser2(){
		SqlSession sqlSession = MybatisUtils.getSqlSession();
		UserMapper mapper = sqlSession(UserMapper.class);
		Map <Srting,Object>map = new HashMap<String,Object>();
		map.put ("userid",5);
		map.put("password","33333");
		mapper.addUser2(map);
		sqlSession.close();
	}
	
}

//The package name in name should be consistent with the package name of Dao/mapper interface

select
Select query statement
id: is the method name in the corresponding namespace;
resultType: return value of Sql statement execution
parameterType: parameter type

Omnipotent map
Assuming that there are too many tables,, fields or parameters in our entity class or database, we should consider using Map

Map passes parameters. You can directly get the key from sql. parameterType = "map"
You can pass on whatever you want, which is equivalent to customization,,

Object passes parameters. You can directly get the attribute of the object in sql. parameterType = "object"

If there is only one basic parameter type, it is directly removed from sql,
boolean deleteUser(int id);

Map or annotation is used for multiple parameters.
boolean deleteUser(int id ,ArgType arg);

In xml, all tags can define order

Configuration resolution

Introducing external profiles into core profiles

<properties resource = "db.properties">
	<property name="username" value="root"/>
	<property name="pwd" value="1111"/>
</properties>

You can import external files directly
You can add some attribute configurations
If two files have the same field, the external configuration file is preferred

Core profile
mybatis-02
------------Db.properties (reintroduced in config to write parameter names directly)

driver = com.mysql.jdbc.Driver
url= jdbc:mysql:localhost:3306:mybatis?
username = root
password=root

Type alias (note the location in the configuration file) resultType = "com.kuang.pojo.User"
A type alias is a short name for a java type
The meaning of existence is only to reduce the redundancy of fully qualified names

You can give an entity class its alias



You can also specify a package name. MyBatis will search for the required Java beans under the package name
Scan the package of the entity class, and its default alias is the class name of the entity class, with lowercase initial


The first one is used when there are few entity classes
When there are many entity classes, the second one is recommended
The first one can customize the alias, and the second one can't. If you have to change it, you need to annotate the entity class

Last in lastName database_ Name is because it is converted to uppercase in oracal to increase readability

Other configurations
typeHandlers
objectFactory (object factory)
plugins plug-in
mybatis_generator=core
mybatis-plus
General mapper

mappers
MapperRegistry: register and bind our Mapper file

Mode 1:
<mappers>
	<mapper resource="com/kuang/dao/UserMapper.xml"
</mappers>
Mode 2: use class File binding registration
<mappers>
	<mapper class ="com.kuang.dao.UserMapper"/>
</mappers>

Note:
Interface and its Mapper configuration file must have the same name
The interface and its Mapper configuration file must be in the same file
Method 3: use scan package for injection binding



Note:
Interface and its Mapper configuration file must have the same name
The interface and its Mapper configuration file must be in the same file

Lifecycle and scope
Lifecycle and scope are critical, because incorrect usage leads to very serious concurrency problems
SqlSessionFactoryBuilder:
Once the ship has SqlSessionFactory, it is not needed
local variable
SqlSessionFactory
To put it bluntly, it is the database connection pool (it always exists after creation, waiting for others to connect, and finally recycled)
Once the SqlSessionFactory is pierced, it should always exist during the operation of the application. There is no reason to discard it or recreate another instance
Therefore, the best scope of SqlSessionFactory is the application scope

The simplest is to use local mode or static singleton mode.

SqlSession
 A request to connect to the connection pool
SqlSession The instance of is not thread safe, so it cannot be co absorbed. Therefore, its best scope is the request or method scope
 Close it immediately after use, otherwise the resources will be occupied

The sqlsessionfactorybuilder car factory built 100 cars and sold them to the sqlsessionfactory. Then it went bankrupt

Solve the problem of inconsistency between attribute name and field name
select * from mybatis.user where id = #{id}
select id,name,pwd from mybatis.user where id = #{id}
resolvent:

	Method 1: alias  
	<select id="get UserById" resultType="com.kuang.pojo.User">
		select id,name ,pwd  as password from mybatis.user where id = #{id}
	</select>
			
	Method 2: result mapping set resultMap
<resultMap id ="UserMap" type="User">
	<result column="id" property="id">  column Fields in the database, property Properties in entity classes
	<result column="name" property="name">
	<result column="pwd" property="password">
</resultMap>

<select id="getUserById" resultMap="UserMap">
		select * from mybatis.user where id = #{id}
</select>

The resultMap element is the most important and powerful element in MyBatis
The design idea of ResultMap is that there is no need to match simple statements at all
Set explicit result mapping, and for more complex statements, you only need to describe their relationship

journal:
Log factory
If an exception occurs in a database operation, we need the troubleshooting log 94 hi's best assistant
Once South debug
Now: log factory
In the mybatis core configuration file, configure our logs
Import package configuration file
to configure


Use limit paging-----------

select * from user limit startIndex,pageSize;
select * from user limit 0,3;

public interface UserMapper{
	//paging
	List<User> getUserLimit(Map<String,Integer> map);
}

<mapper namespace ="com.kuang.dao.UserMapper">
	//paging
	<select id = "getUserLimit" parameterType="map" /*resultType="user"*/ resultMap="UserMap">
		select * from mybatis.user limit #{startIndex},#{pageSize}
	</select>
</mapper>

public calss UserMapperTest{
	@Test
	public void getUserByLimit(){
		SqlSession sqlSession = MybatisUtils.getSqlSession();
		UserMapper mapper = sqlSession.getMapper(UserMapper.class);
		
		HashMap<String,Integer> map = new HashMap<String,Integer>();
		map.put("startIndex",0);
		map.put("pageSize",2);
		
		List<User> userByLimit = mapper.getUserByLimit(map);
		for(User user:userList){
			System.out.println(user);
		} 

		sqlSession.close();
	}
}

RowBounds paging---------
No longer use sql to implement paging

How to use annotations

public interface UserMapper{
	@Select("select * from user");
	List<User> getUsers();	
	
	//Method has multiple parameters. All parameters must be preceded by @ Param
	@Select("select * from user where id=#{id}")
	User getUserById(@Param("id") int id);
	
	@Insert("insert into user(id,name,pwd) value(#{id},#{name},#{pwd})")
	int addUser(User user);
		
	@Update("update user set name=#{name},pwd=#{password} where id = #{id}")
	int updateUser(User user);	
		
	@Delete("delete from user where id=#{id}")
	int deleteUser(@Param("uid") int id);	
}
<mappers>
	<mapper class="com.kaung.dao.UserMapper"/>
</mappers>

public class UserMapperTest{
	SqlSession sqlSession = MybatisUtils.getSqlSession();
	UserMapper mapper = sqlSession.getMapper(UserMapper.class);
	//List<User> user = mapper.getUsers();
	//for(User user :users){
	//	System.out.println(user);
	//}
	
	User userById = mapper.getUserById(1);
	System.out.println(userById);
	
	mapper.addUser(new User(5,"Hello","1231"));
		
	mapper.updateUser(new User(5,"hhh","123115"));
	
	mapper.deleteUser(5);
	
	sqlSession.close();
	
}

About @ Param() annotation
Basic type parameters or String types need to be added
Reference type does not need to be added
If there is only one basic type, it can be ignored, but it is recommended to add
What is referenced in sql is the reasonable attribute name set in @ Param()

#{} prevent sql injection,, ${}

Installing Lombok plug-in in DIEA
Find a jar package such as Lombok in the project
Just annotate the entity class

@Data: get set tostring hashcode equals
@AllArgsConstructor
@NoArgsConstructor

Many to one----------------
Multiple students, corresponding to a senior four and
For students, how about associating multiple students? When associating one, many to one
For teachers, set

CREATE TABLE `teacher` (
  `id` INT(10) NOT NULL,
  `name` VARCHAR(30) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=INNODB DEFAULT CHARSET=utf8

INSERT INTO teacher(`id`, `name`) VALUES (1, Miss Qin); 

CREATE TABLE `student` (
  `id` INT(10) NOT NULL,
  `name` VARCHAR(30) DEFAULT NULL,
  `tid` INT(10) DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `fktid` (`tid`),
  CONSTRAINT `fktid` FOREIGN KEY (`tid`) REFERENCES `teacher` (`id`)
) ENGINE=INNODB DEFAULT CHARSET=utf8INSERT INTO `student` (`id`, `name`, `tid`) VALUES (1, Xiao Ming, 1); 
INSERT INTO `student` (`id`, `name`, `tid`) VALUES (2, Xiao Hong, 1); 
INSERT INTO `student` (`id`, `name`, `tid`) VALUES (3, Xiao Zhang, 1); 
INSERT INTO `student` (`id`, `name`, `tid`) VALUES (4, petty thief, 1); 
INSERT INTO `student` (`id`, `name`, `tid`) VALUES (5, Xiao Wang, 1);

com.kuang.pojo

@Data
public classs Student{
	private int id;
	private String name;	
	//Students need to associate with a teacher
	private Teacher teacher;
}

@Data
public class Teacher{
	private  int id;
	private String name;
}
public interface StudentMapper{
	//Query all student information and corresponding teacher information	
	public List<Student> getStudent();
	public List<Student> getStudent2();
}

public interface TeacherMapper{
	@Select("select * from teacher where id =#{uid}")
	Teacher getTeacher(@Param("tid")int id);	
}

resources build package com.kaung.dao

StudentMapper.xml
=====================Nested processing by query

<mapper namespace="com.kuang.dao.StudentMapper">
	//<select id ="getStudent" resultType="Student">
	<select id ="getStudent" resultMap="StudentTeacher">		
		select * from student
	</select>
	
	<resultMap id="StudentTeacher" type="Student">
		<result property="id" column="id"/>
		<result property="name" column="name"/>
		//Complex attributes need to be handled separately, such as object association and collection
		<association property="teacher" column="tid" javaType="Teacher" select="getTeacher"/>		
	</resultMap>
	
	<select id="getTeacher" resultType="Teacher">
		select * from teacher where id = #{id}
	</select>	
</mapper>

=====================Nested processing according to results

<mapper namespace="com.kuang.dao.StudentMapper">
	<select id ="getStudent2" resultMap="StudentTeacher2">
		select s.id sid,s.name sname,t.name tname
		from studnet s,teacher t
		where s.tid= t.id;		
	</select>
	
	<resultMap id = "StudentTeacher2" type="Student">
		<result property="id" column="sid"/>
		<result property="name" column="sname"/>
		<association property="teachar" javaType="Teacher">
			<result property="name" column="tname"/>
		</association>
	</resultMap>
</mapper>

TeacherMapper.xml

<mapper namespace="com.kuang.dao.TeacherMapper">
</mapper>

mybatis.config.xml Add in
<mappers>
	<mapper resource="com/kuang/dao/*.xml"/>
</mappers>
public class MyTest{
	public static void main(String [] args){
		SqlSession	sqlSession = MybatisUtils.getSqlSession();
		TeacherMapper mapper =sqlSession.getMapper(TeacherMapper.class);		
		Teacher teacher = mapper.getTeacher(1);
		System.out.println(teacher);
		SqlSession.close();
	}
	
	@Test
	public void testStudent(){
		SqlSession	sqlSession = MybatisUtils.getSqlSession();		
		StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
		List<Student> student= mapper.getStudent();
		for(Student student:studentList){
			System.out.println(student);
		}
		
		SqlSession.close();
	}
	
}

Test environment construction
Import lombok
New entity class Teacher,Student
New Mapper interface
Create Mapper.XML file
Bind and register my Mapper interface file in the core configuration file
Test whether the query can succeed

One to many processing
For example, a teacher has multiple students
For teachers, it is one to many

@Data
public class Studnet{
	private int id ;
	private String name;
	private int tid;
}

@Data
public class Teacher{
	private int id;
	private String name;
	//A teacher has more than one student
	private List<Student> students;
}
public interface TeacherMapper{
	//Get teacher
	List<Teacher> getTeacher();
	//Get the information of all students and teachers under the specified teacher
	Teacher getTeacher(@Param(tid) int id);
	
	Teacher getTeacher2(@Param(tid) int id);
	
}

select s.id sid,s.name sname,t.name tname,t.id tid
from student s,teacher t
where s.tid = t.id
====================Nested query by result

<mapper namespace="com.kuang.dao.TeacherMapper">
	<select id="getTeacher" resultMap="TeacherStudent">
		select s.id sid,s.name sname,t.name tname,t.id tid
		from student s,teacher t
		where s.tid = t.id and t.id = #{tid}
	</select>
	
	<resultMap id="TeahcerStudent"  type="Teacher">
		<result property="id" column="tid"/>
		<result property="name" column="tname">
		//For complex attributes, we need to deal with the object association collection separately: collection
		//javaType = "specify the type of attribute", the generic information in the collection. We use ofType to get it
		<collection property="students" ofType="Student">
			<result property="name" column="sname">
			<result property="id" column="sid">
			<result property="tid" column="tid">
		</collection>
	</resultMap>
</mapper>

====================Nested processing by query

<select id = "getTeacher2" resultMap="TeacherStudent2">
	select * from mybatis.teacher where id = #{tid}
<select>
<resultMap id="TeacherStudent2" type="Teacher">
	<result property="id" column="tid"/>
	<result property="name" column="tname"/>
	
	<collection property="students" column="id" javaType="ArrayList" ofType="Student">
	</collection>
	
	<select id = "getStudentByTeacherId" resultType="Student">
		select * from mybatis.student where tid=#{tid} 
	</select>
</resultMap>
public classs MyTest{
	@Test
	public void test(){
		SqlSession sqlSession = MybatisUtils.getSqlSession();
		TeacherMapper mapper = sqlSession.getMapper(TeacherMapper.class);
		List<Teachers> teacher = mapper.getTeacher();
		for(Teacher teacher:teachers){
			System.out.println(teacher);
		}
		sqlSession.close();
	}
	@Test
	public void test(){
		SqlSession sqlSession = MybatisUtils.getSqlSession();
		TeacherMapper mapper = sqlSession.getMapper(TeacherMapper.class);
		Teacher teacher = mapper.getTeacher(1);
		System.out.println(teacher);
		
		sqlSession.close();
	}
}

Summary:
association: many to one----------------
Collection: collection one to many
javaType & ofType
javaType is used to specify the type of attribute in the entity class
ofType is used to specify the pojo type mapped to the List or collection, and the constraint type in the generic type;
Note: ensure the readability of sql and make it easy to understand
Note the problem of attribute names and fields in one to many and many to one
If the problem is difficult to troubleshoot, log can be used. log4j is recommended

Posted by MNS on Tue, 12 Oct 2021 17:59:49 -0700