我正在开发一个新的Java Web应用程序,我正在探索新的方法(对我来说是新的!)来保存数据.我主要有JPA和Hibernate的经验,但除了简单的情况,我认为这种完整的ORM会变得非常复杂.另外,我不喜欢和他们一起工作.我正在寻找一种新的解决方案,可能更接近SQL.
我正在调查的解决方案:
但与Hibernate相比,我有两个使用案例,我担心这些解决方案.我想知道这些用例的推荐模式是什么.
Person实体.
Person有一个相关的Address实体.
Address有一个相关的City实体.
City实体有一个name属性.从人员实体开始,访问城市名称的完整路径是:
person.address.city.name
Run Code Online (Sandbox Code Playgroud)
现在,假设我PersonService使用以下方法从a加载Person实体:
public Person findPersonById(long id)
{
// ...
}
Run Code Online (Sandbox Code Playgroud)
使用Hibernate,Person可以根据需要延迟加载与之关联的实体,因此可以访问person.address.city.name并确保我可以访问此属性(只要该链中的所有实体都不可为空).
但是使用我正在研究的3种解决方案中的任何一种,它都会更复杂.有了这些解决方案,有哪些推荐的模式来处理这个用例?在前面,我看到3种可能的模式:
可以通过所使用的SQL查询急切地加载所有必需的关联子孙实体.
但是我在这个解决方案中看到的问题是,可能还有一些其他代码需要从实体访问其他实体/属性路径Person.例如,可能需要访问一些代码person.job.salary.currency.如果我想重用findPersonById()我已经拥有的方法,那么SQL查询将需要加载更多信息!不仅是相关address->city实体,还包括相关job->salary实体.
现在如果还有10个其他地方需要从人员实体开始访问其他信息呢?我是否应该急切地加载所有可能需要的信息?或者可能有12种不同的服务方法来加载一个人实体?:
findPersonById_simple(long id)
findPersonById_withAdressCity(long id)
findPersonById_withJob(long id)
findPersonById_withAdressCityAndJob(long id)
...
Run Code Online (Sandbox Code Playgroud)
但是每当我使用一个Person实体时,我就必须知道装载它的是什么以及什么没有...它可能非常麻烦,对吧? …
我正在尝试@Select在MyBatis中定义一个简单的注释,以根据IN子句定义的条件获取对象的集合.SQL看起来像:
SELECT * FROM employees WHERE employeeID IN (1, 2, 3);
Run Code Online (Sandbox Code Playgroud)
该列表是动态生成的,因此我不知道它将包含多少参数.我想传递一个List值,例如:
@Select("SELECT * FROM employees WHERE employeeID IN( #{employeeIds} )")
List<Employee> selectSpecificEmployees(@Param("employeeIds") List<Integer> employeeIds);
Run Code Online (Sandbox Code Playgroud)
我正在创建一个Mapper定义上面注释的实例,并按如下方式调用它:
List<Integer> empIds = Arrays.asList(1, 2, 3);
List<Employee> result = mapper.selectSpecificEmployees(empIds);
Run Code Online (Sandbox Code Playgroud)
我发现这不起作用.
org.apache.ibatis.exceptions.PersistenceException:
###查询数据库时出错.原因:java.lang.NullPointerException
###错误可能涉及
com.mycompany.MySourceMapper.selectSpecificEmployees-Inline
###设置参数时发生错误###原因:org.apache.ibatis.exceptions中的java.lang.NullPointerException位于org.apache.ibatis.session.defaults.DefaultSqlSession.select上的org.apache.ibatis.session.defaults.DefaultSqlSession.selectList(DefaultSqlSession.java:77)的.ExceptionFactory.wrapException(ExceptionFactory.java:8)(DefaultSqlSession.java) :69)org.apache.ibatis.binding.binperMethod.executeForList(MapperMethod.java:85)位于org.apache.ibatis.binding的org.apache.ibatis.binding.MapperMethod.execute(MapperMethod.java:65).位于sun.reflect的sun.reflect.NativeMethodAccessorImpl.invoke0(本地方法)的com.mycompany.MySourceMapperDebug.testSelectSpecificEmployees(MySourceMapperDebug.java:60)处的$ Proxy23.selectSpecificProductTypes(未知来源)的MapperProxy.invoke(MapperProxy.java:35) sun.reflect中的.NativeMethodAccessorImpl.invoke(未知来源).在junit.framework.TestCase.runBare(testCase.java:127)的junit.framework.TestCase.runTest(TestCase.java:154)的java.lang.reflect.Method.invoke(未知来源)中委托MethodAethodAccessorImpl.invoke(未知来源) )在junit.framework.TestResult $ 1.protect(TestResult.java:106)的junit.framework.TestResult.runProtected(TestResult.java:124)junit.framework.TestResult.run(TestResult.java:109)junit. framework.TestCase.run(TestCase.java:118)位于junit.framework.TestSuite.runTest(TestSuite.java:208),位于org.eclipse.jdt.internal的junit.framework.TestSuite.run(TestSuite.java:203)位于org.eclipse.jdt.internal.junit的org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)的.junit.runner.junit3.JUnit3TestReference.run(JUnit3TestReference.java:130) .runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)atg.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)org.eclipse.jdt.internal.junit.runner.RemoteTestRunner .RUN(RemoteTestRu nner.java:390)at or.e.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)引起:org.apache.ibatis.type.UnknownTypeHandler.setNonNullParameter的java.lang.NullPointerException( UnknownTypeHandler.java:21)atg.apache.ibatis.type.BaseTypeHandler.setParameter(BaseTypeHandler.java:23)atg.apache.ibatis.executor.parameter.DefaultParameterHandler.setParameters(DefaultParameterHandler.java:73)org.apache位于org.apache.ibatis.executor.SimpleExecutor.prepareStatement的org.apache.ibatis.executor.statement.RoutingStatementHandler.parameterize(RoutingStatementHandler.java:43)中的.ibatis.executor.statement.PreparedStatementHandler.parameterize(PreparedStatementHandler.java:61) (SimpleExecutor.java:56)位于org.apache的org.apache.ibatis.executor.SimpleExecutor.doQuery(SimpleExecutor.java:40)org.apache.ibatis.executor.BaseExecutor.queryFromDatabase(BaseExecutor.java:216). org.apache.ibatis.executor上的ibatis.executor.BaseExecutor.query(BaseExecutor.java:95).cachingExecutor.query(CachingExecutor.java:72)at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)at java. org.apache.ibatis.plugin.Invocation.proceed(Invocation.java:31)中的lang.reflect.Method.invoke(未知来源)
... 36更多
我认为问题在于注释本身.这似乎是一个相当普遍的要求.我是否需要将其转换List为String自己并将其作为String参数传递而不是List<Integer> …
如何使用MyBatis获取插入的生成密钥?我读了很多关于这个问题的网页,但我仍然被封锁,有人可以帮帮我吗?这是我的代码:
桌子:
ID_ERROR long primary key
DATE timestamp
TYPE varchar
MESSAGE varchar
SOURCE varchar
Run Code Online (Sandbox Code Playgroud)
道:
Long returnedId = 0L;
MyMapper myMapper = this.sqlSession.getMapper(MyMapper.class);
myMapper.insertRecord(returnedId, Utils.now(), t.getClass().getName(), t.getMessage(), c.getName());
return returnedId;
Run Code Online (Sandbox Code Playgroud)
mapper.java:
public void insertRecord(@Param("returnedId") Long returnedId, @Param("timestamp")Timestamp timestamp,@Param("type") String type,@Param("message") String message,@Param("source") String source);
Run Code Online (Sandbox Code Playgroud)
mapper.xml
<insert id="insertRecord" parameterType="map" useGeneratedKeys="true" keyProperty="ID_ERROR">
INSERT INTO errors (
DATE,
TYPE,
MESSAGE,
SOURCE
)
VALUES (
#{timestamp},
#{type},
#{message},
#{source}
)
<selectKey resultType="long" order="AFTER" keyProperty="returnedId">
SELECT LAST_INSERT_ID() as returnedId
</selectKey>
</insert>
Run Code Online (Sandbox Code Playgroud)
怎么了?如何获取此插入的生成密钥?谢谢!
iBatis和myBatis有什么区别?我在哪里可以找到一个完美的例子?请建议.我通过谷歌找不到这个问题的链接.
我们只想使用MyBatis的注释; 我们真的想避免使用xml.我们正在尝试使用"IN"子句:
@Select("SELECT * FROM blog WHERE id IN (#{ids})")
List<Blog> selectBlogs(int[] ids);
Run Code Online (Sandbox Code Playgroud)
MyBatis似乎无法选择整数数组并将其放入生成的查询中.它似乎"软弱地失败",我们没有得到任何结果.
看起来我们可以使用XML映射来实现这一点,但我们真的想避免这种情况.是否有正确的注释语法?
我有一个dataSource,我使用Spring 3.0.3,Hibernate 3.5.1作为JPA提供程序,我使用MyBatis 3.0.2进行一些查询,我的应用程序在Tomcat 6上运行.我有一个HibernateDAO和一个MyBatisDAO,当我同时调用它们时从使用@Transactional注释的相同方法看起来它们不共享相同的事务,它们获得不同的连接.
我怎么能让他们这样做?
我已经尝试从DataSourceUtils.getConnection(dataSource)获取连接,我得到了MyBatis使用的连接,这很奇怪我认为问题出在MyBatis配置中,它不能使用JpaTransactionManager.甚至多次调用DataSoruceUtils.getConnection总是给出相同的连接,这没关系.
经过一些谷歌搜索后我尝试了spring-instrument-tomcat的类加载器(虽然我不知道tomcat是否真的使用它:))
部分applicationContext
<bean class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close" id="dataSource">
<property name="driverClassName" value="${database.driverClassName}"/>
<property name="url" value="${database.url}"/>
<property name="username" value="${database.username}"/>
<property name="password" value="${database.password}"/>
</bean>
<bean class="org.springframework.orm.jpa.JpaTransactionManager" id="transactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory"/>
</bean>
<tx:annotation-driven mode="aspectj" transaction-manager="transactionManager"/>
<bean class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean" id="entityManagerFactory">
<property name="dataSource" ref="dataSource"/>
</bean>
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="configLocation" value="classpath:META-INF/mybatis/mybatis-config.xml" />
</bean>
Run Code Online (Sandbox Code Playgroud)
部分mybatis配置
<settings>
<setting name="cacheEnabled" value="false" />
<setting name="useGeneratedKeys" value="false" />
<setting name="defaultExecutorType" value="REUSE" />
<setting name="lazyLoadingEnabled" value="false"/>
</settings>
Run Code Online (Sandbox Code Playgroud)
部分persistence.xml
<persistence-unit name="persistenceUnit" transaction-type="RESOURCE_LOCAL">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
Run Code Online (Sandbox Code Playgroud) 我想使用spring mvc @modelAttribute在我的Jsp页面中显示类别列表.
在我的mapper.xml文件中
<select id="selectAllCategories" resultMap="BaseResultMap">
select id, name from categories
</select>
Run Code Online (Sandbox Code Playgroud)
在我的Mapper.java类中,我有方法
List<Map<String, String>> selectAllCategories();
Run Code Online (Sandbox Code Playgroud)
我想要一个像这样的方法:
Map<Integer, String>`selectAllCategories();
Run Code Online (Sandbox Code Playgroud)
而不是List<Map<>>,这可能吗?
我的Mybatis中有一个包含IN子句的查询,它基本上是一组Id(整数)
我现在停留在如何将一个Integer数组传递给这个IN子句,以便它提取正确的记录.通过将包含ID的String传递给IN子句,但这没有按预期工作.
代码示例如下
使用注释的Mybatis方法
@Select(SEL_QUERY)
@Results(value = {@Result(property="id",column="ID")})
List<Integer> getIds(@Param("usrIds") Integer[] usrIds);
Run Code Online (Sandbox Code Playgroud)
询问
select distinct ID from table a where a.id in ( #{usrIds} )
Run Code Online (Sandbox Code Playgroud)
方法调用
Integer[] arr = new Integer[2];
arr[0] = 1;
arr[1] = 2;
mapper.getIds(arr)
Run Code Online (Sandbox Code Playgroud)
这不起作用,当我调用mapper方法时,Mybatis会抛出一个错误
请给我任何建议
我在mybatis上使用mysql,我在我们的实时服务器上遇到这个错误
com.mchange.v2.async.ThreadPoolAsynchronousRunner$DeadlockDetector@6538f8f2
-- APPARENT DEADLOCK!!! Creating emergency threads for unassigned pending tasks!
Run Code Online (Sandbox Code Playgroud)
我不明白为什么这个错误会因为我的C3P0设置而来?我的C3P0设置是这样的
----开始更新-----
下面是我的spring-servlet.xml配置
我将 datasource bean 更新为
<bean id="datasource" class="com.mchange.v2.c3p0.ComboPooledDataSource"
destroy-method="close" p:driverClass="com.mysql.jdbc.Driver"
p:jdbcUrl="jdbc:mysql://localhost/jdb" p:user="root" p:password="root"
p:acquireIncrement="10"
p:idleConnectionTestPeriod="60"
p:maxPoolSize="100"
p:maxStatements="0"
p:minPoolSize="10"
p:initialPoolSize="10"
p:statementCacheNumDeferredCloseThreads="1" />
<!-- Declare a transaction manager -->
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager"
p:dataSource-ref="datasource" />
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="datasource" />
</bean>
<!-- scan for mappers and will automatically scan the whole classpath for xmls -->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="sqlSessionFactory" ref="sqlSessionFactory" />
<property name="basePackage" value="com.mycom.myproject.db.mybatis.dao" /> …Run Code Online (Sandbox Code Playgroud) 我想将我的几个SQL Map XML文件使用的sql片段放在一个单独的文件中.目前,<sql>具有这些片段的元素与其他元素一起位于其中一个元素中<select>,这使得它们很难找到.
我是否可以使用仅定义几个<sql>元素的映射器,而不是用于生成接口的实现?这个映射器的正确名称空间是什么?
这是包含framents的SQL Map文件:
<mapper namespace="com.company.project.dao.someDao">
<sql id="whereDate">
WHERE date(`time`) BETWEEN #{startDate} AND #{endDate}
</sql>
<sql id="someOtherSqlFragment">
...
</sql>
<select id="getSomeData"
resultType="SomeClass"
parameterType="DateParam" >
SELECT some_column, another_column
</select>
FROM some_table
<include refid="whereDate"/>
<include refid="otherSqlFragment"/>
</select>
</mapper>
Run Code Online (Sandbox Code Playgroud)
我想分开这样的元素:
第一个Sql Map文件:
<mapper namespace="com.company.project.dao.???">
<sql id="whereDate">
WHERE date(`time`) BETWEEN #{startDate} AND #{endDate}
</sql>
<sql id="someOtherSqlFragment">
...
</sql>
</mapper>
Run Code Online (Sandbox Code Playgroud)
第二个Sql Map文件:
<mapper namespace="com.company.project.dao.someDao">
<select id="getSomeData"
resultType="SomeClass"
parameterType="DateParam" >
SELECT some_column, another_column
</select>
FROM some_table
<include refid="whereDate"/> …Run Code Online (Sandbox Code Playgroud) mybatis ×10
java ×8
ibatis ×4
mysql ×2
annotations ×1
hibernate ×1
insert ×1
java-ee ×1
jdbc ×1
jooq ×1
jpa ×1
spring ×1
spring-mvc ×1
sql ×1
transactions ×1