I want to work with myBatis. I have read MyBatis-3-user-guide. Now i am trying to implement it. Recently i have learned spring. So it is difficult for me to implement it. So i need some helpful resource by which i can implement it step by step.
Add the MyBatis-Spring jar in your class path at first
Start with your spring context file.In your context file add following lines
<beans:bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource"
p:driverClassName="yourDriverClassName"
p:url="yourUrl"
p:username="yourUsername"
p:password="yourPassword" />
<beans:bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<beans:property name="dataSource" ref="dataSource" />
<beans:property name="configLocation" value="/WEB-INF/mybatis-config.xml" />
</beans:bean>
<beans:bean id="userDao" class="com.yourcomp.dao.Userdao">
<beans:property name="sqlSessionFactory" ref="sqlSessionFactory" />
</beans:bean>
your mybatis-config.xml should be something like this:
<?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>
</settings>
<typeAliases>
<typeAlias alias="User" type ="com.yourcomp.domain.User" />
</typeAliases>
<mappers>
<mapper resource="com/yourcomp/domain/UserMapper.xml"/>
<mapper resource="com/yourcomp/domain/AnotherDomainObjectMapper.xml"/>
</mappers>
</configuration>
and your userMapper.xml in src/com/yourcomp/domain/ might be something like this
<?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="org.pbl.rms.RMSUserDao">-->
<mapper namespace="com.yourcomp.domain.User">
<resultMap id="userMap" type="User">
<id property="userId" column="USER_ID" javaType="int" jdbcType="NUMERIC"/>
<result property="userName" column="USER_NAME" javaType="String" jdbcType="VARCHAR"/>
<result property="userFullName" column="USER_FULL_NAME" javaType="String" jdbcType="VARCHAR"/>
<result property="password" column="PASSWORD" javaType="String" jdbcType="VARCHAR"/>
<result property="passwordExpiryDate" column="PASWRD_EXPIRY_DATE" javaType="java.util.Date" jdbcType="DATE"/>
<result property="status" column="STATUS" javaType="_integer" jdbcType="DECIMAL"/>
</resultMap>
<select id="getUserById" parameterType="map" resultMap="userMap">
select * from user where USER_ID=#{userId}
</select>
</mapper>
now in your DAO layer you might have class like follows:
public class UserDAO{
private SqlSessionFactory sqlSessionFactory;
public UserDAO() {
}
public UserDAO(SqlSessionFactory sqlSessionFactory ) {
this.sqlSessionFactory = sqlSessionFactory;
}
public String getUserById(Integer userId) {
SqlSession session = sqlSessionFactory.openSession();
String name=null;
try {
name = (String)session.selectOne("com.yourcomp.domain.User.getUserById",userId);
}catch(Exception e){
}finally {
session.close();
}
return name;
}
}
You need MyBatis-Spring for this . See the reference here and here These provide you the step by step configs . If you need any specific details , you need to re frame your query .
Also check the spring reference for IBatis support.
Related
I follow mybatis official website to build my project step by step, but it always can not work well, so I hope you could give me a fully guide from beginning to the end, many thanks.
Step 1. Build a new spring boot project named booking.
This step is basically, I will skip it.
Step 2. Add mybatis-generator to project.
This could help us to generate entity and mapper class mybatis needed automatically, it's very useful for us to save our time.
Add plugin config in pom.xml
<plugin>
<groupId>org.mybatis.generator</groupId>
<artifactId>mybatis-generator-maven-plugin</artifactId>
<version>1.3.5</version>
<dependencies>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>6.0.6</version>
</dependency>
</dependencies>
</plugin>
Create generatorConfig.xml at base resources path.
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE generatorConfiguration
PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"
"http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">
<generatorConfiguration>
<context id="MySqlContext" targetRuntime="MyBatis3Simple" defaultModelType="flat">
<jdbcConnection driverClass="com.mysql.cj.jdbc.Driver"
connectionURL="jdbc:mysql://localhost:3306/booking?useSSL=false"
userId="root"
password="123456">
<property name="nullCatalogMeansCurrent" value="true" />
</jdbcConnection>
<javaModelGenerator targetPackage="com.clycle.booking.entity" targetProject="C:\Users\a243903\projects\booking\webapi\src\main\java">
<property name="enableSubPackages" value="true" />
<property name="trimStrings" value="true" />
</javaModelGenerator>
<sqlMapGenerator targetPackage="com.clycle.booking.mapper" targetProject="C:\Users\a243903\projects\booking\webapi\src\main\resources">
<property name="enableSubPackages" value="true" />
</sqlMapGenerator>
<javaClientGenerator type="XMLMAPPER" targetPackage="com.clycle.booking.mapper" targetProject="C:\Users\a243903\projects\booking\webapi\src\main\java">
<property name="enableSubPackages" value="true" />
</javaClientGenerator>
<table tableName="%">
</table>
</context>
</generatorConfiguration>
Create maven Run/Debug Configuration to run this plugin.
It will generate all entity, mapper class and mapper xml automatically. -Dmybatis.generator.overwrite=true, means it will overwrite existing entity or mapper class when run mybatis generator with maven.
Step 3. Add mybatis to this project.
Add mybatis dependency in pom.xml
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>1.3.1</version>
</dependency>
Create mybatis-config.xml at base resources path.
<?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>
<setting name="logImpl" value="LOG4J" />
</settings>
<typeAliases>
<package name="com.clycle.booking.entity" />
</typeAliases>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC">
<property name="" value="" />
</transactionManager>
<dataSource type="UNPOOLED">
<property name="driver" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://localhost:3306/booking" />
<property name="username" value="root" />
<property name="password" value="123456" />
</dataSource>
</environment>
</environments>
<mappers>
<package name="com.clycle.booking.mapper" />
<!--<mapper resource="com/clycle/booking/mapper/ShopMapper.xml" />-->
</mappers>
</configuration>
Add #MapperScan for application main class.
#SpringBootApplication
#MapperScan({"com.clycle.booking.mapper"})
public class BookingApplication {
public static void main(String[] args) {
SpringApplication.run(BookingApplication.class, args);
}
}
Autowired mapper interface to operate your database.
#Autowired
private ShopMapper shopMapper;
#PostMapping(RoutePath.SHOP_LIST)
public List<Shop> GetList() {
try {
return shopMapper.selectAll();
} catch (Exception ex) {
return null;
}
}
You can download this project: https://github.com/yyqian/spring-boot-mybatis-generator .
Everything just work fine on my computer.
I have one "Hello word" application on spring AOP and configured by XML, it looks like this:
public class CustomerBoImpl {
public CustomerBoImpl() {
super();
}
protected void addCustomer(){
System.out.println("addCustomer() is running ");
}
}
public class App {
public static void main(String[] args) throws Exception {
ApplicationContext appContext =
new ClassPathXmlApplicationContext("Spring-Customer.xml");
CustomerBoImpl customer =
(CustomerBoImpl) appContext.getBean("customerBo");
customer.addCustomer();
}
}
My spring configuration looks like this:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd ">
<aop:aspectj-autoproxy />
<!-- this switches on the load-time weaving -->
<context:load-time-weaver aspectj-weaving="on" />
<bean id="customerBo" class="com.mkyong.saad.CustomerBoImpl"
scope="singleton" />
<!-- Aspect -->
<bean id="logAspect" class="com.mkyong.saad.LoggingAspect" />
<aop:config>
<aop:aspect id="aspectLoggging" ref="logAspect">
<!-- #Before -->
<aop:pointcut id="pointCutBefore"
expression="execution(* com.mkyong.saad.CustomerBoImpl.addCustomer(..))" />
<aop:before method="logBefore" pointcut-ref="pointCutBefore" />
<!-- #After -->
<aop:pointcut id="pointCutAfter"
expression="execution(* com.mkyong.saad.CustomerBoImpl.addCustomer(..))" />
<aop:after method="logAfter" pointcut-ref="pointCutAfter" />
</aop:aspect>
</aop:config>
that doesn't work because of protected method, so I tried to use load time weaving with aop.xml like this:
<?xml version="1.0" encoding="UTF-8"?>
<aspectj>
<weaver>
<!-- only weave classes in our application-specific packages -->
<include within="com.mkyong.saad.*"/>
</weaver>
<aspects>
<!-- weave in just this aspect -->
<aspect name="com.mkyong.saad.LoggingAspect"/>
</aspects>
</aspectj>
Source code for the aspect:
public class LoggingAspect {
public void logBefore(JoinPoint joinPoint) {
System.out.println("logBefore() is running!");
System.out.println("hijacked : " + joinPoint.getSignature().getName());
System.out.println("******");
}
public void logAfter(JoinPoint joinPoint) {
System.out.println("logAfter() is running!");
System.out.println("hijacked : " + joinPoint.getSignature().getName());
System.out.println("******");
}
}
but it doesn't work, only if I change to annotation config. SOS PLZ
removing the following code in your aop.xml, then run your jvm with args like this: -javaagent:"yourpath/spring-instrument-***.jar"
<weaver>
<!-- only weave classes in our application-specific packages -->
<include within="com.mkyong.saad.*"/>
</weaver>
We have written a custom Http-client for spring XD and planning to use this custom processor for invoking different APIs. However, We have a situation where we need to invoke two different API based on the payload. Apart from using dynamic-router (which writes to a named channel) is there a way we can set the URL dynamically for the http-client to invoke? Here is the current configuration.
<header-filter input-channel="input" output-channel="inputX"
header-names="x-death" />
<service-activator input-channel="inputX" ref="gw" />
<gateway id="gw" default-request-channel="toHttp"
default-reply-timeout="0" error-channel="errors" />
<beans:bean id="inputfields"
class="com.batch.httpclient.HTTPInputProperties">
<beans:property name="nonRetryErrorCodes" value="${nonRetryErrorCodes}" />
</beans:bean>
<beans:bean id="responseInterceptor"
class="com.batch.httpclient.ResponseInterceptor">
<beans:property name="inputProperties" ref="inputfields" />
</beans:bean>
<chain input-channel="errors" output-channel="output">
<transformer ref="responseInterceptor" />
</chain>
<int-http:outbound-gateway id='batch-http'
header-mapper="headerMapper" request-channel='toHttp' url-expression="${url}"
http-method="${httpMethod}" expected-response-type='java.lang.String'
charset='${charset}' reply-timeout='${replyTimeout}' reply-channel='output'>
</int-http:outbound-gateway>
<beans:bean id="headerMapper"
class="org.springframework.integration.http.support.DefaultHttpHeaderMapper"
factory-method="outboundMapper">
<beans:property name="outboundHeaderNames" value="*" />
<beans:property name="userDefinedHeaderPrefix" value="" />
</beans:bean>
<channel id="output" />
<channel id="input" />
<channel id="inputX" />
<channel id="toHttp" />
If it's based on the payload type, something like this should work...
url-expression="payload.getClass().getSimpleName().equals("Bar") ? 'http://foo/bar' : 'http://foo/baz'"
If it's a property on the payload, then
url-expression="payload.foo.equals("bar") ? 'http://foo/bar' : 'http://foo/baz'"
EDIT
or
url-expression="payload.foo.equals("bar") ? '${url1}' : '${url2}'"
This would need changing the property metadata class to rename url and add url2.
I'm trying to use display tag library in my project.
JSP:
<display:table name="rooms" class="table table-striped" pagesize="5">
<display:column property="name" titleKey="crs.admin.room.roomName" sortable="true" />
<display:column property="capacity" />
</display:table>
Controller:
#Controller
public class RoomController {
....
#RequestMapping(value = "/roomManagement*", method = RequestMethod.GET)
public ModelAndView get() {
ModelAndView modelAndView = new ModelAndView();
modelAndView.setViewName("roomManagement");
modelAndView.addObject("rooms", roomService.findAll());
return modelAndView;
}
View resolver:
<bean id="jspViewResolver"
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="viewClass"
value="org.springframework.web.servlet.view.JstlView"/>
<property name="prefix" value=""/>
<property name="suffix" value=".jsp"/>
</bean>
When i opening page with it my link looks like:
http://localhost:8081/roomManagement
But after click on pagination/sort link it looks like:
http://localhost:8081/roomManagement.jsp?d-49653-s=0&d-49653-o=2
And becouse of ".jsp" suffix my controller doesnt handle this request, and doesnt put rooms list into view.
How should i handle it?
Ok it was really simple, ive added
requestURI="/roomManagement"
parameter to display:table tag
I try to use the new POCO capabilities of EF 4.0 in combination with the EFOracleProvider. I have recompiled the EFOracleProvider (using ODAC instead of System.Data.OracleClient) to target the .NET Framework 4 (und put it in the 4.0 GAC). Everything ok so far.
I host the Entity Model in a WCF Data Service:
class DivaDispoDataService : DataService<DivaDispoContainer>
{
public static void InitializeService(IDataServiceConfiguration config)
{
config.SetEntitySetAccessRule("*", EntitySetRights.All);
config.SetServiceOperationAccessRule("*", ServiceOperationRights.All);
}
}
My EDMX File looks like this:
<?xml version="1.0" encoding="utf-8"?>
<edmx:Edmx Version="2.0" xmlns:edmx="http://schemas.microsoft.com/ado/2008/10/edmx">
<!-- EF Runtime content -->
<edmx:Runtime>
<!-- SSDL content -->
<edmx:StorageModels>
<Schema xmlns="http://schemas.microsoft.com/ado/2009/02/edm/ssdl" xmlns:store="http://schemas.microsoft.com/ado/2007/12/edm/EntityStoreSchemaGenerator" Namespace="DivaDispo.Store" Alias="Self" Provider="EFOracleProvider" ProviderManifestToken="10g">
<EntityContainer Name="DivaDispoStoreContainer">
<EntitySet Name="DIW_USER" EntityType="DivaDispo.Store.DIW_USER" store:Type="Tables" Schema="" />
</EntityContainer>
<EntityType Name="DIW_USER">
<Key>
<PropertyRef Name="IDX" />
</Key>
<Property Name="IDX" Type="number" Nullable="false" Precision="10" />
<Property Name="USERNAME" Type="number" Precision="10" />
<Property Name="PERSONNELNUMBER" Type="number" Precision="10" />
<Property Name="PASSWORD" Type="varchar2" MaxLength="10" />
<Property Name="ACTIVATED" Type="number" Precision="1" />
<Property Name="ROLE" Type="number" Precision="1" />
</EntityType>
</Schema>
</edmx:StorageModels>
<!-- CSDL content -->
<edmx:ConceptualModels>
<Schema xmlns="http://schemas.microsoft.com/ado/2008/09/edm" xmlns:cg="http://schemas.microsoft.com/ado/2006/04/codegeneration" xmlns:store="http://schemas.microsoft.com/ado/2007/12/edm/EntityStoreSchemaGenerator" Namespace="DivaDispo.Model" Alias="Self" xmlns:annotation="http://schemas.microsoft.com/ado/2009/02/edm/annotation">
<EntityContainer Name="DivaDispoContainer" annotation:LazyLoadingEnabled="false">
<EntitySet Name="User" EntityType="DivaDispo.Model.User" />
</EntityContainer>
<EntityType Name="User">
<Key>
<PropertyRef Name="ID" />
</Key>
<Property Name="ID" Type="Decimal" Nullable="false" Precision="10" Scale="0" />
<Property Name="Username" Type="Decimal" Precision="10" Scale="0" />
<Property Name="PersonnelNumber" Type="Decimal" Precision="10" Scale="0" />
<Property Name="Password" Type="String" MaxLength="10" Unicode="false" FixedLength="false" />
<Property Name="Activated" Type="Boolean" />
<Property Name="Role" Type="Boolean" />
</EntityType>
</Schema>
</edmx:ConceptualModels>
<!-- C-S mapping content -->
<edmx:Mappings>
<Mapping xmlns="http://schemas.microsoft.com/ado/2008/09/mapping/cs" Space="C-S">
<EntityContainerMapping StorageEntityContainer="DivaDispoStoreContainer" CdmEntityContainer="DivaDispoContainer">
<EntitySetMapping Name="User">
<EntityTypeMapping TypeName="IsTypeOf(DivaDispo.Model.User)">
<MappingFragment StoreEntitySet="DIW_USER">
<ScalarProperty Name="ID" ColumnName="IDX" />
<ScalarProperty Name="Username" ColumnName="USERNAME" />
<ScalarProperty Name="PersonnelNumber" ColumnName="PERSONNELNUMBER" />
<ScalarProperty Name="Password" ColumnName="PASSWORD" />
<ScalarProperty Name="Activated" ColumnName="ACTIVATED" />
<ScalarProperty Name="Role" ColumnName="ROLE" />
</MappingFragment>
</EntityTypeMapping>
</EntitySetMapping>
</EntityContainerMapping>
</Mapping>
</edmx:Mappings>
</edmx:Runtime>
</edmx:Edmx>
My POCO Class looks like this:
public partial class User
{
public virtual decimal ID { get; set; }
public virtual Nullable<decimal> Username { get; set; }
public virtual Nullable<decimal> PersonnelNumber { get; set; }
public virtual string Password { get; set; }
public virtual Nullable<bool> Activated { get; set; }
public virtual Nullable<bool> Role { get; set; }
}
and the DataContext like this:
public partial class DivaDispoContainer : ObjectContext
{
public const string ConnectionString = "name=DivaDispoContainer";
public const string ContainerName = "DivaDispoContainer";
#region Constructors
public DivaDispoContainer()
: base(ConnectionString, ContainerName)
{
this.ContextOptions.LazyLoadingEnabled = false;
}
public DivaDispoContainer(string connectionString)
: base(connectionString, ContainerName)
{
this.ContextOptions.LazyLoadingEnabled = false;
}
public DivaDispoContainer(EntityConnection connection)
: base(connection, ContainerName)
{
this.ContextOptions.LazyLoadingEnabled = false;
}
#endregion
#region ObjectSet Properties
public ObjectSet<User> User
{
get { return _user ?? (_user = CreateObjectSet<User>("User")); }
}
private ObjectSet<User> _user;
}
The POCO classes and the DataContext are generated with the POCO Template from Visual Studio 2010.
When I start my WCF Service and want to query the users I receive an System.Data.Services.DataServiceException which says somtihng like
500: Internal Server error. The type 'System.Data.Entity.DynamicProxies.User_057822846B2B8DD7BB03058490B27D19E6C634EACF33438FE886 19C8BBB1CF74' is not a komplex type or entity type.
When I look in the dubgger I can see that the values have been read from the database (therefore I think the EFOracleProvider works ok) and that the DynamicProxies.User_.... is derrived from my User class (which contains at that point the data from the database). So the question is: Why do I receive this exception? Does anyone know whats going on there? What's the DynamicProxies.User_.... automaic generated class for? The Exception is thrown in the Method GetNonPrimitiveResourceType of the class WebUtil. Or maybe I have something overlooked?
Any help greatly appreciated....
The link from Craig to the blog post http://msdn.microsoft.com/en-us/library/ee705457.aspx revealed the answer. It states there that
The POCO proxy type cannot be directly serialized or deserialized by WCF
and that is exactly my problem. If I remove the virtual from the properties of the genrated POCO class the runtime doesnt generate the proxy types and the exception dissapears.
Thanks again for the link, Craig.